diff options
Diffstat (limited to 'sound/mixer.cpp')
-rw-r--r-- | sound/mixer.cpp | 239 |
1 files changed, 115 insertions, 124 deletions
diff --git a/sound/mixer.cpp b/sound/mixer.cpp index 88c7356438..6b1589b002 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -40,6 +40,11 @@ void SoundMixer::play_raw(PlayingSoundHandle *handle, void *sound, uint32 size, void SoundMixer::play_mp3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags) { insert(handle, new Channel_MP3(this, sound, size, flags)); } +void SoundMixer::play_mp3_cdtrack(PlayingSoundHandle *handle, FILE* file, void *buffer, uint32 buffer_size, mad_timer_t duration) { + if (*handle) + stop(*handle); + insert(handle, new Channel_MP3_CDMUSIC(this, file, buffer, buffer_size, duration)); +} #endif void SoundMixer::mix(int16 *buf, uint len) { @@ -282,153 +287,139 @@ void SoundMixer::Channel_MP3::destroy() { delete this; } -#endif -#if 0 +/* MP3 CD music */ -void MixerChannel::mix(int16 * data, uint32 len) -{ - } else if (type == MIXER_MP3_CDMUSIC) { - mad_fixed_t const *ch; - mad_timer_t frame_duration; - static long last_pos = 0; +SoundMixer::Channel_MP3_CDMUSIC::Channel_MP3_CDMUSIC(SoundMixer *mixer, FILE* file, void *buffer, uint32 buffer_size, mad_timer_t duration) { + _mixer = mixer; + _file = file; + _duration = duration; + _initialized = false; + _buffer_size = buffer_size; + _ptr = buffer; + _flags = 0; + mad_stream_init(&_stream); +#ifdef _WIN32_WCE + // 11 kHz on WinCE + mad_stream_options(&_stream, MAD_OPTION_HALFSAMPLERATE); +#endif + mad_frame_init(&_frame); + mad_synth_init(&_synth); +} - if (!sound_data.mp3_cdmusic.playing) +void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len) { + mad_fixed_t const *ch; + mad_timer_t frame_duration; + + if (!_initialized) { + int skip_loop; + // just skipped + memset(_ptr, 0,_buffer_size + MAD_BUFFER_GUARD); + _size = fread(_ptr, 1, _buffer_size, _file); + if (!_size) { + destroy(); return; - - while (1) { - - // See if we just skipped - if (ftell(sound_data.mp3_cdmusic.file) != last_pos) { - int skip_loop; - - // Read the new data - memset(_sfx_sound, 0, - sound_data.mp3_cdmusic.buffer_size + MAD_BUFFER_GUARD); - sound_data.mp3_cdmusic.size = - fread(_sfx_sound, 1, sound_data.mp3_cdmusic.buffer_size, - sound_data.mp3_cdmusic.file); - if (!sound_data.mp3_cdmusic.size) { - sound_data.mp3_cdmusic.playing = false; - return; + } + // Resync + mad_stream_buffer(&_stream,(unsigned char *)_ptr,_size); + skip_loop = 2; + while (skip_loop != 0) { + if (mad_frame_decode(&_frame,&_stream) == 0) { + /* Do not decrease duration - see if it's a problem */ + skip_loop--; + if (skip_loop == 0) { + mad_synth_frame(&_synth, &_frame); } - last_pos = ftell(sound_data.mp3_cdmusic.file); - // Resync - mad_stream_buffer(&sound_data.mp3_cdmusic.stream, - (unsigned char *)_sfx_sound, - sound_data.mp3_cdmusic.size); - skip_loop = 2; - while (skip_loop != 0) { - if (mad_frame_decode(&sound_data.mp3_cdmusic.frame, - &sound_data.mp3_cdmusic.stream) == 0) { - /* Do not decrease duration - see if it's a problem */ - skip_loop--; - if (skip_loop == 0) { - mad_synth_frame(&sound_data.mp3_cdmusic.synth, - &sound_data.mp3_cdmusic.frame); - } - } else { - if (!MAD_RECOVERABLE(sound_data.mp3_cdmusic.stream.error)) { + } else { + if (!MAD_RECOVERABLE(_stream.error)) { debug(1, "Unrecoverable error while skipping !"); - sound_data.mp3_cdmusic.playing = false; + destroy(); return; - } } } - // We are supposed to be in synch - mad_frame_mute(&sound_data.mp3_cdmusic.frame); - mad_synth_mute(&sound_data.mp3_cdmusic.synth); - // Resume decoding - if (mad_frame_decode(&sound_data.mp3_cdmusic.frame, - &sound_data.mp3_cdmusic.stream) == 0) { - sound_data.mp3_cdmusic.position = - (unsigned char *)sound_data.mp3_cdmusic.stream.next_frame - - (unsigned char *)_sfx_sound; - sound_data.mp3_cdmusic.pos_in_frame = 0; - } else { - sound_data.mp3_cdmusic.playing = false; - return; - } - } - // Get samples, play samples ... - - ch = sound_data.mp3_cdmusic.synth.pcm.samples[0] + - sound_data.mp3_cdmusic.pos_in_frame; - while ((sound_data.mp3_cdmusic.pos_in_frame < - sound_data.mp3_cdmusic.synth.pcm.length) && (len > 0)) { - *data++ += scale_sample(*ch++); - len--; - sound_data.mp3_cdmusic.pos_in_frame++; - } - if (len == 0) { - return; - } - // See if we have finished - // May be incorrect to check the size at the end of a frame but I suppose - // they are short enough :) - - frame_duration = sound_data.mp3_cdmusic.frame.header.duration; - - mad_timer_negate(&frame_duration); - mad_timer_add(&sound_data.mp3_cdmusic.duration, frame_duration); - if (mad_timer_compare(sound_data.mp3_cdmusic.duration, mad_timer_zero) - < 0) { - sound_data.mp3_cdmusic.playing = false; - } - - if (mad_frame_decode(&sound_data.mp3_cdmusic.frame, - &sound_data.mp3_cdmusic.stream) == -1) { + } + // We are supposed to be in synch + mad_frame_mute(&_frame); + mad_synth_mute(&_synth); + // Resume decoding + if (mad_frame_decode(&_frame,&_stream) == 0) { + _pos_in_frame = 0; + _initialized = true; + } + else { + debug(1, "Cannot resume decoding"); + destroy(); + return; + } + } - if (sound_data.mp3_cdmusic.stream.error == MAD_ERROR_BUFLEN) { + while(1) { + // Get samples, play samples ... + ch = _synth.pcm.samples[0] + _pos_in_frame; + while ((_pos_in_frame < _synth.pcm.length) && (len > 0)) { + *data++ += scale_sample(*ch++); + len--; + _pos_in_frame++; + } + if (len == 0) { + return; + } + // See if we have finished + // May be incorrect to check the size at the end of a frame but I suppose + // they are short enough :) + frame_duration = _frame.header.duration; + mad_timer_negate(&frame_duration); + mad_timer_add(&_duration, frame_duration); + if (mad_timer_compare(_duration, mad_timer_zero) < 0) { + destroy(); + return; + } + if (mad_frame_decode(&_frame, &_stream) == -1) { + if (_stream.error == MAD_ERROR_BUFLEN) { int not_decoded; - if (!sound_data.mp3_cdmusic.stream.next_frame) { - memset(_sfx_sound, 0, - sound_data.mp3_cdmusic.buffer_size + MAD_BUFFER_GUARD); - sound_data.mp3_cdmusic.size = - fread(_sfx_sound, 1, sound_data.mp3_cdmusic.buffer_size, - sound_data.mp3_cdmusic.file); - sound_data.mp3_cdmusic.position = 0; + if (!_stream.next_frame) { + memset(_ptr, 0, _buffer_size + MAD_BUFFER_GUARD); + _size = + fread(_ptr, 1, _buffer_size, _file); not_decoded = 0; - } else { - not_decoded = sound_data.mp3_cdmusic.stream.bufend - - sound_data.mp3_cdmusic.stream.next_frame; - memcpy(_sfx_sound, sound_data.mp3_cdmusic.stream.next_frame, - not_decoded); - - sound_data.mp3_cdmusic.size = - fread((unsigned char *)_sfx_sound + not_decoded, 1, - sound_data.mp3_cdmusic.buffer_size - not_decoded, - sound_data.mp3_cdmusic.file); + } + else { + not_decoded = _stream.bufend - _stream.next_frame; + memcpy(_ptr, _stream.next_frame, not_decoded); + _size = + fread((unsigned char *)_ptr + not_decoded, 1, + _buffer_size - not_decoded, _file); } - last_pos = ftell(sound_data.mp3_cdmusic.file); - sound_data.mp3_cdmusic.stream.error = MAD_ERROR_NONE; + _stream.error = MAD_ERROR_NONE; // Restream - mad_stream_buffer(&sound_data.mp3_cdmusic.stream, - (unsigned char *)_sfx_sound, - sound_data.mp3_cdmusic.size + not_decoded); - if (mad_frame_decode - (&sound_data.mp3_cdmusic.frame, - &sound_data.mp3_cdmusic.stream) == -1) { + mad_stream_buffer(&_stream, (unsigned char *)_ptr, _size + not_decoded); + if (mad_frame_decode(&_frame, &_stream) == -1) { debug(1, "Error decoding after restream %d !", - sound_data.mp3.stream.error); + _stream.error); } - } else if (!MAD_RECOVERABLE(sound_data.mp3.stream.error)) { + } else if (!MAD_RECOVERABLE(_stream.error)) { error("MAD frame decode error in MP3 CDMUSIC !"); } - } - - mad_synth_frame(&sound_data.mp3_cdmusic.synth, - &sound_data.mp3_cdmusic.frame); - sound_data.mp3_cdmusic.pos_in_frame = 0; - sound_data.mp3_cdmusic.position = - (unsigned char *)sound_data.mp3_cdmusic.stream.next_frame - - (unsigned char *)_sfx_sound; - } } + mad_synth_frame(&_synth, &_frame); + _pos_in_frame = 0; + } } +void SoundMixer::Channel_MP3_CDMUSIC::destroy() { + if (_flags & FLAG_AUTOFREE) + free(_ptr); + _mixer->uninsert(this); + mad_synth_finish(&_synth); + mad_frame_finish(&_frame); + mad_stream_finish(&_stream); + + delete this; +} + + #endif |