Return of the MP3 CD patch ... use CBR 22 kHz
svn-id: r3981
This commit is contained in:
parent
fd6a44e7c5
commit
bb06400d00
9 changed files with 310 additions and 149 deletions
|
@ -32,7 +32,6 @@
|
||||||
#include "scumm.h"
|
#include "scumm.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "cdmusic.h"
|
#include "cdmusic.h"
|
||||||
#include "mp3_cd.h"
|
|
||||||
#include "gameDetector.h"
|
#include "gameDetector.h"
|
||||||
|
|
||||||
#define SRC_WIDTH 320
|
#define SRC_WIDTH 320
|
||||||
|
|
|
@ -2672,8 +2672,14 @@ void Scumm::decodeParseString()
|
||||||
else
|
else
|
||||||
offset = 0;
|
offset = 0;
|
||||||
delay = (int)((getVarOrDirectWord(0x40) & 0xffff) * 7.5);
|
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);
|
_system->play_cdrom(1, 0, offset, delay);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else
|
else
|
||||||
warning("parseString: 8");
|
warning("parseString: 8");
|
||||||
}
|
}
|
||||||
|
|
31
scumm.h
31
scumm.h
|
@ -82,7 +82,7 @@ struct ResHdr {
|
||||||
} GCC_PACK;
|
} GCC_PACK;
|
||||||
|
|
||||||
#define RES_DATA(x) (((byte*)x) + sizeof(ResHdr))
|
#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 {
|
struct RoomHeader {
|
||||||
|
@ -595,7 +595,10 @@ public:
|
||||||
char *getGameName();
|
char *getGameName();
|
||||||
Scumm(); // constructor
|
Scumm(); // constructor
|
||||||
|
|
||||||
byte *_videoBuffer;
|
/* video buffer */
|
||||||
|
byte _videoBuffer[328*200]; // main video buffer
|
||||||
|
|
||||||
|
/* system call object */
|
||||||
|
|
||||||
/* Scumm main loop */
|
/* Scumm main loop */
|
||||||
|
|
||||||
|
@ -952,6 +955,27 @@ public:
|
||||||
uint _curSoundPos;
|
uint _curSoundPos;
|
||||||
int current_cd_sound;
|
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];
|
int16 _soundQuePos, _soundQue[0x100];
|
||||||
byte _soundQue2Pos, _soundQue2[10];
|
byte _soundQue2Pos, _soundQue2[10];
|
||||||
bool _soundsPaused, _soundsPaused2;
|
bool _soundsPaused, _soundsPaused2;
|
||||||
|
@ -1120,6 +1144,7 @@ public:
|
||||||
void restoreBG(int left, int top, int right, int bottom);
|
void restoreBG(int left, int top, int right, int bottom);
|
||||||
void redrawBGStrip(int start, int num);
|
void redrawBGStrip(int start, int num);
|
||||||
void redrawBGAreas();
|
void redrawBGAreas();
|
||||||
|
void redrawLines(int from, int to);
|
||||||
|
|
||||||
void moveCamera();
|
void moveCamera();
|
||||||
void cameraMoved();
|
void cameraMoved();
|
||||||
|
@ -1821,4 +1846,4 @@ byte *findResourceSmall(uint32 tag, byte *searchin);
|
||||||
//void setShakePos(Scumm *s, int shake_pos);
|
//void setShakePos(Scumm *s, int shake_pos);
|
||||||
void setWindowName(Scumm *s);
|
void setWindowName(Scumm *s);
|
||||||
uint16 newTag2Old(uint32 oldTag);
|
uint16 newTag2Old(uint32 oldTag);
|
||||||
|
//void cd_playtrack(int track, int offset, int delay);
|
||||||
|
|
27
scummvm.cpp
27
scummvm.cpp
|
@ -63,7 +63,6 @@ void Scumm::scummInit()
|
||||||
if (!(_features & GF_SMALL_NAMES))
|
if (!(_features & GF_SMALL_NAMES))
|
||||||
loadCharset(1);
|
loadCharset(1);
|
||||||
|
|
||||||
|
|
||||||
initScreens(0, 16, 320, 144);
|
initScreens(0, 16, 320, 144);
|
||||||
|
|
||||||
setShake(0);
|
setShake(0);
|
||||||
|
@ -167,6 +166,11 @@ void Scumm::scummInit()
|
||||||
_vars[VAR_V5_TALK_STRING_Y] = -0x50;
|
_vars[VAR_V5_TALK_STRING_Y] = -0x50;
|
||||||
|
|
||||||
getGraphicsPerformance();
|
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_MOUSE_Y] = mouse.y;
|
||||||
_vars[VAR_DEBUGMODE] = _debugMode;
|
_vars[VAR_DEBUGMODE] = _debugMode;
|
||||||
|
|
||||||
if (_features & GF_AUDIOTRACKS) {
|
if (_features & GF_AUDIOTRACKS) {
|
||||||
if (delta) {
|
if (delta) {
|
||||||
if (++counter != 2)
|
if (++counter != 2)
|
||||||
_vars[VAR_MI1_TIMER] += 5;
|
_vars[VAR_MI1_TIMER] += 5;
|
||||||
else {
|
else {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
_vars[VAR_MI1_TIMER] += 6;
|
_vars[VAR_MI1_TIMER] += 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (_features & GF_OLD256)
|
} else if (_features & GF_OLD256)
|
||||||
_vars[VAR_MUSIC_FLAG]++; // ENDERFIX
|
_vars[VAR_MUSIC_FLAG]++; // ENDERFIX
|
||||||
|
@ -902,8 +906,9 @@ void Scumm::convertKeysToClicks()
|
||||||
Actor *Scumm::derefActorSafe(int id, const char *errmsg)
|
Actor *Scumm::derefActorSafe(int id, const char *errmsg)
|
||||||
{
|
{
|
||||||
if (id < 1 || id >= NUM_ACTORS) {
|
if (id < 1 || id >= NUM_ACTORS) {
|
||||||
if (_debugMode)
|
warning
|
||||||
warning("Invalid actor %d in %s (script %d, opcode 0x%x) - This is potentially a BIG problem.", id, errmsg, vm.slot[_curExecScript].number, _opcode);
|
("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 NULL;
|
||||||
}
|
}
|
||||||
return derefActor(id);
|
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)
|
if (_system->get_msecs() >= start_time + msec_delay)
|
||||||
break;
|
break;
|
||||||
_system->delay_msecs(10);
|
_system->delay_msecs(10);
|
||||||
|
@ -1212,7 +1216,6 @@ void Scumm::launch()
|
||||||
_minHeapThreshold = 400000;
|
_minHeapThreshold = 400000;
|
||||||
|
|
||||||
/* Create a primary virtual screen */
|
/* Create a primary virtual screen */
|
||||||
_videoBuffer = (byte*)malloc(328*200);
|
|
||||||
|
|
||||||
allocResTypeData(rtBuffer, MKID('NONE'), 10, "buffer", 0);
|
allocResTypeData(rtBuffer, MKID('NONE'), 10, "buffer", 0);
|
||||||
initVirtScreen(0, 0, 200, false, false);
|
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
|
/* bind the mixer to the system => mixer will be invoked
|
||||||
* automatically when samples need to be generated */
|
* automatically when samples need to be generated */
|
||||||
if (!scumm->_mixer->bind_to_system(syst)) {
|
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->set_volume(128);
|
scumm->_mixer->set_volume(128);
|
||||||
|
|
||||||
scumm->_fullScreen = detector->_fullScreen;
|
scumm->_fullScreen = detector->_fullScreen;
|
||||||
|
|
1
sdl.cpp
1
sdl.cpp
|
@ -4,7 +4,6 @@
|
||||||
#include "SDL_thread.h"
|
#include "SDL_thread.h"
|
||||||
#include "gameDetector.h"
|
#include "gameDetector.h"
|
||||||
|
|
||||||
#include "mp3_cd.h"
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
#define MAX(a,b) (((a)<(b)) ? (b) : (a))
|
#define MAX(a,b) (((a)<(b)) ? (b) : (a))
|
||||||
|
|
130
sound.cpp
130
sound.cpp
|
@ -504,6 +504,7 @@ void *Scumm::openSfxFile()
|
||||||
warning("Unable to open DIG voice bundle: %s", buf);
|
warning("Unable to open DIG voice bundle: %s", buf);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try opening the file <_exe_name>.sou first, eg tentacle.sou.
|
/* Try opening the file <_exe_name>.sou first, eg tentacle.sou.
|
||||||
* That way, you can keep .sou files for multiple games in the
|
* That way, you can keep .sou files for multiple games in the
|
||||||
* same directory */
|
* same directory */
|
||||||
|
@ -583,9 +584,134 @@ void Scumm::playSfxSound(void *sound, uint32 size, uint rate)
|
||||||
|
|
||||||
void Scumm::playSfxSound_MP3(void *sound, uint32 size)
|
void Scumm::playSfxSound_MP3(void *sound, uint32 size)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef COMPRESSED_SOUND_FILE
|
#ifdef COMPRESSED_SOUND_FILE
|
||||||
|
|
||||||
_mixer->play_mp3(NULL, sound, size, SoundMixer::FLAG_AUTOFREE);
|
_mixer->play_mp3(NULL, sound, size, SoundMixer::FLAG_AUTOFREE);
|
||||||
#else
|
|
||||||
error("Should never happen !!!");
|
|
||||||
#endif
|
#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; i<CACHE_TRACKS; i++)
|
||||||
|
if (_cached_tracks[i] == track) {
|
||||||
|
if (_mp3_tracks[i])
|
||||||
|
return i;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
current_index = _current_cache++;
|
||||||
|
_current_cache %= CACHE_TRACKS;
|
||||||
|
// Not found, see if it exists
|
||||||
|
sprintf(track_name, "%strack%d.mp3", _gameDataPath, track);
|
||||||
|
file = fopen(track_name, "rb");
|
||||||
|
_cached_tracks[current_index] = track;
|
||||||
|
_mp3_tracks[current_index] = NULL;
|
||||||
|
if (!file) {
|
||||||
|
warning("Track %d not available in mp3 format", track);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Check the format and bitrate
|
||||||
|
mad_stream_init(&stream);
|
||||||
|
mad_frame_init(&frame);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (buflen < sizeof(buffer)) {
|
||||||
|
uint16 bytes;
|
||||||
|
|
||||||
|
bytes = fread(buffer + buflen, 1, sizeof(buffer) - buflen, file);
|
||||||
|
if (bytes <= 0) {
|
||||||
|
if (bytes == -1) {
|
||||||
|
warning("Invalid format for track %d", track);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buflen += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
mad_stream_buffer(&stream, buffer, buflen);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (mad_frame_decode(&frame, &stream) == -1) {
|
||||||
|
if (!MAD_RECOVERABLE(stream.error))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (stream.error != MAD_ERROR_BADCRC)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count++)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count || stream.error != MAD_ERROR_BUFLEN)
|
||||||
|
break;
|
||||||
|
|
||||||
|
memmove(buffer, stream.next_frame,
|
||||||
|
buflen = &buffer[buflen] - stream.next_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count)
|
||||||
|
memcpy(&_mad_header[current_index], &frame.header, sizeof(mad_header));
|
||||||
|
else {
|
||||||
|
warning("Invalid format for track %d", track);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mad_frame_finish(&frame);
|
||||||
|
mad_stream_finish(&stream);
|
||||||
|
// Get file size
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
_mp3_size[current_index] = ftell(file);
|
||||||
|
_mp3_tracks[current_index] = file;
|
||||||
|
if (!_mp3_buffer)
|
||||||
|
_mp3_buffer = malloc(MP3_BUFFER_SIZE);
|
||||||
|
|
||||||
|
return current_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::playMP3CDTrack(int track, int num_loops, int start, int delay) {
|
||||||
|
int index;
|
||||||
|
long offset;
|
||||||
|
float frame_size;
|
||||||
|
mad_timer_t duration;
|
||||||
|
|
||||||
|
if (!start && !delay) {
|
||||||
|
_mixer->stop(_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
|
237
sound/mixer.cpp
237
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) {
|
void SoundMixer::play_mp3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags) {
|
||||||
insert(handle, new Channel_MP3(this, sound, size, 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
|
#endif
|
||||||
|
|
||||||
void SoundMixer::mix(int16 *buf, uint len) {
|
void SoundMixer::mix(int16 *buf, uint len) {
|
||||||
|
@ -282,153 +287,139 @@ void SoundMixer::Channel_MP3::destroy() {
|
||||||
|
|
||||||
delete this;
|
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
|
#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)
|
if (!_initialized) {
|
||||||
{
|
int skip_loop;
|
||||||
} else if (type == MIXER_MP3_CDMUSIC) {
|
// just skipped
|
||||||
mad_fixed_t const *ch;
|
memset(_ptr, 0,_buffer_size + MAD_BUFFER_GUARD);
|
||||||
mad_timer_t frame_duration;
|
_size = fread(_ptr, 1, _buffer_size, _file);
|
||||||
static long last_pos = 0;
|
if (!_size) {
|
||||||
|
destroy();
|
||||||
if (!sound_data.mp3_cdmusic.playing)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
while (1) {
|
// Resync
|
||||||
|
mad_stream_buffer(&_stream,(unsigned char *)_ptr,_size);
|
||||||
// See if we just skipped
|
skip_loop = 2;
|
||||||
if (ftell(sound_data.mp3_cdmusic.file) != last_pos) {
|
while (skip_loop != 0) {
|
||||||
int skip_loop;
|
if (mad_frame_decode(&_frame,&_stream) == 0) {
|
||||||
|
/* Do not decrease duration - see if it's a problem */
|
||||||
// Read the new data
|
skip_loop--;
|
||||||
memset(_sfx_sound, 0,
|
if (skip_loop == 0) {
|
||||||
sound_data.mp3_cdmusic.buffer_size + MAD_BUFFER_GUARD);
|
mad_synth_frame(&_synth, &_frame);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
last_pos = ftell(sound_data.mp3_cdmusic.file);
|
} else {
|
||||||
// Resync
|
if (!MAD_RECOVERABLE(_stream.error)) {
|
||||||
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)) {
|
|
||||||
debug(1, "Unrecoverable error while skipping !");
|
debug(1, "Unrecoverable error while skipping !");
|
||||||
sound_data.mp3_cdmusic.playing = false;
|
destroy();
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We are supposed to be in synch
|
}
|
||||||
mad_frame_mute(&sound_data.mp3_cdmusic.frame);
|
// We are supposed to be in synch
|
||||||
mad_synth_mute(&sound_data.mp3_cdmusic.synth);
|
mad_frame_mute(&_frame);
|
||||||
// Resume decoding
|
mad_synth_mute(&_synth);
|
||||||
if (mad_frame_decode(&sound_data.mp3_cdmusic.frame,
|
// Resume decoding
|
||||||
&sound_data.mp3_cdmusic.stream) == 0) {
|
if (mad_frame_decode(&_frame,&_stream) == 0) {
|
||||||
sound_data.mp3_cdmusic.position =
|
_pos_in_frame = 0;
|
||||||
(unsigned char *)sound_data.mp3_cdmusic.stream.next_frame -
|
_initialized = true;
|
||||||
(unsigned char *)_sfx_sound;
|
}
|
||||||
sound_data.mp3_cdmusic.pos_in_frame = 0;
|
else {
|
||||||
} else {
|
debug(1, "Cannot resume decoding");
|
||||||
sound_data.mp3_cdmusic.playing = false;
|
destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get samples, play samples ...
|
|
||||||
|
|
||||||
ch = sound_data.mp3_cdmusic.synth.pcm.samples[0] +
|
while(1) {
|
||||||
sound_data.mp3_cdmusic.pos_in_frame;
|
// Get samples, play samples ...
|
||||||
while ((sound_data.mp3_cdmusic.pos_in_frame <
|
ch = _synth.pcm.samples[0] + _pos_in_frame;
|
||||||
sound_data.mp3_cdmusic.synth.pcm.length) && (len > 0)) {
|
while ((_pos_in_frame < _synth.pcm.length) && (len > 0)) {
|
||||||
*data++ += scale_sample(*ch++);
|
*data++ += scale_sample(*ch++);
|
||||||
len--;
|
len--;
|
||||||
sound_data.mp3_cdmusic.pos_in_frame++;
|
_pos_in_frame++;
|
||||||
}
|
}
|
||||||
if (len == 0) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
// See if we have finished
|
if (mad_frame_decode(&_frame, &_stream) == -1) {
|
||||||
// May be incorrect to check the size at the end of a frame but I suppose
|
if (_stream.error == MAD_ERROR_BUFLEN) {
|
||||||
// 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) {
|
|
||||||
int not_decoded;
|
int not_decoded;
|
||||||
|
|
||||||
if (!sound_data.mp3_cdmusic.stream.next_frame) {
|
if (!_stream.next_frame) {
|
||||||
memset(_sfx_sound, 0,
|
memset(_ptr, 0, _buffer_size + MAD_BUFFER_GUARD);
|
||||||
sound_data.mp3_cdmusic.buffer_size + MAD_BUFFER_GUARD);
|
_size =
|
||||||
sound_data.mp3_cdmusic.size =
|
fread(_ptr, 1, _buffer_size, _file);
|
||||||
fread(_sfx_sound, 1, sound_data.mp3_cdmusic.buffer_size,
|
|
||||||
sound_data.mp3_cdmusic.file);
|
|
||||||
sound_data.mp3_cdmusic.position = 0;
|
|
||||||
not_decoded = 0;
|
not_decoded = 0;
|
||||||
} else {
|
}
|
||||||
not_decoded = sound_data.mp3_cdmusic.stream.bufend -
|
else {
|
||||||
sound_data.mp3_cdmusic.stream.next_frame;
|
not_decoded = _stream.bufend - _stream.next_frame;
|
||||||
memcpy(_sfx_sound, sound_data.mp3_cdmusic.stream.next_frame,
|
memcpy(_ptr, _stream.next_frame, not_decoded);
|
||||||
not_decoded);
|
_size =
|
||||||
|
fread((unsigned char *)_ptr + not_decoded, 1,
|
||||||
sound_data.mp3_cdmusic.size =
|
_buffer_size - not_decoded, _file);
|
||||||
fread((unsigned char *)_sfx_sound + not_decoded, 1,
|
|
||||||
sound_data.mp3_cdmusic.buffer_size - not_decoded,
|
|
||||||
sound_data.mp3_cdmusic.file);
|
|
||||||
}
|
}
|
||||||
last_pos = ftell(sound_data.mp3_cdmusic.file);
|
_stream.error = MAD_ERROR_NONE;
|
||||||
sound_data.mp3_cdmusic.stream.error = MAD_ERROR_NONE;
|
|
||||||
// Restream
|
// Restream
|
||||||
mad_stream_buffer(&sound_data.mp3_cdmusic.stream,
|
mad_stream_buffer(&_stream, (unsigned char *)_ptr, _size + not_decoded);
|
||||||
(unsigned char *)_sfx_sound,
|
if (mad_frame_decode(&_frame, &_stream) == -1) {
|
||||||
sound_data.mp3_cdmusic.size + not_decoded);
|
|
||||||
if (mad_frame_decode
|
|
||||||
(&sound_data.mp3_cdmusic.frame,
|
|
||||||
&sound_data.mp3_cdmusic.stream) == -1) {
|
|
||||||
debug(1, "Error decoding after restream %d !",
|
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 !");
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,26 @@ private:
|
||||||
Channel_MP3(SoundMixer *mixer, void *sound, uint size, byte flags);
|
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
|
#endif
|
||||||
|
|
||||||
static void on_generate_samples(void *s, byte *samples, int len);
|
static void on_generate_samples(void *s, byte *samples, int len);
|
||||||
|
@ -81,11 +101,12 @@ public:
|
||||||
enum {
|
enum {
|
||||||
FLAG_AUTOFREE = 1,
|
FLAG_AUTOFREE = 1,
|
||||||
FLAG_UNSIGNED = 2, /* unsigned samples */
|
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);
|
void play_raw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags);
|
||||||
#ifdef COMPRESSED_SOUND_FILE
|
#ifdef COMPRESSED_SOUND_FILE
|
||||||
void play_mp3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags);
|
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
|
#endif
|
||||||
|
|
||||||
/* Premix procedure, useful when using fmopl adlib */
|
/* Premix procedure, useful when using fmopl adlib */
|
||||||
|
|
1
x11.cpp
1
x11.cpp
|
@ -25,7 +25,6 @@
|
||||||
#include "scumm.h"
|
#include "scumm.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "cdmusic.h"
|
#include "cdmusic.h"
|
||||||
#include "mp3_cd.h"
|
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue