mirror of
https://github.com/libretro/scummvm.git
synced 2024-11-27 19:30:41 +00:00
patch #628997 support for ogg vorbis instead of cd tracks by Daniel Schepler. Uncomment the relevant lines in the makefile to use
svn-id: r5320
This commit is contained in:
parent
f89b40f027
commit
d93e639086
6
Makefile
6
Makefile
@ -36,9 +36,13 @@ OBJS =
|
||||
# DEFINES += -DDUMP_SCRIPTS
|
||||
|
||||
# Uncomment this to activate the MAD lib for compressed sound files
|
||||
DEFINES += -DCOMPRESSED_SOUND_FILE
|
||||
DEFINES += -DUSE_MAD
|
||||
LIBS += -lmad
|
||||
|
||||
# Uncomment this to activate the Ogg Vorbis lib for compressed sound files
|
||||
# DEFINES += -DUSE_VORBIS
|
||||
# LIBS += -lvorbisfile -lvorbis
|
||||
|
||||
# Uncomment this to activate the ALSA lib for midi
|
||||
# DEFINES += -DUSE_ALSA
|
||||
# LIBS += -lasound
|
||||
|
@ -31,6 +31,10 @@ typedef int bool;
|
||||
const bool true(1), false(0);
|
||||
#endif /* HAVE_NO_BOOL */
|
||||
|
||||
#if defined(USE_MAD) || defined(USE_VORBIS)
|
||||
#define COMPRESSED_SOUND_FILE
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
//#pragma warning (disable: 4244)
|
||||
|
318
scumm/sound.cpp
318
scumm/sound.cpp
@ -738,7 +738,7 @@ int Sound::startSfxSound(File *file, int file_size) {
|
||||
int rate, comp;
|
||||
byte *data;
|
||||
|
||||
#ifdef COMPRESSED_SOUND_FILE
|
||||
#ifdef USE_MAD
|
||||
if (file_size > 0) {
|
||||
data = (byte *)calloc(file_size + MAD_BUFFER_GUARD, 1);
|
||||
|
||||
@ -1116,7 +1116,7 @@ int Sound::playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned) {
|
||||
}
|
||||
|
||||
int Sound::playSfxSound_MP3(void *sound, uint32 size) {
|
||||
#ifdef COMPRESSED_SOUND_FILE
|
||||
#ifdef USE_MAD
|
||||
if (_soundsPaused)
|
||||
return -1;
|
||||
return _scumm->_mixer->playMP3(NULL, sound, size, SoundMixer::FLAG_AUTOFREE);
|
||||
@ -1219,16 +1219,11 @@ int Sound::getCachedTrack(int track) {
|
||||
char track_name[1024];
|
||||
File * file = new File();
|
||||
int current_index;
|
||||
struct mad_stream stream;
|
||||
struct mad_frame frame;
|
||||
unsigned char buffer[8192];
|
||||
unsigned int buflen = 0;
|
||||
int count = 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])
|
||||
if (_track_info[i])
|
||||
return i;
|
||||
else
|
||||
return -1;
|
||||
@ -1237,21 +1232,119 @@ int Sound::getCachedTrack(int track) {
|
||||
_current_cache %= CACHE_TRACKS;
|
||||
|
||||
// Not found, see if it exists
|
||||
sprintf(track_name, "track%d.mp3", track);
|
||||
file->open(track_name, _scumm->getGameDataPath());
|
||||
|
||||
// First, delete the previous track info object
|
||||
delete _track_info[current_index];
|
||||
_track_info[current_index] = NULL;
|
||||
|
||||
_cached_tracks[current_index] = track;
|
||||
|
||||
/* First, close the previous file */
|
||||
if (_mp3_tracks[current_index])
|
||||
_mp3_tracks[current_index]->close();
|
||||
#ifdef USE_MAD
|
||||
sprintf(track_name, "track%d.mp3", track);
|
||||
file->open(track_name, _scumm->getGameDataPath());
|
||||
|
||||
_mp3_tracks[current_index] = NULL;
|
||||
if (file->isOpen() == false) {
|
||||
// This warning is pretty pointless.
|
||||
debug(1, "Track %d not available in mp3 format", track);
|
||||
if (file->isOpen()) {
|
||||
_track_info[current_index] = new MP3TrackInfo(file);
|
||||
if (_track_info[current_index]->error()) {
|
||||
delete _track_info[current_index];
|
||||
_track_info[current_index] = NULL;
|
||||
return -1;
|
||||
}
|
||||
return current_index;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_VORBIS
|
||||
sprintf(track_name, "track%d.ogg", track);
|
||||
file->open(track_name, _scumm->getGameDataPath());
|
||||
|
||||
if (file->isOpen()) {
|
||||
_track_info[current_index] = new VorbisTrackInfo(file);
|
||||
if (_track_info[current_index]->error()) {
|
||||
delete _track_info[current_index];
|
||||
_track_info[current_index] = NULL;
|
||||
return -1;
|
||||
}
|
||||
return current_index;
|
||||
}
|
||||
#endif
|
||||
|
||||
debug(1, "Track %d not available in compressed format", track);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Sound::playMP3CDTrack(int track, int num_loops, int start, int delay) {
|
||||
int index;
|
||||
_scumm->_vars[_scumm->VAR_MI1_TIMER] = 0;
|
||||
|
||||
if (_soundsPaused)
|
||||
return 0;
|
||||
|
||||
if ((num_loops == 0) && (start == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
index = getCachedTrack(track);
|
||||
if (index < 0)
|
||||
return -1;
|
||||
|
||||
if (_dig_cd_playing)
|
||||
_scumm->_mixer->stop(_dig_cd_index);
|
||||
_dig_cd_index = _track_info[index]->play(_scumm->_mixer, start, delay);
|
||||
_dig_cd_playing = true;
|
||||
_dig_cd_track = track;
|
||||
_dig_cd_num_loops = num_loops;
|
||||
_dig_cd_start = start;
|
||||
_dig_cd_delay = delay;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Sound::stopMP3CD() {
|
||||
if (_dig_cd_playing == true) {
|
||||
_scumm->_mixer->stop(_dig_cd_index);
|
||||
_dig_cd_playing = false;
|
||||
_dig_cd_track = 0;
|
||||
_dig_cd_num_loops = 0;
|
||||
_dig_cd_start = 0;
|
||||
_dig_cd_delay = 0;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Sound::pollMP3CD() {
|
||||
if (_dig_cd_playing == true)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Sound::updateMP3CD() {
|
||||
if (_dig_cd_playing == false)
|
||||
return -1;
|
||||
|
||||
if (_scumm->_mixer->_channels[_dig_cd_index] == NULL) {
|
||||
warning("Error in MP3 decoding");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_scumm->_mixer->_channels[_dig_cd_index]->soundFinished()) {
|
||||
if (_dig_cd_num_loops == -1 || --_dig_cd_num_loops > 0)
|
||||
playMP3CDTrack(_dig_cd_track, _dig_cd_num_loops, _dig_cd_start, _dig_cd_delay);
|
||||
else
|
||||
stopMP3CD();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_MAD
|
||||
Sound::MP3TrackInfo::MP3TrackInfo(File *file) {
|
||||
struct mad_stream stream;
|
||||
struct mad_frame frame;
|
||||
unsigned char buffer[8192];
|
||||
unsigned int buflen = 0;
|
||||
int count = 0;
|
||||
|
||||
// Check the format and bitrate
|
||||
mad_stream_init(&stream);
|
||||
mad_frame_init(&frame);
|
||||
@ -1263,7 +1356,7 @@ int Sound::getCachedTrack(int track) {
|
||||
bytes = file->read(buffer + buflen, sizeof(buffer) - buflen);
|
||||
if (bytes <= 0) {
|
||||
if (bytes == -1) {
|
||||
warning("Invalid format for track %d", track);
|
||||
warning("Invalid file format");
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
@ -1295,105 +1388,154 @@ int Sound::getCachedTrack(int track) {
|
||||
}
|
||||
|
||||
if (count)
|
||||
memcpy(&_mad_header[current_index], &frame.header, sizeof(mad_header));
|
||||
memcpy(&_mad_header, &frame.header, sizeof(mad_header));
|
||||
else {
|
||||
warning("Invalid format for track %d", track);
|
||||
warning("Invalid file format");
|
||||
goto error;
|
||||
}
|
||||
|
||||
mad_frame_finish(&frame);
|
||||
mad_stream_finish(&stream);
|
||||
// Get file size
|
||||
_mp3_size[current_index] = file->size();
|
||||
_mp3_tracks[current_index] = file;
|
||||
|
||||
return current_index;
|
||||
_size = file->size();
|
||||
_file = file;
|
||||
_error_flag = false;
|
||||
return;
|
||||
|
||||
error:
|
||||
mad_frame_finish(&frame);
|
||||
mad_stream_finish(&stream);
|
||||
_error_flag = true;
|
||||
delete file;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Sound::playMP3CDTrack(int track, int num_loops, int start, int delay) {
|
||||
int index;
|
||||
int Sound::MP3TrackInfo::play(SoundMixer *mixer, int start, int delay) {
|
||||
unsigned int offset;
|
||||
mad_timer_t duration;
|
||||
_scumm->_vars[_scumm->VAR_MI1_TIMER] = 0;
|
||||
|
||||
if (_soundsPaused)
|
||||
return 0;
|
||||
|
||||
if ((num_loops == 0) && (start == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
index = getCachedTrack(track);
|
||||
if (index < 0)
|
||||
return -1;
|
||||
|
||||
// Calc offset. As all bitrates are in kilobit per seconds, the division by 200 is always exact
|
||||
offset = (start * (_mad_header[index].bitrate / (8 * 25))) / 3;
|
||||
offset = (start * (_mad_header.bitrate / (8 * 25))) / 3;
|
||||
|
||||
// Calc delay
|
||||
if (!delay) {
|
||||
mad_timer_set(&duration, (_mp3_size[index] * 8) / _mad_header[index].bitrate,
|
||||
(_mp3_size[index] * 8) % _mad_header[index].bitrate, _mad_header[index].bitrate);
|
||||
mad_timer_set(&duration, (_size * 8) / _mad_header.bitrate,
|
||||
(_size * 8) % _mad_header.bitrate, _mad_header.bitrate);
|
||||
} else {
|
||||
mad_timer_set(&duration, delay / 75, delay % 75, 75);
|
||||
}
|
||||
|
||||
// Go
|
||||
_mp3_tracks[index]->seek(offset, SEEK_SET);
|
||||
_file->seek(offset, SEEK_SET);
|
||||
|
||||
if (_mp3_cd_playing == true)
|
||||
_scumm->_mixer->stop(_mp3_index);
|
||||
_mp3_index = _scumm->_mixer->playMP3CDTrack(NULL, _mp3_tracks[index], duration);
|
||||
_mp3_cd_playing = true;
|
||||
_mp3_cd_track = track;
|
||||
_mp3_cd_num_loops = num_loops;
|
||||
_mp3_cd_start = start;
|
||||
_mp3_cd_delay = delay;
|
||||
return 0;
|
||||
return mixer->playMP3CDTrack(NULL, _file, duration);
|
||||
}
|
||||
|
||||
int Sound::stopMP3CD() {
|
||||
if (_mp3_cd_playing == true) {
|
||||
_scumm->_mixer->stop(_mp3_index);
|
||||
_mp3_cd_playing = false;
|
||||
_mp3_cd_track = 0;
|
||||
_mp3_cd_num_loops = 0;
|
||||
_mp3_cd_start = 0;
|
||||
_mp3_cd_delay = 0;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
Sound::MP3TrackInfo::~MP3TrackInfo() {
|
||||
if (! _error_flag)
|
||||
_file->close();
|
||||
}
|
||||
|
||||
int Sound::pollMP3CD() {
|
||||
if (_mp3_cd_playing == true)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Sound::updateMP3CD() {
|
||||
if (_mp3_cd_playing == false)
|
||||
return -1;
|
||||
|
||||
if (_scumm->_mixer->_channels[_mp3_index] == NULL) {
|
||||
warning("Error in MP3 decoding");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_scumm->_mixer->_channels[_mp3_index]->soundFinished()) {
|
||||
if (_mp3_cd_num_loops == -1 || --_mp3_cd_num_loops > 0)
|
||||
playMP3CDTrack(_mp3_cd_track, _mp3_cd_num_loops, _mp3_cd_start, _mp3_cd_delay);
|
||||
else
|
||||
stopMP3CD();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_VORBIS
|
||||
// These are wrapper functions to allow using a File object to
|
||||
// provide data to the OggVorbis_File object.
|
||||
|
||||
struct file_info {
|
||||
File *file;
|
||||
int start, curr_pos;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static size_t read_wrap(void *ptr, size_t size, size_t nmemb, void *datasource) {
|
||||
file_info *f = (file_info *) datasource;
|
||||
int result;
|
||||
|
||||
nmemb *= size;
|
||||
if (f->curr_pos > (int) f->len)
|
||||
nmemb = 0;
|
||||
else if (nmemb > f->len - f->curr_pos)
|
||||
nmemb = f->len - f->curr_pos;
|
||||
result = f->file->read(ptr, nmemb);
|
||||
if (result == -1) {
|
||||
f->curr_pos = f->file->pos() - f->start;
|
||||
return (size_t) -1;
|
||||
}
|
||||
else {
|
||||
f->curr_pos += result;
|
||||
return result / size;
|
||||
}
|
||||
}
|
||||
|
||||
static int seek_wrap(void *datasource, ogg_int64_t offset, int whence) {
|
||||
file_info *f = (file_info *) datasource;
|
||||
|
||||
if (whence == SEEK_SET)
|
||||
offset += f->start;
|
||||
else if (whence == SEEK_END) {
|
||||
offset += f->start + f->len;
|
||||
whence = SEEK_SET;
|
||||
}
|
||||
|
||||
f->file->seek(offset, whence);
|
||||
f->curr_pos = f->file->pos() - f->start;
|
||||
return f->curr_pos;
|
||||
}
|
||||
|
||||
static int close_wrap(void *datasource) {
|
||||
file_info *f = (file_info *) datasource;
|
||||
|
||||
f->file->close();
|
||||
delete f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long tell_wrap(void *datasource) {
|
||||
file_info *f = (file_info *) datasource;
|
||||
|
||||
return f->file->pos();
|
||||
}
|
||||
|
||||
static ov_callbacks File_wrap = {
|
||||
read_wrap, seek_wrap, close_wrap, tell_wrap
|
||||
};
|
||||
|
||||
Sound::VorbisTrackInfo::VorbisTrackInfo(File *file) {
|
||||
file_info *f = new file_info;
|
||||
|
||||
f->file = file;
|
||||
f->start = 0;
|
||||
f->len = file->size();
|
||||
f->curr_pos = file->pos();
|
||||
|
||||
if (ov_open_callbacks((void *) f, &_ov_file, NULL, 0, File_wrap) < 0) {
|
||||
warning("Invalid file format");
|
||||
_error_flag = true;
|
||||
delete f;
|
||||
delete file;
|
||||
}
|
||||
else {
|
||||
_error_flag = false;
|
||||
_file = file;
|
||||
|
||||
// Check the file format
|
||||
if (ov_info(&_ov_file, -1)->rate != 22050)
|
||||
warning("Vorbis code currently only supports files encoded at 22050 Hz");
|
||||
}
|
||||
}
|
||||
|
||||
int Sound::VorbisTrackInfo::play(SoundMixer *mixer, int start, int delay) {
|
||||
ov_time_seek(&_ov_file, start / 75.0);
|
||||
return mixer->playVorbisCDTrack(NULL, &_ov_file, delay / 75.0);
|
||||
}
|
||||
|
||||
Sound::VorbisTrackInfo::~VorbisTrackInfo() {
|
||||
if (! _error_flag) {
|
||||
ov_clear(&_ov_file);
|
||||
delete _file;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -65,24 +65,62 @@ enum {
|
||||
uint16 _mouthSyncTimes[52];
|
||||
uint _curSoundPos;
|
||||
|
||||
#ifdef COMPRESSED_SOUND_FILE
|
||||
MP3OffsetTable *offset_table; // SO3 MP3 compressed audio
|
||||
int num_sound_effects; // SO3 MP3 compressed audio
|
||||
#ifdef COMPRESSED_SOUND_FILE
|
||||
|
||||
#define CACHE_TRACKS 10
|
||||
|
||||
/* used for mp3 CD music */
|
||||
|
||||
int _cached_tracks[CACHE_TRACKS];
|
||||
struct mad_header _mad_header[CACHE_TRACKS];
|
||||
long _mp3_size[CACHE_TRACKS];
|
||||
File *_mp3_tracks[CACHE_TRACKS];
|
||||
int _mp3_index;
|
||||
int _mp3_cd_track;
|
||||
int _mp3_cd_start;
|
||||
int _mp3_cd_delay;
|
||||
int _mp3_cd_num_loops;
|
||||
bool _mp3_cd_playing;
|
||||
int _dig_cd_index;
|
||||
int _dig_cd_track;
|
||||
int _dig_cd_start;
|
||||
int _dig_cd_delay;
|
||||
int _dig_cd_num_loops;
|
||||
bool _dig_cd_playing;
|
||||
|
||||
class DigitalTrackInfo {
|
||||
public:
|
||||
virtual bool error() = 0;
|
||||
virtual int play(SoundMixer *mixer, int start, int delay) = 0;
|
||||
virtual ~DigitalTrackInfo() { }
|
||||
};
|
||||
|
||||
DigitalTrackInfo *_track_info[CACHE_TRACKS];
|
||||
|
||||
#ifdef USE_MAD
|
||||
class MP3TrackInfo : public DigitalTrackInfo {
|
||||
private:
|
||||
struct mad_header _mad_header;
|
||||
long _size;
|
||||
File *_file;
|
||||
bool _error_flag;
|
||||
|
||||
public:
|
||||
MP3TrackInfo(File *file);
|
||||
~MP3TrackInfo();
|
||||
bool error() { return _error_flag; }
|
||||
int play(SoundMixer *mixer, int start, int delay);
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_VORBIS
|
||||
class VorbisTrackInfo : public DigitalTrackInfo {
|
||||
private:
|
||||
File *_file;
|
||||
OggVorbis_File _ov_file;
|
||||
bool _error_flag;
|
||||
|
||||
public:
|
||||
VorbisTrackInfo(File *file);
|
||||
~VorbisTrackInfo();
|
||||
bool error() { return _error_flag; }
|
||||
int play(SoundMixer *mixer, int start, int delay);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Scumm * _scumm;
|
||||
|
100
sound/mixer.cpp
100
sound/mixer.cpp
@ -120,7 +120,7 @@ void SoundMixer::beginSlots(int index) {
|
||||
_beginSlots = index;
|
||||
}
|
||||
|
||||
#ifdef COMPRESSED_SOUND_FILE
|
||||
#ifdef USE_MAD
|
||||
int SoundMixer::playMP3(PlayingSoundHandle * handle, void *sound, uint32 size, byte flags) {
|
||||
for (int i = _beginSlots; i != NUM_CHANNELS; i++) {
|
||||
if (_channels[i] == NULL) {
|
||||
@ -144,6 +144,19 @@ int SoundMixer::playMP3CDTrack(PlayingSoundHandle * handle, File * file, mad_tim
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_VORBIS
|
||||
int SoundMixer::playVorbisCDTrack(PlayingSoundHandle * handle, OggVorbis_File * ov_file, double duration) {
|
||||
for (int i = _beginSlots; i != NUM_CHANNELS; i++) {
|
||||
if (_channels[i] == NULL) {
|
||||
return insertAt(handle, i, new ChannelVorbis(this, ov_file, duration));
|
||||
}
|
||||
}
|
||||
|
||||
warning("SoundMixer::out of mixer slots");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void SoundMixer::mix(int16 *buf, uint len) {
|
||||
if (_paused) {
|
||||
memset(buf, 0, 2 * len * sizeof(int16));
|
||||
@ -713,7 +726,7 @@ void SoundMixer::ChannelStream::realDestroy() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
#ifdef COMPRESSED_SOUND_FILE
|
||||
#ifdef USE_MAD
|
||||
SoundMixer::ChannelMP3::ChannelMP3(SoundMixer * mixer, void * sound, uint size, byte flags) {
|
||||
_mixer = mixer;
|
||||
_flags = flags;
|
||||
@ -962,3 +975,86 @@ void SoundMixer::ChannelMP3CDMusic::realDestroy() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_VORBIS
|
||||
SoundMixer::ChannelVorbis::ChannelVorbis(SoundMixer * mixer, OggVorbis_File * ov_file, double duration) {
|
||||
_mixer = mixer;
|
||||
_ov_file = ov_file;
|
||||
|
||||
if (duration)
|
||||
_end_pos = ov_time_tell(ov_file) + duration;
|
||||
else
|
||||
_end_pos = 0;
|
||||
|
||||
_eof_flag = false;
|
||||
_toBeDestroyed = false;
|
||||
}
|
||||
|
||||
void SoundMixer::ChannelVorbis::mix(int16 * data, uint len) {
|
||||
if (_toBeDestroyed) {
|
||||
realDestroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_eof_flag) {
|
||||
memset(data, 0, sizeof(int16) * 2 * len);
|
||||
return;
|
||||
}
|
||||
|
||||
int channels = ov_info(_ov_file, -1)->channels;
|
||||
uint len_left = len * channels * 2;
|
||||
int16 *samples = new int16[len_left / 2];
|
||||
char *read_pos = (char *) samples;
|
||||
int volume = _mixer->_musicVolume;
|
||||
|
||||
// Read the samples
|
||||
while (len_left > 0) {
|
||||
long result = ov_read(_ov_file, read_pos, len_left,
|
||||
#ifdef SCUMM_BIG_ENDIAN
|
||||
1,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
2, 1, NULL);
|
||||
if (result == 0) {
|
||||
_eof_flag = true;
|
||||
memset(read_pos, 0, len_left);
|
||||
break;
|
||||
}
|
||||
else if (result < 0) {
|
||||
debug(1, "Decode error %d in Vorbis file", result);
|
||||
// Don't delete it yet, that causes problems in
|
||||
// the CD player emulation code.
|
||||
_eof_flag = true;
|
||||
memset(read_pos, 0, len_left);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
len_left -= result;
|
||||
read_pos += result;
|
||||
}
|
||||
}
|
||||
|
||||
// Mix the samples in
|
||||
for (uint i = 0; i < len; i++) {
|
||||
int16 sample = (int16) ((int32) samples[i * channels] * volume / 256);
|
||||
*data++ += sample;
|
||||
if (channels > 1)
|
||||
sample = (int16) ((int32) samples[i * channels + 1] * volume / 256);
|
||||
*data++ += sample;
|
||||
}
|
||||
|
||||
delete [] samples;
|
||||
}
|
||||
|
||||
void SoundMixer::ChannelVorbis::realDestroy() {
|
||||
_mixer->unInsert(this);
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool SoundMixer::ChannelVorbis::soundFinished() {
|
||||
return _eof_flag || (_end_pos > 0 &&
|
||||
ov_time_tell(_ov_file) >= _end_pos);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -25,10 +25,14 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef COMPRESSED_SOUND_FILE
|
||||
#ifdef USE_MAD
|
||||
#include <mad.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_VORBIS
|
||||
#include <vorbis/vorbisfile.h>
|
||||
#endif
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
|
||||
@ -92,7 +96,7 @@ private:
|
||||
void realDestroy();
|
||||
};
|
||||
|
||||
#ifdef COMPRESSED_SOUND_FILE
|
||||
#ifdef USE_MAD
|
||||
|
||||
class ChannelMP3 : public Channel {
|
||||
SoundMixer * _mixer;
|
||||
@ -138,6 +142,22 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_VORBIS
|
||||
class ChannelVorbis : public Channel {
|
||||
SoundMixer * _mixer;
|
||||
OggVorbis_File * _ov_file;
|
||||
double _end_pos;
|
||||
bool _eof_flag;
|
||||
|
||||
public:
|
||||
ChannelVorbis(SoundMixer * mixer, OggVorbis_File * ov_file, double duration);
|
||||
|
||||
void mix(int16 * data, uint len);
|
||||
void realDestroy();
|
||||
bool soundFinished();
|
||||
};
|
||||
#endif
|
||||
|
||||
static void onGenerateSamples(void * s, byte * samples, int len);
|
||||
|
||||
public:
|
||||
@ -187,10 +207,13 @@ public:
|
||||
int playRaw(PlayingSoundHandle * handle, void * sound, uint32 size, uint rate, byte flags, int id);
|
||||
int playStream(PlayingSoundHandle * handle, int index, void * sound, uint32 size, uint rate,
|
||||
byte flags, int32 timeout = 3, int32 buffer_size = 2000000);
|
||||
#ifdef COMPRESSED_SOUND_FILE
|
||||
#ifdef USE_MAD
|
||||
int playMP3(PlayingSoundHandle * handle, void * sound, uint32 size, byte flags);
|
||||
int playMP3CDTrack(PlayingSoundHandle * handle, File * file, mad_timer_t duration);
|
||||
#endif
|
||||
#ifdef USE_VORBIS
|
||||
int playVorbisCDTrack(PlayingSoundHandle * handle, OggVorbis_File * ov_file, double duration);
|
||||
#endif
|
||||
|
||||
/* Premix procedure, useful when using fmopl adlib */
|
||||
void setupPremix(void * param, PremixProc * proc);
|
||||
|
Loading…
Reference in New Issue
Block a user