19 |
*/ |
*/ |
20 |
#include "enigma.hh" |
#include "enigma.hh" |
21 |
#include "options.hh" |
#include "options.hh" |
22 |
|
#include "oxyd.hh" |
23 |
#include "sound.hh" |
#include "sound.hh" |
24 |
#include "system.hh" |
#include "system.hh" |
25 |
#include "SDL.h" |
#include "SDL.h" |
115 |
} |
} |
116 |
|
|
117 |
static Mix_Chunk * |
static Mix_Chunk * |
|
load_oxyd_sound (const string &name) |
|
|
{ |
|
|
string filename = enigma::FindDataFile("sound/" + name + ".snd"); |
|
|
if (sysdep::FileExists (filename)) { |
|
|
// Mix_Chunk *c; |
|
|
} |
|
|
return 0; |
|
|
} |
|
|
|
|
|
static Mix_Chunk * |
|
118 |
cache_sound(const std::string &name) |
cache_sound(const std::string &name) |
119 |
{ |
{ |
120 |
px::Dict<Mix_Chunk*>::iterator i=wav_cache.find(name); |
px::Dict<Mix_Chunk*>::iterator i=wav_cache.find(name); |
121 |
if (i == wav_cache.end()) { |
if (i == wav_cache.end()) { |
122 |
string filename = enigma::FindDataFile("sound/" + name + ".wav"); |
string filename = enigma::FindDataFile("sound/" + name + ".wav"); |
123 |
Mix_Chunk *ch = Mix_LoadWAV(filename.c_str()); |
Mix_Chunk *ch = 0; |
124 |
|
|
125 |
|
ch = enigma::oxyd::LoadSound(name); |
126 |
|
if (ch == 0) |
127 |
|
ch = Mix_LoadWAV(filename.c_str()); |
128 |
|
|
129 |
if (ch != 0) |
if (ch != 0) |
130 |
wav_cache.insert(name, ch); |
wav_cache.insert(name, ch); |
131 |
else |
else |
156 |
double range = 100; // How far can sound travel? |
double range = 100; // How far can sound travel? |
157 |
double volume = 1 - length(v)/range; |
double volume = 1 - length(v)/range; |
158 |
if (Mix_Chunk *chunk = cache_sound(name)) { |
if (Mix_Chunk *chunk = cache_sound(name)) { |
159 |
int channel = Mix_GroupOldest(-1); |
int channel = -1; //Mix_GroupOldest(-1); |
160 |
int mixvol = int(volume * options::SoundVolume * MIX_MAX_VOLUME); |
int mixvol = int(volume * options::SoundVolume * MIX_MAX_VOLUME); |
161 |
|
|
162 |
Mix_PlayChannel(channel, chunk, 0); |
channel = Mix_PlayChannel(channel, chunk, 0); |
163 |
Mix_SetPanning(channel, left, right); |
Mix_SetPanning(channel, left, right); |
164 |
Mix_Volume(channel, px::Clamp(mixvol, 0, MIX_MAX_VOLUME)); |
Mix_Volume(channel, px::Clamp(mixvol, 0, MIX_MAX_VOLUME)); |
165 |
} |
} |
212 |
current_music = 0; |
current_music = 0; |
213 |
current_music_name = ""; |
current_music_name = ""; |
214 |
} |
} |
215 |
|
|
216 |
|
/* SDL_ConvertAudio is not very good at audio resampling since it is |
217 |
|
only capable of changing the sound frequency by integer powers of 2 |
218 |
|
(i.e., by a factor of ... 1/4 1/2 1 2 ...). The sound files used |
219 |
|
by Oxyd are sampled at 6kHz which we must convert to roughly 22kHz. |
220 |
|
This function resamples between any two frequencies using simple |
221 |
|
linear interpolation. It is not capable of changing the sample |
222 |
|
format or dealing with more than one channel. |
223 |
|
*/ |
224 |
|
namespace |
225 |
|
{ |
226 |
|
Sint8 *resample (const Sint8 *data, Uint32 len, int oldfreq, int newfreq, Uint32 *newlen) |
227 |
|
{ |
228 |
|
assert (data); |
229 |
|
assert (len>0); |
230 |
|
assert (oldfreq > 0); |
231 |
|
assert (newfreq > 0); |
232 |
|
const int sample_size = 1; // 8bit sample data |
233 |
|
|
234 |
|
double ratio = double(oldfreq)/newfreq; |
235 |
|
*newlen = int(len/ratio + sample_size); |
236 |
|
Sint8 *newdata = (Sint8*) malloc (sample_size * (*newlen)); |
237 |
|
if (!newdata) |
238 |
|
return 0; |
239 |
|
|
240 |
|
const Sint8 *src = data; |
241 |
|
Sint8 *dst = newdata; |
242 |
|
|
243 |
|
float srcpos = 0; |
244 |
|
for (int i=0; i<*newlen; ++i) { |
245 |
|
int srcidx = static_cast<int>(floor(srcpos)); |
246 |
|
float a2 = srcpos - srcidx; |
247 |
|
float a1 = 1.0f - a2; |
248 |
|
dst[i] = static_cast<Sint8> (a1*src[srcidx] + a2*src[srcidx+1]); |
249 |
|
srcpos += ratio; |
250 |
|
} |
251 |
|
|
252 |
|
return newdata; |
253 |
|
} |
254 |
|
} |
255 |
|
|
256 |
|
|
257 |
|
|
258 |
|
|
259 |
|
Mix_Chunk * |
260 |
|
sound::ChunkFromRaw (const Uint8 *buf, Uint32 len, |
261 |
|
int sfreq, int sformat, int schannels) |
262 |
|
{ |
263 |
|
if (!sound_initialized || !buf) |
264 |
|
return 0; |
265 |
|
|
266 |
|
// get destination format |
267 |
|
int dfreq, dchannels; |
268 |
|
Uint16 dformat; |
269 |
|
Mix_QuerySpec (&dfreq, &dformat, &dchannels); |
270 |
|
enigma::Log << "converting: (" << sfreq <<","<<schannels |
271 |
|
<< ") to (" << dfreq <<","<<dchannels << endl; |
272 |
|
|
273 |
|
// resample |
274 |
|
Uint32 newlen=0; |
275 |
|
Uint8 *newbuf = (Uint8*) resample ((Sint8*)buf, len, sfreq, dfreq, &newlen); |
276 |
|
|
277 |
|
|
278 |
|
// convert audio data |
279 |
|
SDL_AudioCVT cvt; |
280 |
|
if (!SDL_BuildAudioCVT (&cvt, sformat, schannels, dfreq, |
281 |
|
dformat, dchannels, dfreq)) |
282 |
|
return 0; |
283 |
|
|
284 |
|
cvt.buf = (Uint8*) malloc(newlen * cvt.len_mult); |
285 |
|
cvt.len = newlen; |
286 |
|
memcpy(cvt.buf, newbuf, newlen); |
287 |
|
free(newbuf); |
288 |
|
|
289 |
|
SDL_ConvertAudio(&cvt); |
290 |
|
|
291 |
|
Mix_Chunk *chunk = Mix_QuickLoad_RAW(cvt.buf, cvt.len_cvt); |
292 |
|
chunk->allocated = 1; |
293 |
|
return chunk; |
294 |
|
} |
295 |
|
|