From bb06400d007d0056434fe4a0076e8dacfcd26aec Mon Sep 17 00:00:00 2001 From: Nicolas Bacca Date: Wed, 17 Apr 2002 20:23:45 +0000 Subject: [PATCH] Return of the MP3 CD patch ... use CBR 22 kHz svn-id: r3981 --- mac/mac.cpp | 1 - script_v1.cpp | 8 +- scumm.h | 31 ++++++- scummvm.cpp | 27 +++--- sdl.cpp | 1 - sound.cpp | 130 +++++++++++++++++++++++++- sound/mixer.cpp | 237 +++++++++++++++++++++++------------------------- sound/mixer.h | 23 ++++- x11.cpp | 1 - 9 files changed, 310 insertions(+), 149 deletions(-) diff --git a/mac/mac.cpp b/mac/mac.cpp index c43cf5dae86..0f89434adeb 100644 --- a/mac/mac.cpp +++ b/mac/mac.cpp @@ -32,7 +32,6 @@ #include "scumm.h" #include "gui.h" #include "cdmusic.h" -#include "mp3_cd.h" #include "gameDetector.h" #define SRC_WIDTH 320 diff --git a/script_v1.cpp b/script_v1.cpp index 88c5f5e1b2c..500dd35fd37 100644 --- a/script_v1.cpp +++ b/script_v1.cpp @@ -2672,8 +2672,14 @@ void Scumm::decodeParseString() else offset = 0; delay = (int)((getVarOrDirectWord(0x40) & 0xffff) * 7.5); - if (_gameId == GID_LOOM256) + if (_gameId == GID_LOOM256) { + _vars[VAR_MUSIC_FLAG] = 0; +#ifdef COMPRESSED_SOUND_FILE + playMP3CDTrack(1, 0, offset, delay); +#else _system->play_cdrom(1, 0, offset, delay); +#endif + } else warning("parseString: 8"); } diff --git a/scumm.h b/scumm.h index f3f18548f3d..7eaa8902b8c 100644 --- a/scumm.h +++ b/scumm.h @@ -82,7 +82,7 @@ struct ResHdr { } GCC_PACK; #define RES_DATA(x) (((byte*)x) + sizeof(ResHdr)) -#define RES_SIZE(x) ( READ_BE_UINT32_UNALIGNED(&((ResHdr*)x)->size) ) +#define RES_SIZE(x) ( READ_BE_UINT32(&((ResHdr*)x)->size) ) struct RoomHeader { @@ -595,7 +595,10 @@ public: char *getGameName(); Scumm(); // constructor - byte *_videoBuffer; + /* video buffer */ + byte _videoBuffer[328*200]; // main video buffer + + /* system call object */ /* Scumm main loop */ @@ -952,6 +955,27 @@ public: uint _curSoundPos; int current_cd_sound; +#ifdef COMPRESSED_SOUND_FILE + + #define CACHE_TRACKS 10 + #define MP3_BUFFER_SIZE 200000 + + /* used for mp3 CD music */ + + int _current_cache; + int _cached_tracks[CACHE_TRACKS]; + struct mad_header _mad_header[CACHE_TRACKS]; + long _mp3_size[CACHE_TRACKS]; + FILE* _mp3_tracks[CACHE_TRACKS]; + void* _mp3_buffer; + PlayingSoundHandle _mp3_handle; + + int getCachedTrack(int track); + void playMP3CDTrack(int track, int num_loops, int start, int delay); + + +#endif + int16 _soundQuePos, _soundQue[0x100]; byte _soundQue2Pos, _soundQue2[10]; bool _soundsPaused, _soundsPaused2; @@ -1120,6 +1144,7 @@ public: void restoreBG(int left, int top, int right, int bottom); void redrawBGStrip(int start, int num); void redrawBGAreas(); + void redrawLines(int from, int to); void moveCamera(); void cameraMoved(); @@ -1821,4 +1846,4 @@ byte *findResourceSmall(uint32 tag, byte *searchin); //void setShakePos(Scumm *s, int shake_pos); void setWindowName(Scumm *s); uint16 newTag2Old(uint32 oldTag); - +//void cd_playtrack(int track, int offset, int delay); diff --git a/scummvm.cpp b/scummvm.cpp index a7201ee939b..277872ebfca 100644 --- a/scummvm.cpp +++ b/scummvm.cpp @@ -63,7 +63,6 @@ void Scumm::scummInit() if (!(_features & GF_SMALL_NAMES)) loadCharset(1); - initScreens(0, 16, 320, 144); setShake(0); @@ -167,6 +166,11 @@ void Scumm::scummInit() _vars[VAR_V5_TALK_STRING_Y] = -0x50; getGraphicsPerformance(); + +#ifdef COMPRESSED_SOUND_FILE + _current_cache = 0; + _mp3_buffer = NULL; +#endif } @@ -238,14 +242,14 @@ int Scumm::scummLoop(int delta) _vars[VAR_MOUSE_Y] = mouse.y; _vars[VAR_DEBUGMODE] = _debugMode; - if (_features & GF_AUDIOTRACKS) { + if (_features & GF_AUDIOTRACKS) { if (delta) { if (++counter != 2) _vars[VAR_MI1_TIMER] += 5; else { counter = 0; _vars[VAR_MI1_TIMER] += 6; - } + } } } else if (_features & GF_OLD256) _vars[VAR_MUSIC_FLAG]++; // ENDERFIX @@ -902,8 +906,9 @@ void Scumm::convertKeysToClicks() Actor *Scumm::derefActorSafe(int id, const char *errmsg) { if (id < 1 || id >= NUM_ACTORS) { - if (_debugMode) - warning("Invalid actor %d in %s (script %d, opcode 0x%x) - This is potentially a BIG problem.", id, errmsg, vm.slot[_curExecScript].number, _opcode); + warning + ("Invalid actor %d in %s (script %d, opcode 0x%x) - This is potentially a BIG problem.", + id, errmsg, vm.slot[_curExecScript].number, _opcode); return NULL; } return derefActor(id); @@ -1147,7 +1152,6 @@ void Scumm::waitForTimer(int msec_delay) { } } - _system->update_cdrom(); /* Loop CD Audio if needed */ if (_system->get_msecs() >= start_time + msec_delay) break; _system->delay_msecs(10); @@ -1212,7 +1216,6 @@ void Scumm::launch() _minHeapThreshold = 400000; /* Create a primary virtual screen */ - _videoBuffer = (byte*)malloc(328*200); allocResTypeData(rtBuffer, MKID('NONE'), 10, "buffer", 0); initVirtScreen(0, 0, 200, false, false); @@ -1288,15 +1291,7 @@ Scumm *Scumm::createFromDetector(GameDetector *detector, OSystem *syst) /* bind the mixer to the system => mixer will be invoked * automatically when samples need to be generated */ - if (!scumm->_mixer->bind_to_system(syst)) { - warning("Sound initialization failed"); - if (detector->_use_adlib) { - detector->_use_adlib = false; - detector->_midi_driver = MD_NULL; - warning("Adlib music was selected, switching to midi null driver"); - } - } - + scumm->_mixer->bind_to_system(syst); scumm->_mixer->set_volume(128); scumm->_fullScreen = detector->_fullScreen; diff --git a/sdl.cpp b/sdl.cpp index e221bb74b2a..31f6dac78bf 100644 --- a/sdl.cpp +++ b/sdl.cpp @@ -4,7 +4,6 @@ #include "SDL_thread.h" #include "gameDetector.h" -#include "mp3_cd.h" #include #define MAX(a,b) (((a)<(b)) ? (b) : (a)) diff --git a/sound.cpp b/sound.cpp index 5467d71a520..7d2dae28d1d 100644 --- a/sound.cpp +++ b/sound.cpp @@ -504,6 +504,7 @@ void *Scumm::openSfxFile() warning("Unable to open DIG voice bundle: %s", buf); return file; } + /* Try opening the file <_exe_name>.sou first, eg tentacle.sou. * That way, you can keep .sou files for multiple games in the * same directory */ @@ -583,9 +584,134 @@ void Scumm::playSfxSound(void *sound, uint32 size, uint rate) void Scumm::playSfxSound_MP3(void *sound, uint32 size) { + #ifdef COMPRESSED_SOUND_FILE + _mixer->play_mp3(NULL, sound, size, SoundMixer::FLAG_AUTOFREE); -#else - error("Should never happen !!!"); + #endif } + +#ifdef COMPRESSED_SOUND_FILE + +int Scumm::getCachedTrack(int track) { + int i; + char track_name[1024]; + FILE* file; + int current_index; + struct mad_stream stream; + struct mad_frame frame; + unsigned char buffer[8192]; + unsigned int buflen = 0; + int count = 0, result = 0; + + // See if we find the track in the cache + for (i=0; istop(_mp3_handle); + return; + } + + index = getCachedTrack(track); + if (index < 0) + return; + + // Calc offset + frame_size = 144 * _mad_header[index].bitrate / _mad_header[index].samplerate; + offset = (long)((float)start / (float)75 * 1000 / + (float)((float)1152 / (float)_mad_header[index].samplerate * + 1000) * (float)(frame_size + 0.5)); + // Calc delay + mad_timer_set(&duration, 0, delay, 75); + // Go + fseek(_mp3_tracks[index], offset, SEEK_SET); + + _mixer->play_mp3_cdtrack(&_mp3_handle, _mp3_tracks[index], _mp3_buffer, MP3_BUFFER_SIZE, duration); + +} + +#endif \ No newline at end of file diff --git a/sound/mixer.cpp b/sound/mixer.cpp index 88c73564380..6b1589b0029 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; } + +/* MP3 CD music */ + +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 0 +void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len) { + mad_fixed_t const *ch; + mad_timer_t frame_duration; -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; - - if (!sound_data.mp3_cdmusic.playing) + 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 ... + } + // 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; + } + } - 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) { + 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; - } - // 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) { - - if (sound_data.mp3_cdmusic.stream.error == MAD_ERROR_BUFLEN) { + } + 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 diff --git a/sound/mixer.h b/sound/mixer.h index 26d19881ca6..e455e03d0e9 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -53,6 +53,26 @@ private: Channel_MP3(SoundMixer *mixer, void *sound, uint size, byte flags); }; + class Channel_MP3_CDMUSIC : public Channel { + SoundMixer *_mixer; + void *_ptr; + struct mad_stream _stream; + struct mad_frame _frame; + struct mad_synth _synth; + uint32 _pos_in_frame; + uint32 _size; + uint32 _buffer_size; + mad_timer_t _duration; + FILE *_file; + bool _initialized; + byte _flags; + public: + void mix(int16 *data, uint len); + void destroy(); + + Channel_MP3_CDMUSIC(SoundMixer *mixer, FILE* file, void *buffer, uint32 buffer_size, mad_timer_t duration); + }; + #endif static void on_generate_samples(void *s, byte *samples, int len); @@ -81,11 +101,12 @@ public: enum { FLAG_AUTOFREE = 1, FLAG_UNSIGNED = 2, /* unsigned samples */ - FLAG_FILE = 4, /* sound is a FILE * that's read from */ + FLAG_FILE = 4, /* sound is a FILE * that's read from */ }; void play_raw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags); #ifdef COMPRESSED_SOUND_FILE void play_mp3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags); + void play_mp3_cdtrack(PlayingSoundHandle *handle, FILE* file, void *buffer, uint32 buffer_size, mad_timer_t duration); #endif /* Premix procedure, useful when using fmopl adlib */ diff --git a/x11.cpp b/x11.cpp index 3d249ac2a1c..3fb785caeeb 100644 --- a/x11.cpp +++ b/x11.cpp @@ -25,7 +25,6 @@ #include "scumm.h" #include "gui.h" #include "cdmusic.h" -#include "mp3_cd.h" #include #include