]> git.tdb.fi Git - libs/al.git/blob - source/sound.cpp
Add Streamer class
[libs/al.git] / source / sound.cpp
1 /* $Id$
2
3 This file is part of libmspal
4 Copyright © 2008 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <cstring>
9 #include <msp/core/except.h>
10 #include "sound.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace AL {
16
17 Sound::Sound():
18         data(0),
19         eof_flag(false)
20 {
21         ovfile.datasource=0;
22 }
23
24 Sound::Sound(const std::string &fn):
25         data(0),
26         eof_flag(false)
27 {
28         ovfile.datasource=0;
29         open(fn);
30 }
31
32 Sound::~Sound()
33 {
34         delete data;
35         if(ovfile.datasource)
36                 ov_clear(&ovfile);
37 }
38
39 void Sound::open(const string &fn)
40 {
41         if(ovfile.datasource)
42                 throw InvalidState("Sound has already been opened");
43         if(ov_fopen(const_cast<char *>(fn.c_str()), &ovfile)<0)
44                 throw Exception("Could not open ogg vorbis file "+fn);
45
46         delete data;
47         data=0;
48
49         vorbis_info *info=ov_info(&ovfile, -1);
50         freq=info->rate;
51         switch(info->channels)
52         {
53         case 1: format=MONO16; break;
54         case 2: format=STEREO16; break;
55         default: throw Exception("Unsupported number of channels");
56         }
57 }
58
59 void Sound::load_data()
60 {
61         if(data)
62                 throw InvalidState("Data has already been loaded");
63
64         size=ov_pcm_total(&ovfile, 0)*4;
65         char *dptr=new char[size];
66         unsigned pos=0;
67         while(unsigned len=read(dptr+pos, size-pos))
68                 pos+=len;
69         data=dptr;
70         size=pos;
71 }
72
73 void Sound::load(const string &fn)
74 {
75         open(fn);
76         load_data();
77         close();
78 }
79
80 void Sound::close()
81 {
82         if(ovfile.datasource)
83                 ov_clear(&ovfile);
84 }
85
86 void Sound::rewind()
87 {
88         if(data)
89                 read_pos=0;
90         else
91                 ov_pcm_seek(&ovfile, 0);
92 }
93
94 unsigned Sound::read(char *buf, unsigned len)
95 {
96         if(data)
97         {
98                 len=min(len, size-read_pos);
99                 memcpy(buf, data+read_pos, len);
100                 read_pos+=len;
101                 return len;
102         }
103         else if(ovfile.datasource)
104         {
105                 int section=0;
106                 int res=ov_read(&ovfile, buf, len, 0, 2, 1, &section);
107                 if(res<0)
108                         throw Exception("Error reading ogg vorbis file");
109                 else if(res==0)
110                         eof_flag=true;
111                 return res;
112         }
113         else
114                 throw InvalidState("No data available");
115 }
116
117 const char *Sound::get_data() const
118 {
119         if(!data)
120                 throw InvalidState("Data has not been loaded");
121         return data;
122 }
123
124 } // namespace AL
125 } // namespace Msp