Some work on the Bochs sound support.

- OPL3: Added support to change the samplerate of the generator.
- SDL sound: convert wave packet to 16 Bit signed stereo format.
- Increased the maximum size of a single wave packet for playbck/recording.
This commit is contained in:
Volker Ruppert 2015-01-22 20:28:14 +00:00
parent 55f7c7542b
commit add5b1e61d
6 changed files with 75 additions and 23 deletions

View File

@ -991,7 +991,7 @@ static void OPL_INLINE clipit16(Bit32s ival, Bit16s* outval)
opl_active = 1;
#endif
bx_bool adlib_getsample(Bit16s* sndptr, Bits numsamples)
bx_bool adlib_getsample(Bit16u rate, Bit16s* sndptr, Bits numsamples)
{
Bits i, endsamples;
op_type* cptr;
@ -1009,6 +1009,10 @@ bx_bool adlib_getsample(Bit16s* sndptr, Bits numsamples)
Bits samples_to_process = numsamples;
if (rate != (Bit16u)int_samplerate) {
adlib_init(rate);
}
for (Bits cursmp=0; cursmp<samples_to_process; cursmp+=endsamples) {
endsamples = samples_to_process-cursmp;
if (endsamples>BLOCKBUF_SIZE) endsamples = BLOCKBUF_SIZE;

View File

@ -204,7 +204,7 @@ static Bit32u generator_add; // should be a chip parameter
// general functions
void adlib_init(Bit32u samplerate);
void adlib_write(Bitu idx, Bit8u val);
bx_bool adlib_getsample(Bit16s* sndptr, Bits numsamples);
bx_bool adlib_getsample(Bit16u rate, Bit16s* sndptr, Bits numsamples);
Bitu adlib_reg_read(Bitu port);
void adlib_write_index(Bitu port, Bit8u val);

View File

@ -2364,7 +2364,7 @@ void bx_sb16_c::opl_settimermask(int value, int chipid)
Bit32u bx_sb16_c::fmopl_generator(Bit16u rate, Bit8u *buffer, Bit32u len)
{
bx_bool ret = adlib_getsample((Bit16s*)buffer, len / 4);
bx_bool ret = adlib_getsample(rate, (Bit16s*)buffer, len / 4);
return ret ? len : 0;
}

View File

@ -20,10 +20,9 @@
// Common code for sound lowlevel modules
// this is the size of a sound packet used for sending and receiving
// it should not be too large to avoid lag, and not too
// small to avoid unnecessary overhead.
#define BX_SOUNDLOW_WAVEPACKETSIZE 8192
// This is the maximum size of a wave data packet.
// It should be large enough for 0.1 seconds of playback or recording.
#define BX_SOUNDLOW_WAVEPACKETSIZE 19200
// Definitions for the output functions
#define BX_SOUNDLOW_OK 0

View File

@ -157,35 +157,83 @@ int bx_sound_sdl_c::waveready()
return BX_SOUNDLOW_OK;
}
void bx_sound_sdl_c::convert_wavedata(Bit8u *src, int srcsize, Bit8u *dst, int dstsize, bx_pcm_param_t *param)
{
int i, j;
Bit8u xor_val;
xor_val = (param->format & 1) ? 0x00 : 0x80;
if (param->bits == 16) {
if ((param->format & 1) && (param->channels == 2)) {
memcpy(dst, src, dstsize);
} else if (param->channels == 2) {
j = 0;
for (i = 0; i < srcsize; i+=2) {
dst[j++] = src[i];
dst[j++] = src[i+1] ^ xor_val;
}
} else {
j = 0;
for (i = 0; i < srcsize; i+=2) {
dst[j++] = src[i];
dst[j++] = src[i+1] ^ xor_val;
dst[j++] = src[i];
dst[j++] = src[i+1] ^ xor_val;
}
}
} else {
if (param->channels == 2) {
j = 0;
for (i = 0; i < srcsize; i++) {
dst[j++] = 0;
dst[j++] = src[i] ^ xor_val;
}
} else {
j = 0;
for (i = 0; i < srcsize; i++) {
dst[j++] = 0;
dst[j++] = src[i] ^ xor_val;
dst[j++] = 0;
dst[j++] = src[i] ^ xor_val;
}
}
}
}
int bx_sound_sdl_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *param)
{
int ret = BX_SOUNDLOW_OK;
int tmpsize;
int size;
int bsize, len2, ssize = 1;
if (memcmp(param, &pcm_param, sizeof(bx_pcm_param_t)) != 0) {
startwaveplayback(param->samplerate, param->bits, param->channels == 2,
param->format);
startwaveplayback(param->samplerate, 16, 1, 1);
pcm_param = *param;
}
len2 = length;
if (param->bits == 8) ssize = 2;
if (param->channels == 1) ssize *= 2;
len2 = length * ssize;
SDL_LockAudio();
if (WaveOpen) {
size = audio_buffer.optr - audio_buffer.iptr;
if (size <= 0) {
size += BX_SOUND_SDL_BUFSIZE;
bsize = audio_buffer.optr - audio_buffer.iptr;
if (bsize <= 0) {
bsize += BX_SOUND_SDL_BUFSIZE;
}
if (size < length) {
BX_ERROR(("SDL: audio buffer overflow: l=%d s=%d", length, size));
ret = BX_SOUNDLOW_ERR;
} else {
if ((audio_buffer.iptr + length) > BX_SOUND_SDL_BUFSIZE) {
if (bsize < len2) {
BX_ERROR(("SDL: audio buffer overflow: l=%d s=%d", len2, bsize));
len2 = (bsize > ssize) ? bsize - ssize : 0;
}
if (len2 > 0) {
if ((audio_buffer.iptr + len2) > BX_SOUND_SDL_BUFSIZE) {
tmpsize = BX_SOUND_SDL_BUFSIZE - audio_buffer.iptr;
memcpy(audio_buffer.data+audio_buffer.iptr, data, tmpsize);
memcpy(audio_buffer.data, data+tmpsize, length-tmpsize);
audio_buffer.iptr = length-tmpsize;
len2 -= tmpsize;
convert_wavedata(data, tmpsize/ssize, audio_buffer.data+audio_buffer.iptr, tmpsize, param);
convert_wavedata(data+tmpsize/ssize, len2/ssize, audio_buffer.data, len2, param);
audio_buffer.iptr = len2;
} else {
memcpy(audio_buffer.data+audio_buffer.iptr, data, length);
audio_buffer.iptr += length;
convert_wavedata(data, length, audio_buffer.data+audio_buffer.iptr, len2, param);
audio_buffer.iptr += len2;
}
}
} else {

View File

@ -45,6 +45,7 @@ public:
virtual void unregister_wave_callback(int callback_id);
void get_wave_data(Bit8u *stream, int len);
private:
void convert_wavedata(Bit8u *src, int srcsize, Bit8u *dst, int dstsize, bx_pcm_param_t *param);
bx_bool WaveOpen;
SDL_AudioSpec fmt;
int cb_count;