Mix sound sources in 32-bit buffer, then clip to 16-bit for output. Fixes overflow in some situations, eg MegaRace on SB16.

This commit is contained in:
SarahW 2016-05-22 16:04:19 +01:00
commit d2b6ea7fa3
15 changed files with 60 additions and 37 deletions

View file

@ -78,7 +78,7 @@ void sound_card_init()
static struct
{
void (*get_buffer)(int16_t *buffer, int len, void *p);
void (*get_buffer)(int32_t *buffer, int len, void *p);
void *priv;
} sound_handlers[8];
@ -157,20 +157,20 @@ static void sound_cd_thread(void *param)
}
}
static uint16_t *outbuffer;
static int32_t *outbuffer;
void sound_init()
{
initalmain(0,NULL);
inital();
outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int16_t));
outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int32_t));
sound_cd_event = thread_create_event();
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
}
void sound_add_handler(void (*get_buffer)(int16_t *buffer, int len, void *p), void *p)
void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p)
{
sound_handlers[sound_handlers_num].get_buffer = get_buffer;
sound_handlers[sound_handlers_num].priv = p;
@ -185,14 +185,26 @@ void sound_poll(void *priv)
if (sound_pos_global == SOUNDBUFLEN)
{
int c;
/* int16_t buf16[SOUNDBUFLEN * 2 ];*/
memset(outbuffer, 0, SOUNDBUFLEN * 2 * sizeof(int16_t));
memset(outbuffer, 0, SOUNDBUFLEN * 2 * sizeof(int32_t));
for (c = 0; c < sound_handlers_num; c++)
sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv);
/* if (!soundf) soundf=fopen("sound.pcm","wb");
fwrite(outbuffer,(SOUNDBUFLEN)*2*2,1,soundf);*/
/* for (c=0;c<SOUNDBUFLEN*2;c++)
{
if (outbuffer[c] < -32768)
buf16[c] = -32768;
else if (outbuffer[c] > 32767)
buf16[c] = 32767;
else
buf16[c] = outbuffer[c];
}
if (!soundf) soundf=fopen("sound.pcm","wb");
fwrite(buf16,(SOUNDBUFLEN)*2*2,1,soundf);*/
if (soundon) givealbuffer(outbuffer);

View file

@ -1,6 +1,6 @@
#include "timer.h"
void sound_add_handler(void (*get_buffer)(int16_t *buffer, int len, void *p), void *p);
void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p);
extern int sbtype;

View file

@ -11,7 +11,7 @@ typedef struct adlib_t
opl_t opl;
} adlib_t;
static void adlib_get_buffer(int16_t *buffer, int len, void *p)
static void adlib_get_buffer(int32_t *buffer, int len, void *p)
{
adlib_t *adlib = (adlib_t *)p;
int c;
@ -19,7 +19,7 @@ static void adlib_get_buffer(int16_t *buffer, int len, void *p)
opl2_update2(&adlib->opl);
for (c = 0; c < len * 2; c++)
buffer[c] += adlib->opl.buffer[c];
buffer[c] += (int32_t)adlib->opl.buffer[c];
adlib->opl.pos = 0;
}

View file

@ -651,7 +651,7 @@ void adgold_timer_poll(void *p)
}
}
static void adgold_get_buffer(int16_t *buffer, int len, void *p)
static void adgold_get_buffer(int32_t *buffer, int len, void *p)
{
adgold_t *adgold = (adgold_t *)p;
int16_t adgold_buffer[len*2];

View file

@ -84,7 +84,7 @@ void cms_update(cms_t *cms)
}
}
void cms_get_buffer(int16_t *buffer, int len, void *p)
void cms_get_buffer(int32_t *buffer, int len, void *p)
{
cms_t *cms = (cms_t *)p;

View file

@ -1047,7 +1047,7 @@ void gus_poll_wave(void *p)
pollgusirqs(gus);
}
static void gus_get_buffer(int16_t *buffer, int len, void *p)
static void gus_get_buffer(int32_t *buffer, int len, void *p)
{
gus_t *gus = (gus_t *)p;
int c;
@ -1056,7 +1056,7 @@ static void gus_get_buffer(int16_t *buffer, int len, void *p)
for (c = 0; c < len * 2; c++)
{
buffer[c] += gus->buffer[c & 1][c >> 1];
buffer[c] += (int32_t)gus->buffer[c & 1][c >> 1];
}
gus->pos = 0;

View file

@ -706,7 +706,7 @@ static void pas16_update(pas16_t *pas16)
}
}
void pas16_get_buffer(int16_t *buffer, int len, void *p)
void pas16_get_buffer(int32_t *buffer, int len, void *p)
{
pas16_t *pas16 = (pas16_t *)p;
int c;

View file

@ -126,7 +126,7 @@ static void ps1_audio_callback(void *p)
ps1->timer_count += ps1->timer_latch * TIMER_USEC;
}
static void ps1_audio_get_buffer(int16_t *buffer, int len, void *p)
static void ps1_audio_get_buffer(int32_t *buffer, int len, void *p)
{
ps1_audio_t *ps1 = (ps1_audio_t *)p;
int c;

View file

@ -167,7 +167,7 @@ static void pssj_callback(void *p)
pssj->timer_count += (int)(TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400));
}
static void pssj_get_buffer(int16_t *buffer, int len, void *p)
static void pssj_get_buffer(int32_t *buffer, int len, void *p)
{
pssj_t *pssj = (pssj_t *)p;
int c;

View file

@ -11,12 +11,12 @@
typedef struct sb_mixer_t
{
unsigned int master_l, master_r;
unsigned int voice_l, voice_r;
unsigned int fm_l, fm_r;
unsigned int cd_l, cd_r;
unsigned int bass_l, bass_r;
unsigned int treble_l, treble_r;
int master_l, master_r;
int voice_l, voice_r;
int fm_l, fm_r;
int cd_l, cd_r;
int bass_l, bass_r;
int treble_l, treble_r;
int filter;
int index;
@ -41,7 +41,7 @@ static int sb_att[]=
39036,46395,55140,65535
};
static void sb_get_buffer_opl2(int16_t *buffer, int len, void *p)
static void sb_get_buffer_opl2(int32_t *buffer, int len, void *p)
{
sb_t *sb = (sb_t *)p;
sb_mixer_t *mixer = &sb->mixer;
@ -52,7 +52,7 @@ static void sb_get_buffer_opl2(int16_t *buffer, int len, void *p)
sb_dsp_update(&sb->dsp);
for (c = 0; c < len * 2; c += 2)
{
int16_t out_l, out_r;
int32_t out_l, out_r;
out_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 16);
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16);
@ -92,7 +92,7 @@ static void sb_get_buffer_opl2(int16_t *buffer, int len, void *p)
sb->dsp.pos = 0;
}
static void sb_get_buffer_opl3(int16_t *buffer, int len, void *p)
static void sb_get_buffer_opl3(int32_t *buffer, int len, void *p)
{
sb_t *sb = (sb_t *)p;
sb_mixer_t *mixer = &sb->mixer;
@ -104,7 +104,7 @@ static void sb_get_buffer_opl3(int16_t *buffer, int len, void *p)
for (c = 0; c < len * 2; c += 2)
{
int c_emu8k = (((c/2) * 44100) / 48000)*2;
int16_t out_l, out_r;
int32_t out_l, out_r;
out_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 16);
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16);
@ -145,7 +145,7 @@ static void sb_get_buffer_opl3(int16_t *buffer, int len, void *p)
sb->emu8k.pos = 0;
}
static void sb_get_buffer_emu8k(int16_t *buffer, int len, void *p)
static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p)
{
sb_t *sb = (sb_t *)p;
sb_mixer_t *mixer = &sb->mixer;
@ -158,10 +158,10 @@ static void sb_get_buffer_emu8k(int16_t *buffer, int len, void *p)
for (c = 0; c < len * 2; c += 2)
{
int c_emu8k = (((c/2) * 44100) / 48000)*2;
int16_t out_l, out_r;
int32_t out_l, out_r;
out_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 16);
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16);
out_l = (((int32_t)sb->opl.buffer[c] * (int32_t)mixer->fm_l) >> 16);
out_r = (((int32_t)sb->opl.buffer[c + 1] * (int32_t)mixer->fm_r) >> 16);
out_l += ((sb->emu8k.buffer[c_emu8k] * mixer->fm_l) >> 16);
out_r += ((sb->emu8k.buffer[c_emu8k + 1] * mixer->fm_l) >> 16);

View file

@ -60,7 +60,7 @@ void sn76489_update(sn76489_t *sn76489)
}
}
void sn76489_get_buffer(int16_t *buffer, int len, void *p)
void sn76489_get_buffer(int32_t *buffer, int len, void *p)
{
sn76489_t *sn76489 = (sn76489_t *)p;

View file

@ -37,7 +37,7 @@ void speaker_update()
}
}
static void speaker_get_buffer(int16_t *buffer, int len, void *p)
static void speaker_get_buffer(int32_t *buffer, int len, void *p)
{
int c;

View file

@ -22,7 +22,7 @@ static void ssi2001_update(ssi2001_t *ssi2001)
ssi2001->pos = sound_pos_global;
}
static void ssi2001_get_buffer(int16_t *buffer, int len, void *p)
static void ssi2001_get_buffer(int32_t *buffer, int len, void *p)
{
ssi2001_t *ssi2001 = (ssi2001_t *)p;
int c;

View file

@ -57,7 +57,7 @@ void wss_write(uint16_t addr, uint8_t val, void *p)
ad1848_setirq(&wss->ad1848, wss_irq[(val >> 3) & 7]);
}
static void wss_get_buffer(int16_t *buffer, int len, void *p)
static void wss_get_buffer(int32_t *buffer, int len, void *p)
{
wss_t *wss = (wss_t *)p;

View file

@ -141,9 +141,10 @@ void inital()
#endif
}
void givealbuffer(int16_t *buf)
void givealbuffer(int32_t *buf)
{
#ifdef USE_OPENAL
int16_t buf16[BUFLEN*2];
int processed;
int state;
@ -172,14 +173,24 @@ void givealbuffer(int16_t *buf)
if (processed>=1)
{
int c;
ALuint buffer;
alSourceUnqueueBuffers(source[0], 1, &buffer);
// printf("U ");
check();
for (c=0;c<BUFLEN*2;c++)
{
if (buf[c] < -32768)
buf16[c] = -32768;
else if (buf[c] > 32767)
buf16[c] = 32767;
else
buf16[c] = buf[c];
}
// for (c=0;c<BUFLEN*2;c++) buf[c]^=0x8000;
alBufferData(buffer, AL_FORMAT_STEREO16, buf, BUFLEN*2*2, FREQ);
alBufferData(buffer, AL_FORMAT_STEREO16, buf16, BUFLEN*2*2, FREQ);
// printf("B ");
check();