renamed Sound -> BaseSound to avoid conflicts with the scumm class of the same name (we really should start to put all the Scumm/Simon/Sky code into namespaces
svn-id: r8508
This commit is contained in:
parent
7f7ce14d5e
commit
9ef0657c5c
2 changed files with 184 additions and 184 deletions
362
simon/sound.cpp
362
simon/sound.cpp
|
@ -22,38 +22,208 @@
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
#include "common/engine.h"
|
#include "common/engine.h"
|
||||||
|
|
||||||
class Sound {
|
class BaseSound {
|
||||||
protected:
|
protected:
|
||||||
File *_file;
|
File *_file;
|
||||||
uint32 *_offsets;
|
uint32 *_offsets;
|
||||||
SoundMixer *_mixer;
|
SoundMixer *_mixer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Sound(SoundMixer *mixer, File *file, uint32 base = 0);
|
BaseSound(SoundMixer *mixer, File *file, uint32 base = 0);
|
||||||
Sound(SoundMixer *mixer, File *file, uint32 *offsets);
|
BaseSound(SoundMixer *mixer, File *file, uint32 *offsets);
|
||||||
virtual ~Sound() { delete _file; }
|
virtual ~BaseSound() { delete _file; }
|
||||||
virtual int playSound(uint sound, PlayingSoundHandle *handle, byte flags = 0) = 0;
|
virtual int playSound(uint sound, PlayingSoundHandle *handle, byte flags = 0) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WavSound : public Sound {
|
class WavSound : public BaseSound {
|
||||||
public:
|
public:
|
||||||
WavSound(SoundMixer *mixer, File *file, uint32 base = 0) : Sound(mixer, file, base) {};
|
WavSound(SoundMixer *mixer, File *file, uint32 base = 0) : BaseSound(mixer, file, base) {};
|
||||||
WavSound(SoundMixer *mixer, File *file, uint32 *offsets) : Sound(mixer, file, offsets) {};
|
WavSound(SoundMixer *mixer, File *file, uint32 *offsets) : BaseSound(mixer, file, offsets) {};
|
||||||
int playSound(uint sound, PlayingSoundHandle *handle, byte flags = 0);
|
int playSound(uint sound, PlayingSoundHandle *handle, byte flags = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
class VocSound : public Sound {
|
class VocSound : public BaseSound {
|
||||||
public:
|
public:
|
||||||
VocSound(SoundMixer *mixer, File *file, uint32 base = 0) : Sound(mixer, file, base) {};
|
VocSound(SoundMixer *mixer, File *file, uint32 base = 0) : BaseSound(mixer, file, base) {};
|
||||||
int playSound(uint sound, PlayingSoundHandle *handle, byte flags = 0);
|
int playSound(uint sound, PlayingSoundHandle *handle, byte flags = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MP3Sound : public Sound {
|
class MP3Sound : public BaseSound {
|
||||||
public:
|
public:
|
||||||
MP3Sound(SoundMixer *mixer, File *file, uint32 base = 0) : Sound(mixer, file, base) {};
|
MP3Sound(SoundMixer *mixer, File *file, uint32 base = 0) : BaseSound(mixer, file, base) {};
|
||||||
int playSound(uint sound, PlayingSoundHandle *handle, byte flags = 0);
|
int playSound(uint sound, PlayingSoundHandle *handle, byte flags = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BaseSound::BaseSound(SoundMixer *mixer, File *file, uint32 base) {
|
||||||
|
_mixer = mixer;
|
||||||
|
_file = file;
|
||||||
|
|
||||||
|
uint res = 0;
|
||||||
|
uint32 size;
|
||||||
|
|
||||||
|
_file->seek(base + sizeof(uint32), SEEK_SET);
|
||||||
|
size = _file->readUint32LE();
|
||||||
|
|
||||||
|
res = size / sizeof(uint32);
|
||||||
|
|
||||||
|
_offsets = (uint32 *)malloc(size + sizeof(uint32));
|
||||||
|
|
||||||
|
_file->seek(base, SEEK_SET);
|
||||||
|
|
||||||
|
if (_file->read(_offsets, size) != size)
|
||||||
|
error("Can't read offsets");
|
||||||
|
|
||||||
|
for (uint i = 0; i < res; i++) {
|
||||||
|
#if defined(SCUMM_BIG_ENDIAN)
|
||||||
|
_offsets[i] = FROM_LE_32(_offsets[i]);
|
||||||
|
#endif
|
||||||
|
_offsets[i] += base;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only needed for mp3
|
||||||
|
_file->seek(0, SEEK_END);
|
||||||
|
_offsets[res] = _file->pos();
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseSound::BaseSound(SoundMixer *mixer, File *file, uint32 *offsets) {
|
||||||
|
_mixer = mixer;
|
||||||
|
_file = file;
|
||||||
|
_offsets = offsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(__GNUC__)
|
||||||
|
#pragma START_PACK_STRUCTS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct WaveHeader {
|
||||||
|
uint32 riff;
|
||||||
|
uint32 unk;
|
||||||
|
uint32 wave;
|
||||||
|
uint32 fmt;
|
||||||
|
|
||||||
|
uint32 size;
|
||||||
|
|
||||||
|
uint16 format_tag;
|
||||||
|
uint16 channels;
|
||||||
|
uint32 samples_per_sec;
|
||||||
|
uint32 avg_bytes;
|
||||||
|
|
||||||
|
uint16 block_align;
|
||||||
|
uint16 bits_per_sample;
|
||||||
|
} GCC_PACK;
|
||||||
|
|
||||||
|
struct VocHeader {
|
||||||
|
uint8 desc[20];
|
||||||
|
uint16 datablock_offset;
|
||||||
|
uint16 version;
|
||||||
|
uint16 id;
|
||||||
|
} GCC_PACK;
|
||||||
|
|
||||||
|
struct VocBlockHeader {
|
||||||
|
uint8 blocktype;
|
||||||
|
uint8 size[3];
|
||||||
|
uint8 sr;
|
||||||
|
uint8 pack;
|
||||||
|
} GCC_PACK;
|
||||||
|
|
||||||
|
#if !defined(__GNUC__)
|
||||||
|
#pragma END_PACK_STRUCTS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int WavSound::playSound(uint sound, PlayingSoundHandle *handle, byte flags) {
|
||||||
|
if (_offsets == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
WaveHeader wave_hdr;
|
||||||
|
uint32 data[2];
|
||||||
|
|
||||||
|
flags |= SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE;
|
||||||
|
|
||||||
|
_file->seek(_offsets[sound], SEEK_SET);
|
||||||
|
|
||||||
|
if (_file->read(&wave_hdr, sizeof(wave_hdr)) != sizeof(wave_hdr) ||
|
||||||
|
wave_hdr.riff != MKID('RIFF') || wave_hdr.wave != MKID('WAVE')
|
||||||
|
|| wave_hdr.fmt != MKID('fmt ') || READ_LE_UINT16(&wave_hdr.format_tag) != 1
|
||||||
|
|| READ_LE_UINT16(&wave_hdr.channels) != 1
|
||||||
|
|| READ_LE_UINT16(&wave_hdr.bits_per_sample) != 8) {
|
||||||
|
error("playWav(%d): can't read RIFF header", sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
_file->seek(FROM_LE_32(wave_hdr.size) - sizeof(wave_hdr) + 20, SEEK_CUR);
|
||||||
|
|
||||||
|
data[0] = _file->readUint32LE();
|
||||||
|
data[1] = _file->readUint32LE();
|
||||||
|
if (//fread(data, sizeof(data), 1, sound_file) != 1 ||
|
||||||
|
data[0] != 'atad') {
|
||||||
|
error("playWav(%d): can't read data header", sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *buffer = (byte *)malloc(data[1]);
|
||||||
|
_file->read(buffer, data[1]);
|
||||||
|
|
||||||
|
return _mixer->playRaw(handle, buffer, data[1], FROM_LE_32(wave_hdr.samples_per_sec), flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VocSound::playSound(uint sound, PlayingSoundHandle *handle, byte flags) {
|
||||||
|
if (_offsets == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
VocHeader voc_hdr;
|
||||||
|
VocBlockHeader voc_block_hdr;
|
||||||
|
uint32 size;
|
||||||
|
|
||||||
|
flags |= SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE;
|
||||||
|
|
||||||
|
_file->seek(_offsets[sound], SEEK_SET);
|
||||||
|
|
||||||
|
if (_file->read(&voc_hdr, sizeof(voc_hdr)) != sizeof(voc_hdr) ||
|
||||||
|
strncmp((char *)voc_hdr.desc, "Creative Voice File\x1A", 10) != 0) {
|
||||||
|
error("playVoc(%d): can't read voc header", sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
_file->read(&voc_block_hdr, sizeof(voc_block_hdr));
|
||||||
|
|
||||||
|
size = voc_block_hdr.size[0] + (voc_block_hdr.size[1] << 8) + (voc_block_hdr.size[2] << 16) - 2;
|
||||||
|
uint32 samples_per_sec;
|
||||||
|
|
||||||
|
/* workaround for voc weakness */
|
||||||
|
if (voc_block_hdr.sr == 0xa6) {
|
||||||
|
samples_per_sec = 11025;
|
||||||
|
} else if (voc_block_hdr.sr == 0xd2) {
|
||||||
|
samples_per_sec = 22050;
|
||||||
|
} else {
|
||||||
|
samples_per_sec = 1000000L / (256L - (long)voc_block_hdr.sr);
|
||||||
|
warning("inexact sample rate used: %i", samples_per_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *buffer = (byte *)malloc(size);
|
||||||
|
_file->read(buffer, size);
|
||||||
|
|
||||||
|
return _mixer->playRaw(handle, buffer, size, samples_per_sec, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_MAD
|
||||||
|
int MP3Sound::playSound(uint sound, PlayingSoundHandle *handle, byte flags)
|
||||||
|
{
|
||||||
|
if (_offsets == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
flags |= SoundMixer::FLAG_AUTOFREE;
|
||||||
|
|
||||||
|
_file->seek(_offsets[sound], SEEK_SET);
|
||||||
|
|
||||||
|
uint32 size = _offsets[sound+1] - _offsets[sound];
|
||||||
|
|
||||||
|
byte *buffer = (byte *)malloc(size);
|
||||||
|
_file->read(buffer, size);
|
||||||
|
|
||||||
|
return _mixer->playMP3(handle, buffer, size, flags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
SimonSound::SimonSound(const byte game, const GameSpecificSettings *gss, const char *gameDataPath, SoundMixer *mixer) {
|
SimonSound::SimonSound(const byte game, const GameSpecificSettings *gss, const char *gameDataPath, SoundMixer *mixer) {
|
||||||
_game = game;
|
_game = game;
|
||||||
|
@ -260,173 +430,3 @@ void SimonSound::ambientPause(bool b) {
|
||||||
playAmbient(tmp);
|
playAmbient(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
Sound::Sound(SoundMixer *mixer, File *file, uint32 base) {
|
|
||||||
_mixer = mixer;
|
|
||||||
_file = file;
|
|
||||||
|
|
||||||
uint res = 0;
|
|
||||||
uint32 size;
|
|
||||||
|
|
||||||
_file->seek(base + sizeof(uint32), SEEK_SET);
|
|
||||||
size = _file->readUint32LE();
|
|
||||||
|
|
||||||
res = size / sizeof(uint32);
|
|
||||||
|
|
||||||
_offsets = (uint32 *)malloc(size + sizeof(uint32));
|
|
||||||
|
|
||||||
_file->seek(base, SEEK_SET);
|
|
||||||
|
|
||||||
if (_file->read(_offsets, size) != size)
|
|
||||||
error("Can't read offsets");
|
|
||||||
|
|
||||||
for (uint i = 0; i < res; i++) {
|
|
||||||
#if defined(SCUMM_BIG_ENDIAN)
|
|
||||||
_offsets[i] = FROM_LE_32(_offsets[i]);
|
|
||||||
#endif
|
|
||||||
_offsets[i] += base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* only needed for mp3 */
|
|
||||||
_file->seek(0, SEEK_END);
|
|
||||||
_offsets[res] = _file->pos();
|
|
||||||
}
|
|
||||||
|
|
||||||
Sound::Sound(SoundMixer *mixer, File *file, uint32 *offsets) {
|
|
||||||
_mixer = mixer;
|
|
||||||
_file = file;
|
|
||||||
_offsets = offsets;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(__GNUC__)
|
|
||||||
#pragma START_PACK_STRUCTS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct WaveHeader {
|
|
||||||
uint32 riff;
|
|
||||||
uint32 unk;
|
|
||||||
uint32 wave;
|
|
||||||
uint32 fmt;
|
|
||||||
|
|
||||||
uint32 size;
|
|
||||||
|
|
||||||
uint16 format_tag;
|
|
||||||
uint16 channels;
|
|
||||||
uint32 samples_per_sec;
|
|
||||||
uint32 avg_bytes;
|
|
||||||
|
|
||||||
uint16 block_align;
|
|
||||||
uint16 bits_per_sample;
|
|
||||||
} GCC_PACK;
|
|
||||||
|
|
||||||
struct VocHeader {
|
|
||||||
uint8 desc[20];
|
|
||||||
uint16 datablock_offset;
|
|
||||||
uint16 version;
|
|
||||||
uint16 id;
|
|
||||||
} GCC_PACK;
|
|
||||||
|
|
||||||
struct VocBlockHeader {
|
|
||||||
uint8 blocktype;
|
|
||||||
uint8 size[3];
|
|
||||||
uint8 sr;
|
|
||||||
uint8 pack;
|
|
||||||
} GCC_PACK;
|
|
||||||
|
|
||||||
#if !defined(__GNUC__)
|
|
||||||
#pragma END_PACK_STRUCTS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_MAD
|
|
||||||
int MP3Sound::playSound(uint sound, PlayingSoundHandle *handle, byte flags)
|
|
||||||
{
|
|
||||||
if (_offsets == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
flags |= SoundMixer::FLAG_AUTOFREE;
|
|
||||||
|
|
||||||
_file->seek(_offsets[sound], SEEK_SET);
|
|
||||||
|
|
||||||
uint32 size = _offsets[sound+1] - _offsets[sound];
|
|
||||||
|
|
||||||
byte *buffer = (byte *)malloc(size);
|
|
||||||
_file->read(buffer, size);
|
|
||||||
|
|
||||||
return _mixer->playMP3(handle, buffer, size, flags);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int VocSound::playSound(uint sound, PlayingSoundHandle *handle, byte flags) {
|
|
||||||
if (_offsets == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
VocHeader voc_hdr;
|
|
||||||
VocBlockHeader voc_block_hdr;
|
|
||||||
uint32 size;
|
|
||||||
|
|
||||||
flags |= SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE;
|
|
||||||
|
|
||||||
_file->seek(_offsets[sound], SEEK_SET);
|
|
||||||
|
|
||||||
if (_file->read(&voc_hdr, sizeof(voc_hdr)) != sizeof(voc_hdr) ||
|
|
||||||
strncmp((char *)voc_hdr.desc, "Creative Voice File\x1A", 10) != 0) {
|
|
||||||
error("playVoc(%d): can't read voc header", sound);
|
|
||||||
}
|
|
||||||
|
|
||||||
_file->read(&voc_block_hdr, sizeof(voc_block_hdr));
|
|
||||||
|
|
||||||
size = voc_block_hdr.size[0] + (voc_block_hdr.size[1] << 8) + (voc_block_hdr.size[2] << 16) - 2;
|
|
||||||
uint32 samples_per_sec;
|
|
||||||
|
|
||||||
/* workaround for voc weakness */
|
|
||||||
if (voc_block_hdr.sr == 0xa6) {
|
|
||||||
samples_per_sec = 11025;
|
|
||||||
} else if (voc_block_hdr.sr == 0xd2) {
|
|
||||||
samples_per_sec = 22050;
|
|
||||||
} else {
|
|
||||||
samples_per_sec = 1000000L / (256L - (long)voc_block_hdr.sr);
|
|
||||||
warning("inexact sample rate used: %i", samples_per_sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte *buffer = (byte *)malloc(size);
|
|
||||||
_file->read(buffer, size);
|
|
||||||
|
|
||||||
return _mixer->playRaw(handle, buffer, size, samples_per_sec, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int WavSound::playSound(uint sound, PlayingSoundHandle *handle, byte flags) {
|
|
||||||
if (_offsets == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
WaveHeader wave_hdr;
|
|
||||||
uint32 data[2];
|
|
||||||
|
|
||||||
flags |= SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE;
|
|
||||||
|
|
||||||
_file->seek(_offsets[sound], SEEK_SET);
|
|
||||||
|
|
||||||
if (_file->read(&wave_hdr, sizeof(wave_hdr)) != sizeof(wave_hdr) ||
|
|
||||||
wave_hdr.riff != MKID('RIFF') || wave_hdr.wave != MKID('WAVE')
|
|
||||||
|| wave_hdr.fmt != MKID('fmt ') || READ_LE_UINT16(&wave_hdr.format_tag) != 1
|
|
||||||
|| READ_LE_UINT16(&wave_hdr.channels) != 1
|
|
||||||
|| READ_LE_UINT16(&wave_hdr.bits_per_sample) != 8) {
|
|
||||||
error("playWav(%d): can't read RIFF header", sound);
|
|
||||||
}
|
|
||||||
|
|
||||||
_file->seek(FROM_LE_32(wave_hdr.size) - sizeof(wave_hdr) + 20, SEEK_CUR);
|
|
||||||
|
|
||||||
data[0] = _file->readUint32LE();
|
|
||||||
data[1] = _file->readUint32LE();
|
|
||||||
if (//fread(data, sizeof(data), 1, sound_file) != 1 ||
|
|
||||||
data[0] != 'atad') {
|
|
||||||
error("playWav(%d): can't read data header", sound);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte *buffer = (byte *)malloc(data[1]);
|
|
||||||
_file->read(buffer, data[1]);
|
|
||||||
|
|
||||||
return _mixer->playRaw(handle, buffer, data[1], FROM_LE_32(wave_hdr.samples_per_sec), flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "sound/mixer.h"
|
#include "sound/mixer.h"
|
||||||
#include "simon/intern.h"
|
#include "simon/intern.h"
|
||||||
|
|
||||||
class Sound;
|
class BaseSound;
|
||||||
|
|
||||||
class SimonSound {
|
class SimonSound {
|
||||||
private:
|
private:
|
||||||
|
@ -32,8 +32,8 @@ private:
|
||||||
int _voice_index;
|
int _voice_index;
|
||||||
int _ambient_index;
|
int _ambient_index;
|
||||||
|
|
||||||
Sound *_voice;
|
BaseSound *_voice;
|
||||||
Sound *_effects;
|
BaseSound *_effects;
|
||||||
|
|
||||||
bool _effects_paused;
|
bool _effects_paused;
|
||||||
bool _ambient_paused;
|
bool _ambient_paused;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue