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:
parent
9a5ac02902
commit
d2b6ea7fa3
15 changed files with 60 additions and 37 deletions
26
src/sound.c
26
src/sound.c
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue