]> Dogcows Code - chaz/yoink/blob - src/Moof/Sound.cc
initial port to win32
[chaz/yoink] / src / Moof / Sound.cc
1
2 /*******************************************************************************
3
4 Copyright (c) 2009, Charles McGarvey
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 *******************************************************************************/
28
29 #include <string>
30
31 #include <SDL/SDL.h>
32 #include <SDL/SDL_sound.h>
33 #include <AL/al.h>
34
35 #include "Log.hh"
36 #include "Mippleton.hh"
37 #include "Sound.hh"
38
39 #define BUFFER_SIZE (8 * 4096)
40
41 namespace Mf {
42
43
44 struct Sound::Impl
45 {
46
47 static ALenum getAudioFormat(const Sound_AudioInfo& audioInfo)
48 {
49 if (audioInfo.format == AUDIO_U8 || audioInfo.format == AUDIO_S8)
50 {
51 if (audioInfo.channels == 1) return AL_FORMAT_MONO8;
52 else return AL_FORMAT_STEREO8;
53 }
54 else
55 {
56 if (audioInfo.channels == 1) return AL_FORMAT_MONO16;
57 else return AL_FORMAT_STEREO16;
58 }
59 }
60
61 struct Buffer : public Mippleton<Buffer>
62 {
63 Buffer(const std::string& name) :
64 Mippleton<Buffer>(name)
65 {
66 sound = 0;
67 objects[0] = 0;
68 objects[1] = 0;
69 }
70
71 ~Buffer()
72 {
73 alDeleteBuffers(2, objects);
74
75 if (sound) Sound_FreeSample(sound);
76 }
77
78
79 void loadFromFile(const std::string& filePath, bool stream)
80 {
81 if (objects[0] != 0) return;
82
83 sound = Sound_NewSampleFromFile(filePath.c_str(),
84 NULL, BUFFER_SIZE);
85
86 if (!sound)
87 {
88 logWarning("error while loading sound %s: %s", getName().c_str(), Sound_GetError());
89 throw Exception(Exception::FILE_NOT_FOUND);
90 }
91
92 if (!stream)
93 {
94 unsigned decoded = Sound_DecodeAll(sound);
95 if (decoded == 0)
96 {
97 logWarning("decoded no bytes from %s", getName().c_str());
98 //throw Exception(Exception::FILE_NOT_FOUND);
99 return;
100 }
101
102 alGenBuffers(2, objects);
103 alBufferData(objects[0], getAudioFormat(sound->actual), sound->buffer,
104 sound->buffer_size, sound->actual.rate);
105 logDebug("buffer size: %d", sound->buffer_size);
106 logDebug(" channels: %d", sound->actual.channels);
107 logDebug(" format: %d", sound->actual.format);
108 logDebug(" frequency: %d", sound->actual.rate);
109
110 Sound_FreeSample(sound);
111 sound = 0;
112 }
113 else
114 {
115 logDebug("buffer size: %d", sound->buffer_size);
116 logDebug(" channels: %d", sound->actual.channels);
117 logDebug(" format: %d", sound->actual.format);
118 logDebug(" frequency: %d", sound->actual.rate);
119 alGenBuffers(2, objects);
120 }
121 }
122
123 bool stream(ALuint buffer)
124 {
125 int bytes = Sound_Decode(sound);
126
127 if (bytes < BUFFER_SIZE) return false;
128
129 alBufferData(buffer, getAudioFormat(sound->actual), sound->buffer,
130 sound->buffer_size, sound->actual.rate);
131 return false;
132 }
133
134 Sound_Sample* sound;
135 ALuint objects[2];
136
137 //ALfloat location[] = {0.0f, 0.0f, 0.0f};
138 //ALfloat location2[] = {0.0f, 0.0f, 0.0f};
139 //ALfloat orient[] = {0.0f, 0.0f, -1.0f, 0.0, 1.0, 0.0};
140
141
142 //alListenerfv(AL_POSITION, location);
143 //alListenerfv(AL_VELOCITY, location);
144 //alListenerfv(AL_VELOCITY, orient);
145 };
146
147 Impl(const std::string& name, bool stream = false) :
148 buffer_(Buffer::getInstance(name))
149 {
150 if (!stream) buffer_->loadFromFile(Sound::getPath(name), stream);
151 else buffer_->loadFromFile(SoundStream::getPath(name), stream);
152
153 ALfloat location[] = {0.0f, 0.0f, 0.0f};
154
155 alGenSources(1, &source_);
156
157 alSourcef(source_, AL_PITCH, 1.0f);
158 alSourcef(source_, AL_GAIN, 1.0f);
159 alSourcefv(source_, AL_POSITION, location);
160 alSourcefv(source_, AL_VELOCITY, location);
161 alSourcei(source_, AL_LOOPING, AL_FALSE);
162
163 if (!stream)
164 {
165 alSourcei(source_, AL_BUFFER, buffer_->objects[0]);
166 }
167 else
168 {
169 buffer_->stream(buffer_->objects[0]);
170 buffer_->stream(buffer_->objects[1]);
171
172 alSourceQueueBuffers(source_, 2, buffer_->objects);
173 }
174 }
175
176 ~Impl()
177 {
178 alDeleteSources(1, &source_);
179 }
180
181
182 void update()
183 {
184 int finished = 0;
185
186 alGetSourcei(source_, AL_BUFFERS_PROCESSED, &finished);
187
188 while (finished-- > 0)
189 {
190 ALuint buffer;
191
192 alSourceUnqueueBuffers(source_, 1, &buffer);
193 buffer_->stream(buffer);
194 alSourceQueueBuffers(source_, 1, &buffer);
195 }
196 }
197
198
199 boost::shared_ptr<Buffer> buffer_;
200 ALuint source_;
201 bool playing;
202 };
203
204
205 Sound::Sound(const std::string& name) :
206 // pass through
207 impl_(new Sound::Impl(name)) {}
208
209
210 void Sound::play()
211 {
212 if (!impl_->buffer_->sound) return;
213
214 //alSourceRewind(impl_->source_);
215 alSourcePlay(impl_->source_);
216 impl_->playing = true;
217 }
218
219 void Sound::pause()
220 {
221 alSourcePause(impl_->source_);
222 impl_->playing = false;
223 }
224
225 void Sound::togglePlayPause()
226 {
227 if (impl_->playing) pause();
228 else play();
229 }
230
231 void Sound::setGain(Scalar gain)
232 {
233 alSourcef(impl_->source_, AL_GAIN, gain);
234 }
235
236
237 std::string Sound::getPath(const std::string& name)
238 {
239 std::string path = Resource::getPath("sounds/" + name + ".ogg");
240 return path;
241 }
242
243
244 //##############################################################################
245
246
247 SoundStream::SoundStream(const std::string& name)
248 // pass through
249 //impl_(name, true) {}
250 {
251 impl_ = boost::shared_ptr<Sound::Impl>(new Sound::Impl(name, true));
252 }
253
254
255 void SoundStream::update(Scalar t, Scalar dt)
256 {
257 // pass through
258 impl_->update();
259 }
260
261
262 std::string SoundStream::getPath(const std::string& name)
263 {
264 std::string path = Resource::getPath("sounds/" + name + ".xm");
265 return path;
266 }
267
268
269 } // namespace Mf
270
271 /** vim: set ts=4 sw=4 tw=80: *************************************************/
272
This page took 0.048189 seconds and 5 git commands to generate.