Line data Source code
1 : #include "Music.h"
2 :
3 : // Music()
4 : //
5 : // Class constructor.
6 58 : Music::Music() {
7 29 : Playing = false;
8 29 : Repeat = false;
9 29 : initialized_ = false;
10 58 : }
11 :
12 : // ~Music()
13 : //
14 : // Class destructor.
15 58 : Music::~Music() {
16 29 : unload();
17 58 : }
18 :
19 : // load()
20 : //
21 : // Sets up OpenAL and initialized state flags.
22 9 : void Music::load() {
23 9 : if (initialized_)
24 0 : return;
25 :
26 9 : alGenBuffers( 2, Buffers );
27 9 : ALenum errorCode = alGetError();
28 9 : if (errorCode != AL_NO_ERROR) {
29 9 : PRINT_ERROR("Could not generate buffers; AL error code: '%d'.\n", errorCode);
30 9 : return;
31 : }
32 :
33 0 : alGenSources( 1, &Source );
34 0 : errorCode = alGetError();
35 0 : if (errorCode != AL_NO_ERROR) {
36 0 : PRINT_ERROR("Could not generate sources; AL error code: '%d'.\n", errorCode);
37 0 : return;
38 : }
39 :
40 0 : alSource3f( Source, AL_POSITION, 0.0f, 0.0f, 0.0f );
41 0 : errorCode = alGetError();
42 0 : if (errorCode != AL_NO_ERROR) {
43 0 : PRINT_ERROR("Could not set source position; AL error code: '%d'.\n", errorCode);
44 0 : return;
45 : }
46 :
47 0 : initialized_ = true;
48 :
49 0 : SetMusicListener( 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f );
50 9 : }
51 :
52 : // unload()
53 : //
54 : // Cleans up OpenAL buffer information.
55 58 : void Music::unload() {
56 58 : if (!initialized_)
57 58 : return;
58 :
59 : PRINT_DEBUG("Cleaning up...\n");
60 0 : StopSong();
61 :
62 0 : alDeleteBuffers( 2, Buffers );
63 0 : ALenum errorCode = alGetError();
64 0 : if (errorCode != AL_NO_ERROR)
65 0 : PRINT_ERROR("Could not delete buffers; AL error code: '%d'.\n", errorCode);
66 :
67 0 : alDeleteSources( 1, &Source );
68 0 : errorCode = alGetError();
69 0 : if (errorCode != AL_NO_ERROR)
70 0 : PRINT_ERROR("Could not delete sources; AL error code: '%d'.\n", errorCode);
71 :
72 0 : initialized_ = false;
73 58 : }
74 :
75 : // PlaySong()
76 : //
77 : // Plays a specified song file. Accepts a file path to the song and
78 : // a boolean representing whether or not the song should be looped.
79 0 : void Music::PlaySong(const char* file_path, const bool &rep) {
80 0 : if (!initialized_)
81 0 : return;
82 :
83 : PRINT_DEBUG("Playing Song '%s'...\n", file_path);
84 : // Open binary file and set up the ov_open function for reading.
85 0 : Music_File = fopen( file_path, "rb" );
86 :
87 0 : if (Music_File == NULL)
88 0 : return;
89 :
90 0 : Repeat = rep;
91 :
92 0 : ov_open( Music_File, &Ogg_File, NULL, 0 );
93 :
94 : // Get format infomation from the info struct.
95 0 : Ogg_Info = ov_info( &Ogg_File, -1 );
96 0 : if ( Ogg_Info->channels == 1 )
97 0 : Format = AL_FORMAT_MONO16;
98 : else
99 0 : Format = AL_FORMAT_STEREO16;
100 :
101 : // Fill sound buffers.
102 0 : for ( int i = 0; i < 2; i++ ) {
103 0 : Size = 0;
104 0 : while ( Size < BUFFER_SIZE ) {
105 0 : Bytes = ov_read(
106 0 : &Ogg_File,
107 0 : Sound_Buffer + Size,
108 0 : BUFFER_SIZE - Size,
109 0 : 0, 2, 1, &Section
110 : );
111 0 : Size += Bytes;
112 : }
113 0 : alBufferData( Buffers[i], Format, Sound_Buffer, Size, Ogg_Info->rate );
114 0 : ALenum errorCode = alGetError();
115 0 : if (errorCode != AL_NO_ERROR)
116 0 : PRINT_ERROR("Could setup buffers; AL error code: '%d'.\n", errorCode);
117 0 : }
118 0 : Size = 0;
119 :
120 0 : alSourceQueueBuffers( Source, 2, Buffers );
121 0 : ALenum errorCode = alGetError();
122 0 : if (errorCode != AL_NO_ERROR)
123 0 : PRINT_ERROR("Could queue buffers; AL error code: '%d'.\n", errorCode);
124 :
125 0 : alSourcePlay( Source );
126 0 : errorCode = alGetError();
127 0 : if (errorCode != AL_NO_ERROR)
128 0 : PRINT_ERROR("Could not play source; AL error code: '%d'.\n", errorCode);
129 :
130 0 : Playing = true;
131 0 : }
132 :
133 : // StopSong()
134 : //
135 : // Halts the currently playing song, closes the Ogg file, and unqueues the
136 : // currently allocated song buffers. Takes no parameters.
137 0 : void Music::StopSong() {
138 0 : if (!initialized_ || !Playing)
139 0 : return;
140 :
141 0 : alSourceStop( Source ); // Stops OpenAL.
142 0 : ALenum errorCode = alGetError();
143 0 : if (errorCode != AL_NO_ERROR)
144 0 : PRINT_ERROR("Could not stop source; AL error code: '%d'.\n", errorCode);
145 :
146 0 : ov_clear( &Ogg_File ); // Closes the music file.
147 :
148 : // Tears down each buffer in the queue.
149 : ALuint temp_buff;
150 0 : alSourceUnqueueBuffers( Source, 1, &temp_buff );
151 0 : errorCode = alGetError();
152 0 : if (errorCode != AL_NO_ERROR)
153 0 : PRINT_ERROR("Could not unqueue buffers; AL error code: '%d'.\n", errorCode);
154 :
155 0 : alSourceUnqueueBuffers( Source, 1, &temp_buff );
156 0 : errorCode = alGetError();
157 0 : if (errorCode != AL_NO_ERROR)
158 0 : PRINT_ERROR("Could not unqueue buffers; AL error code: '%d'.\n", errorCode);
159 :
160 0 : Playing = false;
161 0 : Repeat = false;
162 0 : }
163 :
164 : // PauseSong()
165 : //
166 : // Pauses the currently playing song. Resumes play if the current song is
167 : // already paused. Takes no parameters.
168 0 : void Music::PauseSong() {
169 0 : if (!initialized_ || !Playing)
170 0 : return;
171 :
172 0 : alSourcePause( Source );
173 0 : ALenum errorCode = alGetError();
174 0 : if (errorCode != AL_NO_ERROR)
175 0 : PRINT_ERROR("Could not pause source; AL error code: '%d'.\n", errorCode);
176 :
177 0 : Playing = !Playing;
178 0 : }
179 :
180 : // Update()
181 : //
182 : // Fills up the sound buffers with the next data from the currently playing
183 : // song file. Takes no parameters.
184 0 : void Music::Update() {
185 0 : if (!initialized_ || !Playing)
186 0 : return;
187 :
188 : // Make sure to restart the song if we have a break in the data stream.
189 0 : alGetSourcei( Source, AL_SOURCE_STATE, &State );
190 0 : if ( State != AL_PLAYING )
191 0 : alSourcePlay( Source );
192 :
193 : // Fill any empty buffers and queue them up.
194 0 : alGetSourcei( Source, AL_BUFFERS_PROCESSED, &Processed );
195 0 : if ( Processed > 0 ) {
196 0 : alSourceUnqueueBuffers( Source, 1, &Temp_Buffer );
197 :
198 0 : while ( Size < BUFFER_SIZE ) {
199 0 : Bytes = ov_read(
200 0 : &Ogg_File,
201 0 : Sound_Buffer + Size,
202 0 : BUFFER_SIZE - Size,
203 0 : 0, 2, 1, &Section
204 : );
205 :
206 0 : if ( Bytes == 0 && Repeat )
207 0 : ov_raw_seek( &Ogg_File, 1 );
208 0 : else if ( Bytes == 0 && !Repeat )
209 0 : StopSong();
210 :
211 0 : Size += Bytes;
212 : }
213 :
214 0 : alBufferData( Temp_Buffer, Format, Sound_Buffer, Size, Ogg_Info->rate );
215 0 : alSourceQueueBuffers( Source, 1, &Temp_Buffer );
216 0 : Size = 0;
217 0 : }
218 0 : }
219 :
220 : // SetMusicListener()
221 : //
222 : // Sets the position and velocity of the listener. Takes six parameters. The
223 : // first three represent the listener's X, Y, and Z position, and the second
224 : // three represent the relative X, Y, and Z velocity.
225 0 : void Music::SetMusicListener(
226 : const ALfloat &PosX, const ALfloat &PosY, const ALfloat &PosZ,
227 : const ALfloat &VelX, const ALfloat &VelY, const ALfloat &VelZ
228 : ) {
229 0 : if (!initialized_)
230 0 : return;
231 :
232 0 : ALfloat ListenerPos[3] = { PosX, PosY, PosZ };
233 0 : ALfloat ListenerVel[3] = { VelX, VelY, VelZ };
234 0 : ALfloat ListenerOri[6] = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f };
235 :
236 0 : alListenerfv( AL_POSITION, ListenerPos );
237 0 : ALenum errorcode = alGetError();
238 0 : if (errorcode != AL_NO_ERROR)
239 0 : PRINT_ERROR("Could not set listener position; al error code: '%d'.\n", errorcode);
240 :
241 0 : alListenerfv( AL_VELOCITY, ListenerVel );
242 0 : errorcode = alGetError();
243 0 : if (errorcode != AL_NO_ERROR)
244 0 : PRINT_ERROR("Could not set listener velocity; al error code: '%d'.\n", errorcode);
245 :
246 0 : alListenerfv( AL_ORIENTATION, ListenerOri );
247 0 : errorcode = alGetError();
248 0 : if (errorcode != AL_NO_ERROR)
249 0 : PRINT_ERROR("Could not set listener orientation; al error code: '%d'.\n", errorcode);
250 0 : }
|