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
|
static struct
|
||||||
{
|
{
|
||||||
void (*get_buffer)(int16_t *buffer, int len, void *p);
|
void (*get_buffer)(int32_t *buffer, int len, void *p);
|
||||||
void *priv;
|
void *priv;
|
||||||
} sound_handlers[8];
|
} 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()
|
void sound_init()
|
||||||
{
|
{
|
||||||
initalmain(0,NULL);
|
initalmain(0,NULL);
|
||||||
inital();
|
inital();
|
||||||
|
|
||||||
outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int16_t));
|
outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int32_t));
|
||||||
|
|
||||||
sound_cd_event = thread_create_event();
|
sound_cd_event = thread_create_event();
|
||||||
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
|
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].get_buffer = get_buffer;
|
||||||
sound_handlers[sound_handlers_num].priv = p;
|
sound_handlers[sound_handlers_num].priv = p;
|
||||||
|
|
@ -185,14 +185,26 @@ void sound_poll(void *priv)
|
||||||
if (sound_pos_global == SOUNDBUFLEN)
|
if (sound_pos_global == SOUNDBUFLEN)
|
||||||
{
|
{
|
||||||
int c;
|
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++)
|
for (c = 0; c < sound_handlers_num; c++)
|
||||||
sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv);
|
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);
|
if (soundon) givealbuffer(outbuffer);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "timer.h"
|
#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;
|
extern int sbtype;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ typedef struct adlib_t
|
||||||
opl_t opl;
|
opl_t opl;
|
||||||
} adlib_t;
|
} 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;
|
adlib_t *adlib = (adlib_t *)p;
|
||||||
int c;
|
int c;
|
||||||
|
|
@ -19,7 +19,7 @@ static void adlib_get_buffer(int16_t *buffer, int len, void *p)
|
||||||
opl2_update2(&adlib->opl);
|
opl2_update2(&adlib->opl);
|
||||||
|
|
||||||
for (c = 0; c < len * 2; c++)
|
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;
|
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;
|
adgold_t *adgold = (adgold_t *)p;
|
||||||
int16_t adgold_buffer[len*2];
|
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;
|
cms_t *cms = (cms_t *)p;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1047,7 +1047,7 @@ void gus_poll_wave(void *p)
|
||||||
pollgusirqs(gus);
|
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;
|
gus_t *gus = (gus_t *)p;
|
||||||
int c;
|
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++)
|
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;
|
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;
|
pas16_t *pas16 = (pas16_t *)p;
|
||||||
int c;
|
int c;
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ static void ps1_audio_callback(void *p)
|
||||||
ps1->timer_count += ps1->timer_latch * TIMER_USEC;
|
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;
|
ps1_audio_t *ps1 = (ps1_audio_t *)p;
|
||||||
int c;
|
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));
|
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;
|
pssj_t *pssj = (pssj_t *)p;
|
||||||
int c;
|
int c;
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@
|
||||||
|
|
||||||
typedef struct sb_mixer_t
|
typedef struct sb_mixer_t
|
||||||
{
|
{
|
||||||
unsigned int master_l, master_r;
|
int master_l, master_r;
|
||||||
unsigned int voice_l, voice_r;
|
int voice_l, voice_r;
|
||||||
unsigned int fm_l, fm_r;
|
int fm_l, fm_r;
|
||||||
unsigned int cd_l, cd_r;
|
int cd_l, cd_r;
|
||||||
unsigned int bass_l, bass_r;
|
int bass_l, bass_r;
|
||||||
unsigned int treble_l, treble_r;
|
int treble_l, treble_r;
|
||||||
int filter;
|
int filter;
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
|
|
@ -41,7 +41,7 @@ static int sb_att[]=
|
||||||
39036,46395,55140,65535
|
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_t *sb = (sb_t *)p;
|
||||||
sb_mixer_t *mixer = &sb->mixer;
|
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);
|
sb_dsp_update(&sb->dsp);
|
||||||
for (c = 0; c < len * 2; c += 2)
|
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_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 16);
|
||||||
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 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;
|
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_t *sb = (sb_t *)p;
|
||||||
sb_mixer_t *mixer = &sb->mixer;
|
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)
|
for (c = 0; c < len * 2; c += 2)
|
||||||
{
|
{
|
||||||
int c_emu8k = (((c/2) * 44100) / 48000)*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_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 16);
|
||||||
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 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;
|
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_t *sb = (sb_t *)p;
|
||||||
sb_mixer_t *mixer = &sb->mixer;
|
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)
|
for (c = 0; c < len * 2; c += 2)
|
||||||
{
|
{
|
||||||
int c_emu8k = (((c/2) * 44100) / 48000)*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_l = (((int32_t)sb->opl.buffer[c] * (int32_t)mixer->fm_l) >> 16);
|
||||||
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 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_l += ((sb->emu8k.buffer[c_emu8k] * mixer->fm_l) >> 16);
|
||||||
out_r += ((sb->emu8k.buffer[c_emu8k + 1] * 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;
|
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;
|
int c;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ static void ssi2001_update(ssi2001_t *ssi2001)
|
||||||
ssi2001->pos = sound_pos_global;
|
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;
|
ssi2001_t *ssi2001 = (ssi2001_t *)p;
|
||||||
int c;
|
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]);
|
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;
|
wss_t *wss = (wss_t *)p;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,9 +141,10 @@ void inital()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void givealbuffer(int16_t *buf)
|
void givealbuffer(int32_t *buf)
|
||||||
{
|
{
|
||||||
#ifdef USE_OPENAL
|
#ifdef USE_OPENAL
|
||||||
|
int16_t buf16[BUFLEN*2];
|
||||||
int processed;
|
int processed;
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
|
|
@ -172,14 +173,24 @@ void givealbuffer(int16_t *buf)
|
||||||
|
|
||||||
if (processed>=1)
|
if (processed>=1)
|
||||||
{
|
{
|
||||||
|
int c;
|
||||||
ALuint buffer;
|
ALuint buffer;
|
||||||
|
|
||||||
alSourceUnqueueBuffers(source[0], 1, &buffer);
|
alSourceUnqueueBuffers(source[0], 1, &buffer);
|
||||||
// printf("U ");
|
// printf("U ");
|
||||||
check();
|
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;
|
// 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 ");
|
// printf("B ");
|
||||||
check();
|
check();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue