From 3b4c6ceb0f621b68a5a44922d7218987faedb10e Mon Sep 17 00:00:00 2001 From: Lionel Ulmer Date: Sat, 18 May 2002 14:53:19 +0000 Subject: [PATCH] Added infrastructure to support more than 8 bit signed / unsigned RAW mixers. Porters, beware, the default configuration is now 16 bit stereo instead of 16 mono as before (I changed X11 and SDL but no others). I did not add support for any other format yet, I will let Endy do it when he needs it :-) svn-id: r4348 --- sdl.cpp | 2 +- sound/mixer.cpp | 94 ++++++++++++++++++++++++++++++++++++++----------- sound/mixer.h | 9 +++-- x11.cpp | 11 +++--- 4 files changed, 85 insertions(+), 31 deletions(-) diff --git a/sdl.cpp b/sdl.cpp index 316fb2af59e..8ec7d2611c9 100644 --- a/sdl.cpp +++ b/sdl.cpp @@ -829,7 +829,7 @@ bool OSystem_SDL::set_sound_proc(void *param, SoundProc *proc, byte format) { desired.freq = SAMPLES_PER_SEC; desired.format = AUDIO_S16SYS; - desired.channels = 1; + desired.channels = 2; desired.samples = 2048; desired.callback = proc; desired.userdata = param; diff --git a/sound/mixer.cpp b/sound/mixer.cpp index 9473ddd69d0..a47965ca659 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -84,14 +84,20 @@ int SoundMixer::play_mp3_cdtrack(PlayingSoundHandle *handle, FILE* file, mad_tim void SoundMixer::mix(int16 *buf, uint len) { - if (_paused) + if (_paused) { + memset(buf, 0, 2 * len * sizeof(int16)); return; + } if (_premix_proc) { + int i; _premix_proc(_premix_param, buf, len); + for (i = (len - 1); i >= 0; i--) { + buf[2 * i] = buf[2 * i + 1] = buf[i]; + } } else { /* no premixer available, zero the buf out */ - memset(buf, 0, len * sizeof(int16)); + memset(buf, 0, 2 * len * sizeof(int16)); } /* now mix all channels */ @@ -101,7 +107,7 @@ void SoundMixer::mix(int16 *buf, uint len) { } void SoundMixer::on_generate_samples(void *s, byte *samples, int len) { - ((SoundMixer*)s)->mix((int16*)samples, len>>1); + ((SoundMixer*)s)->mix((int16*)samples, len>>2); } bool SoundMixer::bind_to_system(OSystem *syst) { @@ -207,6 +213,64 @@ void SoundMixer::Channel_RAW::append(void *data, uint32 len) { _mixer->_paused = false; /* Mix again now */ } +static void mix_signed_mono_8(int16 *data, uint len, byte **s_ptr, uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab) { + uint32 fp_pos = *fp_pos_ptr; + byte *s = *s_ptr; + do { + fp_pos += fp_speed; + *data++ += vol_tab[*s]; + *data++ += vol_tab[*s]; + s += fp_pos >> 16; + fp_pos &= 0x0000FFFF; + } while (--len); + + *fp_pos_ptr = fp_pos; + *s_ptr = s; +} +static void mix_unsigned_mono_8(int16 *data, uint len, byte **s_ptr, uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab) { + uint32 fp_pos = *fp_pos_ptr; + byte *s = *s_ptr; + do { + fp_pos += fp_speed; + *data++ += vol_tab[*s ^ 0x80]; + *data++ += vol_tab[*s ^ 0x80]; + s += fp_pos >> 16; + fp_pos &= 0x0000FFFF; + } while (--len); + + *fp_pos_ptr = fp_pos; + *s_ptr = s; +} +static void mix_signed_stereo_8(int16 *data, uint len, byte **s_ptr, uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab) { + warning("Mixing stereo signed 8 bit is not supported yet "); +} +static void mix_unsigned_stereo_8(int16 *data, uint len, byte **s_ptr, uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab) { + warning("Mixing stereo unsigned 8 bit is not supported yet "); +} +static void mix_signed_mono_16(int16 *data, uint len, byte **s_ptr, uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab) { + warning("Mixing mono signed 16 bit is not supported yet "); +} +static void mix_unsigned_mono_16(int16 *data, uint len, byte **s_ptr, uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab) { + warning("Mixing mono unsigned 16 bit is not supported yet "); +} +static void mix_signed_stereo_16(int16 *data, uint len, byte **s_ptr, uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab) { + warning("Mixing stereo signed 16 bit is not supported yet "); +} +static void mix_unsigned_stereo_16(int16 *data, uint len, byte **s_ptr, uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab) { + warning("Mixing stereo unsigned 16 bit is not supported yet "); +} + +static void (*mixer_helper_table[16])(int16 *data, uint len, byte **s_ptr, uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab) = { + mix_signed_mono_8, + mix_unsigned_mono_8, + mix_signed_stereo_8, + mix_unsigned_stereo_8, + mix_signed_mono_16, + mix_unsigned_mono_16, + mix_signed_stereo_16, + mix_unsigned_stereo_16 +}; + void SoundMixer::Channel_RAW::mix(int16 *data, uint len) { byte *s, *s_org = NULL; uint32 fp_pos; @@ -245,21 +309,7 @@ void SoundMixer::Channel_RAW::mix(int16 *data, uint len) { const uint32 fp_speed = _fp_speed; const int16 *vol_tab = _mixer->_volume_table; - if (_flags & FLAG_UNSIGNED) { - do { - fp_pos += fp_speed; - *data++ += vol_tab[*s ^ 0x80]; - s += fp_pos >> 16; - fp_pos &= 0x0000FFFF; - } while (--len); - } else { - do { - fp_pos += fp_speed; - *data++ += vol_tab[*s]; - s += fp_pos >> 16; - fp_pos &= 0x0000FFFF; - } while (--len); - } + mixer_helper_table[_flags & 0x07](data, len, &s, &fp_pos, fp_speed, vol_tab); _pos = s - (byte*) _ptr; _fp_pos = fp_pos; @@ -345,7 +395,9 @@ void SoundMixer::Channel_MP3::mix(int16 *data, uint len) { if (_silence_cut > 0) { _silence_cut--; } else { - *data++ += (int16) ((scale_sample(*ch++) * volume) / 32); + int16 sample = (int16) ((scale_sample(*ch++) * volume) / 32); + *data++ += sample; + *data++ += sample; len--; } _pos_in_frame++; @@ -463,7 +515,9 @@ void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len) { // Get samples, play samples ... ch = _synth.pcm.samples[0] + _pos_in_frame; while ((_pos_in_frame < _synth.pcm.length) && (len > 0)) { - *data++ += (int16) ((scale_sample(*ch++) * volume) / 32); + int16 sample = (int16) ((scale_sample(*ch++) * volume) / 32); + *data++ += sample; + *data++ += sample; len--; _pos_in_frame++; } diff --git a/sound/mixer.h b/sound/mixer.h index 2e88fbe96b6..fc9d687f155 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -131,9 +131,12 @@ public: /* start playing a raw sound */ enum { - FLAG_AUTOFREE = 1, - FLAG_UNSIGNED = 2, /* unsigned samples */ - FLAG_FILE = 4, /* sound is a FILE * that's read from */ + /* Do *NOT* change any of these flags without looking at the code in mixer.cpp */ + FLAG_UNSIGNED = 1, /* unsigned samples */ + FLAG_STEREO = 2, /* sound is in stereo */ + FLAG_16BITS = 4, /* sound is 16 bits wide */ + FLAG_AUTOFREE = 8, /* sound buffer is freed automagically at the end of playing */ + FLAG_FILE = 16, /* sound is a FILE * that's read from */ }; int play_raw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags); #ifdef COMPRESSED_SOUND_FILE diff --git a/x11.cpp b/x11.cpp index e88a298f6db..b33c0c89e40 100644 --- a/x11.cpp +++ b/x11.cpp @@ -256,21 +256,18 @@ static void *sound_and_music_thread(void *params) sched_yield(); while (1) { - unsigned short *buf = (unsigned short *)sound_buffer; + unsigned char *buf = (unsigned char *)sound_buffer; int size, written; - sound_proc(proc_param, (byte *)sound_buffer, FRAG_SIZE >> 1); - /* Now convert to stereo */ - for (int i = ((FRAG_SIZE >> 2) - 1); i >= 0; i--) { - buf[2 * i + 1] = buf[2 * i] = buf[i]; - } + sound_proc(proc_param, (byte *)sound_buffer, FRAG_SIZE); #ifdef CAPTURE_SOUND fwrite(buf, 2, FRAG_SIZE >> 1, f); fflush(f); #endif size = FRAG_SIZE; while (size > 0) { - written = write(sound_fd, sound_buffer, size); + written = write(sound_fd, buf, size); + buf += written; size -= written; } }