From 3a57341837f9dfb9a91d6439c968398bf21529d0 Mon Sep 17 00:00:00 2001 From: TomW Date: Wed, 10 Feb 2016 20:49:28 +0000 Subject: [PATCH] Refactored sound code - slight speedup. --- src/device.c | 3 + src/keyboard_amstrad.c | 1 + src/keyboard_at.c | 1 + src/keyboard_olim24.c | 1 + src/keyboard_pcjr.c | 1 + src/keyboard_xt.c | 1 + src/pit.c | 6 +- src/sound.c | 47 ++++--- src/sound.h | 7 +- src/sound_ad1848.c | 113 +++++++++------- src/sound_ad1848.h | 16 ++- src/sound_adlib.c | 20 +-- src/sound_adlibgold.c | 56 ++++---- src/sound_cms.c | 94 +++++++------- src/sound_dbopl.cc | 11 +- src/sound_dbopl.h | 2 +- src/sound_emu8k.c | 289 +++++++++++++++++++++-------------------- src/sound_emu8k.h | 5 +- src/sound_gus.c | 31 +++-- src/sound_opl.c | 110 +++++++++------- src/sound_opl.h | 6 + src/sound_pas16.c | 52 ++++---- src/sound_pssj.c | 18 +-- src/sound_resid.cc | 4 +- src/sound_sb.c | 184 ++++++++++++++++++-------- src/sound_sb_dsp.c | 14 +- src/sound_sb_dsp.h | 5 + src/sound_sn76489.c | 73 ++++++----- src/sound_speaker.c | 29 +++-- src/sound_speaker.h | 2 + src/sound_ssi2001.c | 26 ++-- src/sound_wss.c | 38 +++--- src/timer.h | 5 + 33 files changed, 721 insertions(+), 550 deletions(-) diff --git a/src/device.c b/src/device.c index f71a9c4..6bd27a8 100644 --- a/src/device.c +++ b/src/device.c @@ -1,6 +1,7 @@ #include "ibm.h" #include "config.h" #include "device.h" +#include "sound.h" static void *device_priv[256]; static device_t *devices[256]; @@ -73,6 +74,8 @@ void device_speed_changed() } } } + + sound_speed_changed(); } void device_force_redraw() diff --git a/src/keyboard_amstrad.c b/src/keyboard_amstrad.c index 2bff91f..6d6f459 100644 --- a/src/keyboard_amstrad.c +++ b/src/keyboard_amstrad.c @@ -79,6 +79,7 @@ void keyboard_amstrad_write(uint16_t port, uint8_t val, void *priv) timer_process(); timer_update_outstanding(); + speaker_update(); speaker_gated = val & 1; speaker_enable = val & 2; if (speaker_enable) diff --git a/src/keyboard_at.c b/src/keyboard_at.c index bcf8468..9ded5e8 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -288,6 +288,7 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) timer_process(); timer_update_outstanding(); + speaker_update(); speaker_gated = val & 1; speaker_enable = val & 2; if (speaker_enable) diff --git a/src/keyboard_olim24.c b/src/keyboard_olim24.c index a728203..4986a65 100644 --- a/src/keyboard_olim24.c +++ b/src/keyboard_olim24.c @@ -147,6 +147,7 @@ void keyboard_olim24_write(uint16_t port, uint8_t val, void *priv) timer_process(); timer_update_outstanding(); + speaker_update(); speaker_gated = val & 1; speaker_enable = val & 2; if (speaker_enable) diff --git a/src/keyboard_pcjr.c b/src/keyboard_pcjr.c index b354ebe..adbf98f 100644 --- a/src/keyboard_pcjr.c +++ b/src/keyboard_pcjr.c @@ -128,6 +128,7 @@ void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv) timer_process(); timer_update_outstanding(); + speaker_update(); speaker_gated = val & 1; speaker_enable = val & 2; if (speaker_enable) diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index 8ff395f..3ddd82b 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -81,6 +81,7 @@ void keyboard_xt_write(uint16_t port, uint8_t val, void *priv) timer_process(); timer_update_outstanding(); + speaker_update(); speaker_gated = val & 1; speaker_enable = val & 2; if (speaker_enable) diff --git a/src/pit.c b/src/pit.c index 54ccd3d..051e2c9 100644 --- a/src/pit.c +++ b/src/pit.c @@ -572,7 +572,11 @@ void pit_refresh_timer_at(int new_out, int old_out) void pit_speaker_timer(int new_out, int old_out) { - int l = pit.l[2] ? pit.l[2] : 0x10000; + int l; + + speaker_update(); + + l = pit.l[2] ? pit.l[2] : 0x10000; if (l < 25) speakon = 0; else diff --git a/src/sound.c b/src/sound.c index 3759c6a..7f1d48f 100644 --- a/src/sound.c +++ b/src/sound.c @@ -78,14 +78,14 @@ void sound_card_init() static struct { - void (*poll)(void *p); void (*get_buffer)(int16_t *buffer, int len, void *p); void *priv; } sound_handlers[8]; static int sound_handlers_num; -static int sound_poll_time = 0, sound_get_buffer_time = 0; +static int sound_poll_time = 0, sound_get_buffer_time = 0, sound_poll_latch; +int sound_pos_global = 0; int soundon = 1; @@ -133,9 +133,8 @@ void sound_init() sound_cd_thread_h = thread_create(sound_cd_thread, NULL); } -void sound_add_handler(void (*poll)(void *p), void (*get_buffer)(int16_t *buffer, int len, void *p), void *p) +void sound_add_handler(void (*get_buffer)(int16_t *buffer, int len, void *p), void *p) { - sound_handlers[sound_handlers_num].poll = poll; sound_handlers[sound_handlers_num].get_buffer = get_buffer; sound_handlers[sound_handlers_num].priv = p; sound_handlers_num++; @@ -143,39 +142,37 @@ void sound_add_handler(void (*poll)(void *p), void (*get_buffer)(int16_t *buffer void sound_poll(void *priv) { - int c; + sound_poll_time += sound_poll_latch; + + sound_pos_global++; + if (sound_pos_global == SOUNDBUFLEN) + { + int c; - sound_poll_time += (int)((double)TIMER_USEC * (1000000.0 / 48000.0)); - - for (c = 0; c < sound_handlers_num; c++) - sound_handlers[c].poll(sound_handlers[c].priv); -} + memset(outbuffer, 0, SOUNDBUFLEN * 2 * sizeof(int16_t)); -FILE *soundf; - -void sound_get_buffer(void *priv) -{ - int c; - - sound_get_buffer_time += (TIMER_USEC * (1000000 / 10)); - - memset(outbuffer, 0, SOUNDBUFLEN * 2 * sizeof(int16_t)); - - for (c = 0; c < sound_handlers_num; c++) - sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv); + 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);*/ - if (soundon) givealbuffer(outbuffer); + if (soundon) givealbuffer(outbuffer); - thread_set_event(sound_cd_event); + thread_set_event(sound_cd_event); + + sound_pos_global = 0; + } +} + +void sound_speed_changed() +{ + sound_poll_latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0)); } void sound_reset() { timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL); - timer_add(sound_get_buffer, &sound_get_buffer_time, TIMER_ALWAYS_ENABLED, NULL); sound_handlers_num = 0; diff --git a/src/sound.h b/src/sound.h index fe7c31a..19fb588 100644 --- a/src/sound.h +++ b/src/sound.h @@ -1,4 +1,6 @@ -void sound_add_handler(void (*poll)(void *p), void (*get_buffer)(int16_t *buffer, int len, void *p), void *p); +#include "timer.h" + +void sound_add_handler(void (*get_buffer)(int16_t *buffer, int len, void *p), void *p); extern int sbtype; @@ -13,3 +15,6 @@ void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r); #define CD_FREQ 44100 #define CD_BUFLEN (CD_FREQ / 10) + +extern int sound_pos_global; +void sound_speed_changed(); diff --git a/src/sound_ad1848.c b/src/sound_ad1848.c index 499fd15..1addd43 100644 --- a/src/sound_ad1848.c +++ b/src/sound_ad1848.c @@ -3,6 +3,7 @@ AD1848 CODEC emulation (Windows Sound System compatible)*/ #include "ibm.h" +#include "sound.h" #include "sound_ad1848.h" static int ad1848_vols[64]; @@ -66,14 +67,14 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p) case 6: freq /= 512; break; case 7: freq /= 2560; break; } - ad1848->inc = (int)((freq * 65536) / 48000); + ad1848->freq = freq; + ad1848->timer_latch = (int)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq)); break; case 9: - if (!ad1848->enable) - ad1848->interp_count = 0; - ad1848->enable = ((val & 0x41) == 0x01); + if (!ad1848->enable) + ad1848->out_l = ad1848->out_r = 0; break; case 12: @@ -91,71 +92,84 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p) } } -void ad1848_poll(void *p, int16_t *l, int16_t *r) +void ad1848_speed_changed(ad1848_t *ad1848) +{ + ad1848->timer_latch = (int)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq)); +} + +void ad1848_update(ad1848_t *ad1848) +{ + for (; ad1848->pos < sound_pos_global; ad1848->pos++) + { + ad1848->buffer[ad1848->pos*2] = ad1848->out_l; + ad1848->buffer[ad1848->pos*2 + 1] = ad1848->out_r; + } +} + +static void ad1848_poll(void *p) { ad1848_t *ad1848 = (ad1848_t *)p; + + if (ad1848->timer_latch) + ad1848->timer_count += ad1848->timer_latch; + else + ad1848->timer_count = TIMER_USEC; -// opl3_poll(&ad1848->opl, &ad1848->opl_buffer[ad1848->pos * 2], &ad1848->opl_buffer[(ad1848->pos * 2) + 1]); + ad1848_update(ad1848); if (ad1848->enable) { int32_t temp; + switch (ad1848->regs[8] & 0x70) + { + case 0x00: /*Mono, 8-bit PCM*/ + ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; + break; + case 0x10: /*Stereo, 8-bit PCM*/ + ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; + ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; + break; + + case 0x40: /*Mono, 16-bit PCM*/ + temp = dma_channel_read(ad1848->dma); + ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp; + break; + case 0x50: /*Stereo, 16-bit PCM*/ + temp = dma_channel_read(ad1848->dma); + ad1848->out_l = (dma_channel_read(ad1848->dma) << 8) | temp; + temp = dma_channel_read(ad1848->dma); + ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp; + break; + } + if (ad1848->regs[6] & 0x80) - *l = 0; + ad1848->out_l = 0; else - *l = (ad1848->out_l * ad1848_vols[ad1848->regs[6] & 0x3f]) >> 16; + ad1848->out_l = (ad1848->out_l * ad1848_vols[ad1848->regs[6] & 0x3f]) >> 16; if (ad1848->regs[7] & 0x80) - *r = 0; + ad1848->out_r = 0; else - *r = (ad1848->out_r * ad1848_vols[ad1848->regs[7] & 0x3f]) >> 16; + ad1848->out_r = (ad1848->out_r * ad1848_vols[ad1848->regs[7] & 0x3f]) >> 16; - ad1848->interp_count += ad1848->inc; - if (ad1848->interp_count >= 0x10000) + if (ad1848->count < 0) { - ad1848->interp_count -= 0x10000; - - if (ad1848->count < 0) - { - ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8); - if (!(ad1848->status & 0x01)) - { - ad1848->status |= 0x01; - if (ad1848->regs[0xa] & 2) - picint(1 << ad1848->irq); - } - } - - switch (ad1848->regs[8] & 0x70) + ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8); + if (!(ad1848->status & 0x01)) { - case 0x00: /*Mono, 8-bit PCM*/ - ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; - break; - case 0x10: /*Stereo, 8-bit PCM*/ - ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; - ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; - break; - - case 0x40: /*Mono, 16-bit PCM*/ - temp = dma_channel_read(ad1848->dma); - ad1848->out_l = ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8); - break; - case 0x50: /*Stereo, 16-bit PCM*/ - temp = dma_channel_read(ad1848->dma); - ad1848->out_l = dma_channel_read(ad1848->dma) | (temp << 8); - temp = dma_channel_read(ad1848->dma); - ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8); - break; - } - - ad1848->count--; + ad1848->status |= 0x01; + if (ad1848->regs[0xa] & 2) + picint(1 << ad1848->irq); + } } + + ad1848->count--; // pclog("ad1848_poll : enable %X %X %X %X %X %X\n", ad1848->pcm_buffer[0][ad1848->pos], ad1848->pcm_buffer[1][ad1848->pos], ad1848->out_l[0], ad1848->out_r[0], ad1848->out_l[1], ad1848->out_r[1]); } else { - *l = *r = 0; + ad1848->out_l = ad1848->out_r = 0; // pclog("ad1848_poll : not enable\n"); } } @@ -184,7 +198,6 @@ void ad1848_init(ad1848_t *ad1848) ad1848->out_l = 0; ad1848->out_r = 0; - ad1848->interp_count = 0; for (c = 0; c < 64; c++) { @@ -201,4 +214,6 @@ void ad1848_init(ad1848_t *ad1848) ad1848_vols[c] = (int)(attenuation * 65536); // pclog("ad1848_vols %i = %f %i\n", c, attenuation, ad1848_vols[c]); } + + timer_add(ad1848_poll, &ad1848->timer_count, &ad1848->enable, ad1848); } diff --git a/src/sound_ad1848.h b/src/sound_ad1848.h index bbed948..546c0ca 100644 --- a/src/sound_ad1848.h +++ b/src/sound_ad1848.h @@ -1,3 +1,5 @@ +#include "timer.h" + typedef struct ad1848_t { int index; @@ -10,12 +12,17 @@ typedef struct ad1848_t int count; int16_t out_l, out_r; - - int interp_count, inc; - + int enable; int irq, dma; + + int freq; + + int timer_count, timer_latch; + + int16_t buffer[SOUNDBUFLEN * 2]; + int pos; } ad1848_t; void ad1848_setirq(ad1848_t *ad1848, int irq); @@ -24,4 +31,5 @@ void ad1848_setdma(ad1848_t *ad1848, int dma); uint8_t ad1848_read(uint16_t addr, void *p); void ad1848_write(uint16_t addr, uint8_t val, void *p); -void ad1848_poll(void *p, int16_t *l, int16_t *r); +void ad1848_update(ad1848_t *ad1848); +void ad1848_speed_changed(ad1848_t *ad1848); diff --git a/src/sound_adlib.c b/src/sound_adlib.c index eb52d73..db5d0fc 100644 --- a/src/sound_adlib.c +++ b/src/sound_adlib.c @@ -9,29 +9,19 @@ typedef struct adlib_t { opl_t opl; - int16_t buffer[SOUNDBUFLEN * 2]; - int pos; } adlib_t; -static void adlib_poll(void *p) -{ - adlib_t *adlib = (adlib_t *)p; - - if (adlib->pos >= SOUNDBUFLEN) return; - - opl2_poll(&adlib->opl, &adlib->buffer[adlib->pos * 2], &adlib->buffer[(adlib->pos * 2) + 1]); - adlib->pos++; -} - static void adlib_get_buffer(int16_t *buffer, int len, void *p) { adlib_t *adlib = (adlib_t *)p; int c; + opl2_update2(&adlib->opl); + for (c = 0; c < len * 2; c++) - buffer[c] += adlib->buffer[c]; + buffer[c] += adlib->opl.buffer[c]; - adlib->pos = 0; + adlib->opl.pos = 0; } void *adlib_init() @@ -42,7 +32,7 @@ void *adlib_init() pclog("adlib_init\n"); opl2_init(&adlib->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); - sound_add_handler(adlib_poll, adlib_get_buffer, adlib); + sound_add_handler(adlib_get_buffer, adlib); return adlib; } diff --git a/src/sound_adlibgold.c b/src/sound_adlibgold.c index 6db437a..43bb9ff 100644 --- a/src/sound_adlibgold.c +++ b/src/sound_adlibgold.c @@ -8,10 +8,9 @@ #include "io.h" #include "pic.h" #include "pit.h" +#include "sound.h" #include "timer.h" -void adgold_timer_poll(); - typedef struct adgold_t { int adgold_irq_status; @@ -53,6 +52,9 @@ typedef struct adgold_t int pos; } adgold_t; +void adgold_timer_poll(); +void adgold_update(adgold_t *adgold); + void adgold_update_irq_status(adgold_t *adgold) { uint8_t temp = 0xf; @@ -280,6 +282,7 @@ void adgold_write(uint16_t addr, uint8_t val, void *p) switch (adgold->adgold_mma_addr) { case 0x9: + adgold_update(adgold); switch (val & 0x18) { case 0x00: adgold->adgold_mma.voice_latch[1] = 12; break; /*44100 Hz*/ @@ -401,10 +404,30 @@ uint8_t adgold_read(uint16_t addr, void *p) return temp; } +void adgold_update(adgold_t *adgold) +{ + for (; adgold->pos < sound_pos_global; adgold->pos++) + { + adgold->mma_buffer[0][adgold->pos] = adgold->mma_buffer[1][adgold->pos] = 0; + + if (adgold->adgold_mma_regs[0][9] & 0x20) + adgold->mma_buffer[0][adgold->pos] += adgold->adgold_mma_out[0] / 2; + if (adgold->adgold_mma_regs[0][9] & 0x40) + adgold->mma_buffer[1][adgold->pos] += adgold->adgold_mma_out[0] / 2; + + if (adgold->adgold_mma_regs[1][9] & 0x20) + adgold->mma_buffer[0][adgold->pos] += adgold->adgold_mma_out[1] / 2; + if (adgold->adgold_mma_regs[1][9] & 0x40) + adgold->mma_buffer[1][adgold->pos] += adgold->adgold_mma_out[1] / 2; + } +} + void adgold_mma_poll(adgold_t *adgold, int channel) { int16_t dat; + adgold_update(adgold); + if (adgold->adgold_mma_fifo_start[channel] != adgold->adgold_mma_fifo_end[channel]) { switch (adgold->adgold_mma_regs[channel][0xc] & 0x60) @@ -514,41 +537,20 @@ void adgold_timer_poll(void *p) } } -void adgold_poll(void *p) -{ - adgold_t *adgold = (adgold_t *)p; - - if (adgold->pos >= SOUNDBUFLEN) - return; - - opl3_poll(&adgold->opl, &adgold->opl_buffer[adgold->pos * 2], &adgold->opl_buffer[(adgold->pos * 2) + 1]); - adgold->mma_buffer[0][adgold->pos] = adgold->mma_buffer[1][adgold->pos] = 0; - - if (adgold->adgold_mma_regs[0][9] & 0x20) - adgold->mma_buffer[0][adgold->pos] += adgold->adgold_mma_out[0] / 2; - if (adgold->adgold_mma_regs[0][9] & 0x40) - adgold->mma_buffer[1][adgold->pos] += adgold->adgold_mma_out[0] / 2; - - if (adgold->adgold_mma_regs[1][9] & 0x20) - adgold->mma_buffer[0][adgold->pos] += adgold->adgold_mma_out[1] / 2; - if (adgold->adgold_mma_regs[1][9] & 0x40) - adgold->mma_buffer[1][adgold->pos] += adgold->adgold_mma_out[1] / 2; - - adgold->pos++; -} - static void adgold_get_buffer(int16_t *buffer, int len, void *p) { adgold_t *adgold = (adgold_t *)p; int c; + opl3_update2(&adgold->opl); for (c = 0; c < len * 2; c++) { - buffer[c] += adgold->opl_buffer[c]; + buffer[c] += adgold->opl.buffer[c]; buffer[c] += adgold->mma_buffer[c & 1][c >> 1] / 2; } + adgold->opl.pos = 0; adgold->pos = 0; } @@ -576,7 +578,7 @@ void *adgold_init() timer_add(adgold_timer_poll, &adgold->adgold_mma_timer_count, TIMER_ALWAYS_ENABLED, adgold); - sound_add_handler(adgold_poll, adgold_get_buffer, adgold); + sound_add_handler(adgold_get_buffer, adgold); return adgold; } diff --git a/src/sound_cms.c b/src/sound_cms.c index 9479ef3..1d4d892 100644 --- a/src/sound_cms.c +++ b/src/sound_cms.c @@ -26,65 +26,62 @@ typedef struct cms_t int pos; } cms_t; -void cms_poll(void *p) +void cms_update(cms_t *cms) { - cms_t *cms = (cms_t *)p; - int c, d; - int16_t out_l = 0, out_r = 0; - - if (cms->pos >= SOUNDBUFLEN) - return; - - for (c = 0; c < 4; c++) + for (; cms->pos < sound_pos_global; cms->pos++) { - switch (cms->noisetype[c >> 1][c & 1]) + int c, d; + int16_t out_l = 0, out_r = 0; + + for (c = 0; c < 4; c++) { - case 0: cms->noisefreq[c >> 1][c & 1] = 31250; break; - case 1: cms->noisefreq[c >> 1][c & 1] = 15625; break; - case 2: cms->noisefreq[c >> 1][c & 1] = 7812; break; - case 3: cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3]; break; - } - } - for (c = 0; c < 2; c ++) - { - if (cms->regs[c][0x1C] & 1) - { - for (d = 0; d < 6; d++) + switch (cms->noisetype[c >> 1][c & 1]) { - if (cms->regs[c][0x14] & (1 << d)) + case 0: cms->noisefreq[c >> 1][c & 1] = 31250; break; + case 1: cms->noisefreq[c >> 1][c & 1] = 15625; break; + case 2: cms->noisefreq[c >> 1][c & 1] = 7812; break; + case 3: cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3]; break; + } + } + for (c = 0; c < 2; c ++) + { + if (cms->regs[c][0x1C] & 1) + { + for (d = 0; d < 6; d++) { - if (cms->stat[c][d]) out_l += (cms->vol[c][d][0] * 90); - if (cms->stat[c][d]) out_r += (cms->vol[c][d][1] * 90); - cms->count[c][d] += cms->freq[c][d]; - if (cms->count[c][d] >= 24000) + if (cms->regs[c][0x14] & (1 << d)) { - cms->count[c][d] -= 24000; - cms->stat[c][d] ^= 1; + if (cms->stat[c][d]) out_l += (cms->vol[c][d][0] * 90); + if (cms->stat[c][d]) out_r += (cms->vol[c][d][1] * 90); + cms->count[c][d] += cms->freq[c][d]; + if (cms->count[c][d] >= 24000) + { + cms->count[c][d] -= 24000; + cms->stat[c][d] ^= 1; + } + } + else if (cms->regs[c][0x15] & (1 << d)) + { + if (cms->noise[c][d / 3] & 1) out_l += (cms->vol[c][d][0] * 90); + if (cms->noise[c][d / 3] & 1) out_r += (cms->vol[c][d][0] * 90); } } - else if (cms->regs[c][0x15] & (1 << d)) + for (d = 0; d < 2; d++) { - if (cms->noise[c][d / 3] & 1) out_l += (cms->vol[c][d][0] * 90); - if (cms->noise[c][d / 3] & 1) out_r += (cms->vol[c][d][0] * 90); - } - } - for (d = 0; d < 2; d++) - { - cms->noisecount[c][d] += cms->noisefreq[c][d]; - while (cms->noisecount[c][d] >= 24000) - { - cms->noisecount[c][d] -= 24000; - cms->noise[c][d] <<= 1; - if (!(((cms->noise[c][d] & 0x4000) >> 8) ^ (cms->noise[c][d] & 0x40))) - cms->noise[c][d] |= 1; + cms->noisecount[c][d] += cms->noisefreq[c][d]; + while (cms->noisecount[c][d] >= 24000) + { + cms->noisecount[c][d] -= 24000; + cms->noise[c][d] <<= 1; + if (!(((cms->noise[c][d] & 0x4000) >> 8) ^ (cms->noise[c][d] & 0x40))) + cms->noise[c][d] |= 1; + } } } } + cms->buffer[(cms->pos << 1)] = out_l; + cms->buffer[(cms->pos << 1) + 1] = out_r; } - cms->buffer[(cms->pos << 1)] = out_l; - cms->buffer[(cms->pos << 1) + 1] = out_r; - - cms->pos++; } void cms_get_buffer(int16_t *buffer, int len, void *p) @@ -93,6 +90,8 @@ void cms_get_buffer(int16_t *buffer, int len, void *p) int c; + cms_update(cms); + for (c = 0; c < len * 2; c++) buffer[c] += cms->buffer[c]; @@ -111,6 +110,7 @@ void cms_write(uint16_t addr, uint8_t val, void *p) cms->addrs[chip] = val & 31; else { + cms_update(cms); cms->regs[chip][cms->addrs[chip] & 31] = val; switch (cms->addrs[chip] & 31) { @@ -159,7 +159,7 @@ void *cms_init() pclog("cms_init\n"); io_sethandler(0x0220, 0x0004, cms_read, NULL, NULL, cms_write, NULL, NULL, cms); - sound_add_handler(cms_poll, cms_get_buffer, cms); + sound_add_handler(cms_get_buffer, cms); return cms; } diff --git a/src/sound_dbopl.cc b/src/sound_dbopl.cc index ae12b15..9246b0e 100644 --- a/src/sound_dbopl.cc +++ b/src/sound_dbopl.cc @@ -126,19 +126,16 @@ void opl2_update(int nr, int16_t *buffer, int samples) opl[nr].chip.GenerateBlock2(samples, buffer_32); for (c = 0; c < samples; c++) - buffer[c] = (int16_t)buffer_32[c]; + buffer[c*2] = (int16_t)buffer_32[c]; } -void opl3_update(int nr, int16_t *bufferl, int16_t *bufferr, int samples) +void opl3_update(int nr, int16_t *buffer, int samples) { int c; Bit32s buffer_32[samples*2]; opl[nr].chip.GenerateBlock3(samples, buffer_32); - for (c = 0; c < samples; c++) - { - bufferl[c] = (int16_t)buffer_32[c*2]; - bufferr[c] = (int16_t)buffer_32[(c*2)+1]; - } + for (c = 0; c < samples*2; c++) + buffer[c] = (int16_t)buffer_32[c]; } diff --git a/src/sound_dbopl.h b/src/sound_dbopl.h index 74e80f7..0890552 100644 --- a/src/sound_dbopl.h +++ b/src/sound_dbopl.h @@ -6,7 +6,7 @@ extern "C" { uint8_t opl_read(int nr, uint16_t addr); void opl_timer_over(int nr, int timer); void opl2_update(int nr, int16_t *buffer, int samples); - void opl3_update(int nr, int16_t *bufferl, int16_t *bufferr, int samples); + void opl3_update(int nr, int16_t *buffer, int samples); #ifdef __cplusplus } #endif diff --git a/src/sound_emu8k.c b/src/sound_emu8k.c index e43acc6..2ef6795 100644 --- a/src/sound_emu8k.c +++ b/src/sound_emu8k.c @@ -258,6 +258,7 @@ void emu8k_outw(uint32_t addr, uint16_t val, void *p) { emu8k_t *emu8k = (emu8k_t *)p; + emu8k_update(emu8k); /* pclog("emu8k_outw : addr=%08X reg=%i voice=%i val=%04X\n", addr, emu8k->cur_reg, emu8k->cur_voice, val);*/ //emu8k_outw : addr=00000A22 reg=3 voice=21 val=0265 addr -= 0x220; @@ -501,160 +502,172 @@ void emu8k_outb(uint32_t addr, uint8_t val, void *p) emu8k_outw(addr, val, p); } -void emu8k_poll(void *p) +void emu8k_update(emu8k_t *emu8k) { - emu8k_t *emu8k = (emu8k_t *)p; - int c; - int32_t out_l = 0, out_r = 0; - - emu8k->timer_count += (int)(TIMER_USEC * (1000000.0 / 44100.0)); - - for (c = 0; c < 32; c++) + int new_pos = (sound_pos_global * 44100) / 48000; + if (emu8k->pos < new_pos) { - int32_t voice_l, voice_r; - int32_t dat; - int lfo1_vibrato, lfo2_vibrato; - int tremolo; + int32_t *buf; + int pos; + int c; + int32_t out_l = 0, out_r = 0; + + buf = &emu8k->buffer[emu8k->pos*2]; - tremolo = ((lfotable[(emu8k->voice[c].lfo1_count >> 8) & 4095] * emu8k->voice[c].lfo1_trem) * 4) >> 12; + for (pos = emu8k->pos; pos < new_pos; pos++) + emu8k->buffer[pos*2] = emu8k->buffer[pos*2 + 1] = 0; - if (freqtable[emu8k->voice[c].pitch] >> 32) - dat = EMU8K_READ(emu8k, emu8k->voice[c].addr >> 32); - else - dat = EMU8K_READ_INTERP(emu8k, emu8k->voice[c].addr >> 24); - - dat = (dat * emu8k->voice[c].attenuation) >> 16; - - dat = (dat * envtable[emu8k->voice[c].env_vol >> 9]) >> 16; - - if ((emu8k->voice[c].ccca >> 28) || (emu8k->voice[c].cutoff != 0xff)) + for (c = 0; c < 32; c++) { - int cutoff = emu8k->voice[c].cutoff + ((emu8k->voice[c].menv_vol * emu8k->voice[c].fe_height) >> 20); - if (cutoff < 0) - cutoff = 0; - if (cutoff > 255) - cutoff = 255; - - emu8k->voice[c].vhp = ((-emu8k->voice[c].vbp * emu8k->voice[c].q) >> 8) - emu8k->voice[c].vlp - dat; - emu8k->voice[c].vlp += (emu8k->voice[c].vbp * filt_w0[cutoff]) >> 8; - emu8k->voice[c].vbp += (emu8k->voice[c].vhp * filt_w0[cutoff]) >> 8; - if (emu8k->voice[c].vlp < -32767) - dat = -32767; - else if (emu8k->voice[c].vlp > 32767) - dat = 32767; - else - dat = (int16_t)emu8k->voice[c].vlp; - } + buf = &emu8k->buffer[emu8k->pos*2]; - voice_l = (dat * emu8k->voice[c].vol_l) >> 7; - voice_r = (dat * emu8k->voice[c].vol_r) >> 7; + for (pos = emu8k->pos; pos < new_pos; pos++) + { + int32_t voice_l, voice_r; + int32_t dat; + int lfo1_vibrato, lfo2_vibrato; + int tremolo; + + tremolo = ((lfotable[(emu8k->voice[c].lfo1_count >> 8) & 4095] * emu8k->voice[c].lfo1_trem) * 4) >> 12; + + if (freqtable[emu8k->voice[c].pitch] >> 32) + dat = EMU8K_READ(emu8k, emu8k->voice[c].addr >> 32); + else + dat = EMU8K_READ_INTERP(emu8k, emu8k->voice[c].addr >> 24); + + dat = (dat * emu8k->voice[c].attenuation) >> 16; + + dat = (dat * envtable[emu8k->voice[c].env_vol >> 9]) >> 16; - out_l += voice_l * 8192; - out_r += voice_r * 8192; + if ((emu8k->voice[c].ccca >> 28) || (emu8k->voice[c].cutoff != 0xff)) + { + int cutoff = emu8k->voice[c].cutoff + ((emu8k->voice[c].menv_vol * emu8k->voice[c].fe_height) >> 20); + if (cutoff < 0) + cutoff = 0; + if (cutoff > 255) + cutoff = 255; - switch (emu8k->voice[c].env_state) - { - case ENV_ATTACK: - emu8k->voice[c].env_vol += emu8k->voice[c].env_attack; - emu8k->voice[c].vtft |= 0xffff0000; - if (emu8k->voice[c].env_vol >= (1 << 21)) - { - emu8k->voice[c].env_vol = 1 << 21; - emu8k->voice[c].env_state = ENV_DECAY; - } - break; + emu8k->voice[c].vhp = ((-emu8k->voice[c].vbp * emu8k->voice[c].q) >> 8) - emu8k->voice[c].vlp - dat; + emu8k->voice[c].vlp += (emu8k->voice[c].vbp * filt_w0[cutoff]) >> 8; + emu8k->voice[c].vbp += (emu8k->voice[c].vhp * filt_w0[cutoff]) >> 8; + if (emu8k->voice[c].vlp < -32767) + dat = -32767; + else if (emu8k->voice[c].vlp > 32767) + dat = 32767; + else + dat = (int16_t)emu8k->voice[c].vlp; + } - case ENV_DECAY: - emu8k->voice[c].env_vol -= emu8k->voice[c].env_decay; - emu8k->voice[c].vtft = (emu8k->voice[c].vtft & ~0xffff0000) | ((emu8k->voice[c].env_sustain >> 5) << 16); - if (emu8k->voice[c].env_vol <= emu8k->voice[c].env_sustain) - { - emu8k->voice[c].env_vol = emu8k->voice[c].env_sustain; - emu8k->voice[c].env_state = ENV_SUSTAIN; - } - break; - - case ENV_RELEASE: - emu8k->voice[c].env_vol -= emu8k->voice[c].env_release; - emu8k->voice[c].vtft &= ~0xffff0000; - if (emu8k->voice[c].env_vol <= 0) - { - emu8k->voice[c].env_vol = 0; - emu8k->voice[c].env_state = ENV_STOPPED; - } - break; - } - - if (emu8k->voice[c].env_vol >= (1 << 21)) - emu8k->voice[c].cvcf &= ~0xffff0000; - else - emu8k->voice[c].cvcf = (emu8k->voice[c].cvcf & ~0xffff0000) | ((emu8k->voice[c].env_vol >> 5) << 16); - - switch (emu8k->voice[c].menv_state) - { - case ENV_ATTACK: - emu8k->voice[c].menv_vol += emu8k->voice[c].menv_attack; - if (emu8k->voice[c].menv_vol >= (1 << 21)) - { - emu8k->voice[c].menv_vol = 1 << 21; - emu8k->voice[c].menv_state = ENV_DECAY; - } - break; + voice_l = (dat * emu8k->voice[c].vol_l) >> 7; + voice_r = (dat * emu8k->voice[c].vol_r) >> 7; - case ENV_DECAY: - emu8k->voice[c].menv_vol -= emu8k->voice[c].menv_decay; - if (emu8k->voice[c].menv_vol <= emu8k->voice[c].menv_sustain) - { - emu8k->voice[c].menv_vol = emu8k->voice[c].menv_sustain; - emu8k->voice[c].menv_state = ENV_SUSTAIN; - } - break; + (*buf++) += voice_l * 8192; + (*buf++) += voice_r * 8192; - case ENV_RELEASE: - emu8k->voice[c].menv_vol -= emu8k->voice[c].menv_release; - if (emu8k->voice[c].menv_vol <= 0) - { - emu8k->voice[c].menv_vol = 0; - emu8k->voice[c].menv_state = ENV_STOPPED; - } - break; - } + switch (emu8k->voice[c].env_state) + { + case ENV_ATTACK: + emu8k->voice[c].env_vol += emu8k->voice[c].env_attack; + emu8k->voice[c].vtft |= 0xffff0000; + if (emu8k->voice[c].env_vol >= (1 << 21)) + { + emu8k->voice[c].env_vol = 1 << 21; + emu8k->voice[c].env_state = ENV_DECAY; + } + break; + + case ENV_DECAY: + emu8k->voice[c].env_vol -= emu8k->voice[c].env_decay; + emu8k->voice[c].vtft = (emu8k->voice[c].vtft & ~0xffff0000) | ((emu8k->voice[c].env_sustain >> 5) << 16); + if (emu8k->voice[c].env_vol <= emu8k->voice[c].env_sustain) + { + emu8k->voice[c].env_vol = emu8k->voice[c].env_sustain; + emu8k->voice[c].env_state = ENV_SUSTAIN; + } + break; - lfo1_vibrato = (lfotable[(emu8k->voice[c].lfo1_count >> 8) & 4095] * emu8k->voice[c].lfo1_fmmod) >> 9; - lfo2_vibrato = (lfotable[(emu8k->voice[c].lfo2_count >> 8) & 4095] * emu8k->voice[c].lfo2_fmmod) >> 9; + case ENV_RELEASE: + emu8k->voice[c].env_vol -= emu8k->voice[c].env_release; + emu8k->voice[c].vtft &= ~0xffff0000; + if (emu8k->voice[c].env_vol <= 0) + { + emu8k->voice[c].env_vol = 0; + emu8k->voice[c].env_state = ENV_STOPPED; + } + break; + } + + if (emu8k->voice[c].env_vol >= (1 << 21)) + emu8k->voice[c].cvcf &= ~0xffff0000; + else + emu8k->voice[c].cvcf = (emu8k->voice[c].cvcf & ~0xffff0000) | ((emu8k->voice[c].env_vol >> 5) << 16); + + switch (emu8k->voice[c].menv_state) + { + case ENV_ATTACK: + emu8k->voice[c].menv_vol += emu8k->voice[c].menv_attack; + if (emu8k->voice[c].menv_vol >= (1 << 21)) + { + emu8k->voice[c].menv_vol = 1 << 21; + emu8k->voice[c].menv_state = ENV_DECAY; + } + break; + + case ENV_DECAY: + emu8k->voice[c].menv_vol -= emu8k->voice[c].menv_decay; + if (emu8k->voice[c].menv_vol <= emu8k->voice[c].menv_sustain) + { + emu8k->voice[c].menv_vol = emu8k->voice[c].menv_sustain; + emu8k->voice[c].menv_state = ENV_SUSTAIN; + } + break; + + case ENV_RELEASE: + emu8k->voice[c].menv_vol -= emu8k->voice[c].menv_release; + if (emu8k->voice[c].menv_vol <= 0) + { + emu8k->voice[c].menv_vol = 0; + emu8k->voice[c].menv_state = ENV_STOPPED; + } + break; + } + + lfo1_vibrato = (lfotable[(emu8k->voice[c].lfo1_count >> 8) & 4095] * emu8k->voice[c].lfo1_fmmod) >> 9; + lfo2_vibrato = (lfotable[(emu8k->voice[c].lfo2_count >> 8) & 4095] * emu8k->voice[c].lfo2_fmmod) >> 9; - emu8k->voice[c].addr += freqtable[(emu8k->voice[c].pitch + lfo1_vibrato + lfo2_vibrato) & 0xffff]; - if (emu8k->voice[c].addr >= emu8k->voice[c].loop_end) - emu8k->voice[c].addr -= (emu8k->voice[c].loop_end - emu8k->voice[c].loop_start); + emu8k->voice[c].addr += freqtable[(emu8k->voice[c].pitch + lfo1_vibrato + lfo2_vibrato) & 0xffff]; + if (emu8k->voice[c].addr >= emu8k->voice[c].loop_end) + emu8k->voice[c].addr -= (emu8k->voice[c].loop_end - emu8k->voice[c].loop_start); - emu8k->voice[c].lfo1_count += (emu8k->voice[c].tremfrq & 0xff); - emu8k->voice[c].lfo2_count += (emu8k->voice[c].fm2frq2 & 0xff); - } - - out_l >>= 15; - out_r >>= 15; - - if (out_l < -32768) - emu8k->out_l = -32768; - else if (out_l > 32767) - emu8k->out_l = 32767; - else - emu8k->out_l = out_l; + emu8k->voice[c].lfo1_count += (emu8k->voice[c].tremfrq & 0xff); + emu8k->voice[c].lfo2_count += (emu8k->voice[c].fm2frq2 & 0xff); + } + } + + buf = &emu8k->buffer[emu8k->pos*2]; - if (out_r < -32768) - emu8k->out_r = -32768; - else if (out_r > 32767) - emu8k->out_r = 32767; - else - emu8k->out_r = out_r; + for (pos = emu8k->pos; pos < new_pos; pos++) + { + buf[0] >>= 15; + buf[1] >>= 15; - emu8k->wc++; -} + if (buf[0] < -32768) + buf[0] = -32768; + else if (buf[0] > 32767) + buf[0] = 32767; + + if (buf[1] < -32768) + buf[1] = -32768; + else if (buf[1] > 32767) + buf[1] = 32767; + + buf += 2; + } -void emu8k_poll_getsamp(emu8k_t *emu8k, int16_t *l, int16_t *r) -{ - *l = emu8k->out_l; - *r = emu8k->out_r; + emu8k->wc += (new_pos - emu8k->pos); + + emu8k->pos = new_pos; + } } void emu8k_init(emu8k_t *emu8k, int onboard_ram) @@ -689,8 +702,6 @@ void emu8k_init(emu8k_t *emu8k, int onboard_ram) io_sethandler(0x0a20, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); io_sethandler(0x0e20, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - timer_add(emu8k_poll, &emu8k->timer_count, TIMER_ALWAYS_ENABLED, emu8k); - /*Create frequency table*/ for (c = 0; c < 0x10000; c++) { diff --git a/src/sound_emu8k.h b/src/sound_emu8k.h index ed63eda..ac091de 100644 --- a/src/sound_emu8k.h +++ b/src/sound_emu8k.h @@ -79,9 +79,12 @@ typedef struct emu8k_t int timer_count; int16_t out_l, out_r; + + int pos; + int32_t buffer[SOUNDBUFLEN * 2]; } emu8k_t; void emu8k_init(emu8k_t *emu8k, int onboard_ram); void emu8k_close(emu8k_t *emu8k); -void emu8k_poll_getsamp(emu8k_t *dsp, int16_t *l, int16_t *r); +void emu8k_update(emu8k_t *emu8k); diff --git a/src/sound_gus.c b/src/sound_gus.c index 87e3837..c1a0be8 100644 --- a/src/sound_gus.c +++ b/src/sound_gus.c @@ -849,6 +849,15 @@ void gus_poll_timer_2(void *p) } } +static void gus_update(gus_t *gus) +{ + for (; gus->pos < sound_pos_global; gus->pos++) + { + gus->buffer[0][gus->pos] = gus->out_l; + gus->buffer[1][gus->pos] = gus->out_r; + } +} + void gus_poll_wave(void *p) { gus_t *gus = (gus_t *)p; @@ -857,7 +866,9 @@ void gus_poll_wave(void *p) int16_t v; int32_t vl; int update_irqs = 0; - + + gus_update(gus); + gus->samp_timer += gus->samp_latch; gus->out_l = gus->out_r = 0; @@ -1018,25 +1029,13 @@ void gus_poll_wave(void *p) pollgusirqs(gus); } -void gus_poll(void *p) -{ - gus_t *gus = (gus_t *)p; - - if (gus->pos >= SOUNDBUFLEN) - return; - - //pclog("gus_poll\n"); - gus->buffer[0][gus->pos] = gus->out_l; - gus->buffer[1][gus->pos] = gus->out_r; - - gus->pos++; -} - static void gus_get_buffer(int16_t *buffer, int len, void *p) { gus_t *gus = (gus_t *)p; int c; + gus_update(gus); + for (c = 0; c < len * 2; c++) { buffer[c] += gus->buffer[c & 1][c >> 1]; @@ -1085,7 +1084,7 @@ void *gus_init() timer_add(gus_poll_timer_1, &gus->timer_1, TIMER_ALWAYS_ENABLED, gus); timer_add(gus_poll_timer_2, &gus->timer_2, TIMER_ALWAYS_ENABLED, gus); - sound_add_handler(gus_poll, gus_get_buffer, gus); + sound_add_handler(gus_get_buffer, gus); return gus; } diff --git a/src/sound_opl.c b/src/sound_opl.c index 3892c01..0ec7643 100644 --- a/src/sound_opl.c +++ b/src/sound_opl.c @@ -2,6 +2,7 @@ #include #include "ibm.h" #include "io.h" +#include "sound.h" #include "sound_opl.h" #include "sound_dbopl.h" @@ -13,12 +14,14 @@ uint8_t opl2_read(uint16_t a, void *priv) opl_t *opl = (opl_t *)priv; cycles -= (int)(isa_timing * 8); + opl2_update2(opl); return opl_read(0, a); } void opl2_write(uint16_t a, uint8_t v, void *priv) { opl_t *opl = (opl_t *)priv; + opl2_update2(opl); opl_write(0, a, v); opl_write(1, a, v); } @@ -28,12 +31,14 @@ uint8_t opl2_l_read(uint16_t a, void *priv) opl_t *opl = (opl_t *)priv; cycles -= (int)(isa_timing * 8); + opl2_update2(opl); return opl_read(0, a); } void opl2_l_write(uint16_t a, uint8_t v, void *priv) { opl_t *opl = (opl_t *)priv; + opl2_update2(opl); opl_write(0, a, v); } @@ -42,12 +47,14 @@ uint8_t opl2_r_read(uint16_t a, void *priv) opl_t *opl = (opl_t *)priv; cycles -= (int)(isa_timing * 8); + opl2_update2(opl); return opl_read(1, a); } void opl2_r_write(uint16_t a, uint8_t v, void *priv) { opl_t *opl = (opl_t *)priv; + opl2_update2(opl); opl_write(1, a, v); } @@ -56,69 +63,41 @@ uint8_t opl3_read(uint16_t a, void *priv) opl_t *opl = (opl_t *)priv; cycles -= (int)(isa_timing * 8); + opl3_update2(opl); return opl_read(0, a); } void opl3_write(uint16_t a, uint8_t v, void *priv) { opl_t *opl = (opl_t *)priv; + opl3_update2(opl); opl_write(0, a, v); } -void opl2_poll(opl_t *opl, int16_t *bufl, int16_t *bufr) +void opl2_update2(opl_t *opl) { - opl2_update(0, bufl, 1); - opl2_update(1, bufr, 1); - - opl->filtbuf[0] = *bufl = ((*bufl) / 4) + ((opl->filtbuf[0] * 11) / 16); - opl->filtbuf[1] = *bufr = ((*bufr) / 4) + ((opl->filtbuf[1] * 11) / 16); - - if (opl->timers_enable[0][0]) + if (opl->pos < sound_pos_global) { - opl->timers[0][0]--; - if (opl->timers[0][0] < 0) opl_timer_over(0, 0); - } - if (opl->timers_enable[0][1]) - { - opl->timers[0][1]--; - if (opl->timers[0][1] < 0) opl_timer_over(0, 1); - } - if (opl->timers_enable[1][0]) - { - opl->timers[1][0]--; - if (opl->timers[1][0] < 0) opl_timer_over(1, 0); - } - if (opl->timers_enable[1][1]) - { - opl->timers[1][1]--; - if (opl->timers[1][1] < 0) opl_timer_over(1, 1); + opl2_update(0, &opl->buffer[opl->pos*2], sound_pos_global - opl->pos); + opl2_update(1, &opl->buffer[opl->pos*2 + 1], sound_pos_global - opl->pos); + for (; opl->pos < sound_pos_global; opl->pos++) + { + opl->filtbuf[0] = opl->buffer[opl->pos*2] = (opl->buffer[opl->pos*2] / 4) + ((opl->filtbuf[0] * 11) / 16); + opl->filtbuf[1] = opl->buffer[opl->pos*2+1] = (opl->buffer[opl->pos*2+1] / 4) + ((opl->filtbuf[1] * 11) / 16); + } } } -void opl3_poll(opl_t *opl, int16_t *bufl, int16_t *bufr) +void opl3_update2(opl_t *opl) { - opl3_update(0, bufl, bufr, 1); - - opl->filtbuf[0] = *bufl = ((*bufl) / 4) + ((opl->filtbuf[0] * 11) / 16); - opl->filtbuf[1] = *bufr = ((*bufr) / 4) + ((opl->filtbuf[1] * 11) / 16); - - if (opl->timers_enable[0][0]) + if (opl->pos < sound_pos_global) { - opl->timers[0][0]--; - if (opl->timers[0][0] < 0) + opl3_update(0, &opl->buffer[opl->pos*2], sound_pos_global - opl->pos); + for (; opl->pos < sound_pos_global; opl->pos++) { - opl->timers_enable[0][0] = 0; - opl_timer_over(0, 0); - } - } - if (opl->timers_enable[0][1]) - { - opl->timers[0][1]--; - if (opl->timers[0][1] < 0) - { - opl->timers_enable[0][1] = 0; - opl_timer_over(0, 1); + opl->filtbuf[0] = opl->buffer[opl->pos*2] = (opl->buffer[opl->pos*2] / 4) + ((opl->filtbuf[0] * 11) / 16); + opl->filtbuf[1] = opl->buffer[opl->pos*2+1] = (opl->buffer[opl->pos*2+1] / 4) + ((opl->filtbuf[1] * 11) / 16); } } } @@ -127,7 +106,7 @@ void ym3812_timer_set_0(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[0][timer] = period / 20833; + opl->timers[0][timer] = period * TIMER_USEC * 20; if (!opl->timers[0][timer]) opl->timers[0][timer] = 1; opl->timers_enable[0][timer] = period ? 1 : 0; } @@ -135,7 +114,7 @@ void ym3812_timer_set_1(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[1][timer] = period / 20833; + opl->timers[1][timer] = period * TIMER_USEC * 20; if (!opl->timers[1][timer]) opl->timers[1][timer] = 1; opl->timers_enable[1][timer] = period ? 1 : 0; } @@ -144,19 +123,54 @@ void ymf262_timer_set(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[0][timer] = period / 20833; + opl->timers[0][timer] = period * TIMER_USEC * 20; if (!opl->timers[0][timer]) opl->timers[0][timer] = 1; opl->timers_enable[0][timer] = period ? 1 : 0; } +static void opl_timer_callback00(void *p) +{ + opl_t *opl = (opl_t *)p; + + opl->timers_enable[0][0] = 0; + opl_timer_over(0, 0); +} +static void opl_timer_callback01(void *p) +{ + opl_t *opl = (opl_t *)p; + + opl->timers_enable[0][1] = 0; + opl_timer_over(0, 1); +} +static void opl_timer_callback10(void *p) +{ + opl_t *opl = (opl_t *)p; + + opl->timers_enable[1][0] = 0; + opl_timer_over(1, 0); +} +static void opl_timer_callback11(void *p) +{ + opl_t *opl = (opl_t *)p; + + opl->timers_enable[1][1] = 0; + opl_timer_over(1, 1); +} + void opl2_init(opl_t *opl) { opl_init(ym3812_timer_set_0, opl, 0, 0); opl_init(ym3812_timer_set_1, opl, 1, 0); + timer_add(opl_timer_callback00, &opl->timers[0][0], &opl->timers_enable[0][0], (void *)opl); + timer_add(opl_timer_callback01, &opl->timers[0][1], &opl->timers_enable[0][1], (void *)opl); + timer_add(opl_timer_callback10, &opl->timers[1][0], &opl->timers_enable[1][0], (void *)opl); + timer_add(opl_timer_callback11, &opl->timers[1][1], &opl->timers_enable[1][1], (void *)opl); } void opl3_init(opl_t *opl) { opl_init(ymf262_timer_set, opl, 0, 1); + timer_add(opl_timer_callback00, &opl->timers[0][0], &opl->timers_enable[0][0], (void *)opl); + timer_add(opl_timer_callback01, &opl->timers[0][1], &opl->timers_enable[0][1], (void *)opl); } diff --git a/src/sound_opl.h b/src/sound_opl.h index ae31aa3..047808e 100644 --- a/src/sound_opl.h +++ b/src/sound_opl.h @@ -6,6 +6,9 @@ typedef struct opl_t int timers_enable[2][2]; int16_t filtbuf[2]; + + int16_t buffer[SOUNDBUFLEN * 2]; + int pos; } opl_t; uint8_t opl2_read(uint16_t a, void *priv); @@ -22,3 +25,6 @@ void opl3_poll(opl_t *opl, int16_t *bufl, int16_t *bufr); void opl2_init(opl_t *opl); void opl3_init(opl_t *opl); + +void opl2_update2(opl_t *opl); +void opl3_update2(opl_t *opl); diff --git a/src/sound_pas16.c b/src/sound_pas16.c index 0f9e22b..83988f0 100644 --- a/src/sound_pas16.c +++ b/src/sound_pas16.c @@ -7,6 +7,7 @@ #include "io.h" #include "pic.h" #include "pit.h" +#include "sound.h" #include "sound_opl.h" #include "sound_pas16.h" #include "sound_sb_dsp.h" @@ -85,10 +86,6 @@ 3 = PAS16 */ -static uint8_t pas16_pit_in(uint16_t port, void *priv); -static void pas16_pit_out(uint16_t port, uint8_t val, void *priv); -//static void pas16_update_irqs(); - typedef struct pas16_t { uint16_t base; @@ -135,13 +132,15 @@ typedef struct pas16_t opl_t opl; sb_dsp_t dsp; - int16_t opl_buffer[SOUNDBUFLEN * 2]; int16_t pcm_buffer[2][SOUNDBUFLEN]; - int16_t dsp_buffer[SOUNDBUFLEN * 2]; int pos; } pas16_t; +static uint8_t pas16_pit_in(uint16_t port, void *priv); +static void pas16_pit_out(uint16_t port, uint8_t val, void *priv); +static void pas16_update(pas16_t *pas16); + static int pas16_dmas[8] = {4, 1, 2, 3, 0, 5, 6, 7}; static int pas16_irqs[16] = {0, 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, 15, 0, 0, 0, 0}; static int pas16_sb_irqs[8] = {0, 2, 3, 5, 7, 10, 11, 12}; @@ -294,6 +293,7 @@ static void pas16_out(uint16_t port, uint8_t val, void *p) break; case 0xb8a: + pas16_update(pas16); pas16->audiofilt = val; break; @@ -303,9 +303,11 @@ static void pas16_out(uint16_t port, uint8_t val, void *p) break; case 0xf88: + pas16_update(pas16); pas16->pcm_dat = (pas16->pcm_dat & 0xff00) | val; break; case 0xf89: + pas16_update(pas16); pas16->pcm_dat = (pas16->pcm_dat & 0x00ff) | (val << 8); break; case 0xf8a: @@ -548,6 +550,8 @@ static uint8_t pas16_readdma(pas16_t *pas16) static void pas16_pcm_poll(void *p) { pas16_t *pas16 = (pas16_t *)p; + + pas16_update(pas16); // if (pas16->pcm_ctrl & PAS16_PCM_ENA) // pclog("pas16_pcm_poll : poll %i %i ", pas16->pit.c[0], pas16->pit.l[0]); if (pas16->pit.m[0] & 2) @@ -682,27 +686,24 @@ static void pas16_out_base(uint16_t port, uint8_t val, void *p) } -void pas16_poll(void *p) +static void pas16_update(pas16_t *pas16) { - pas16_t *pas16 = (pas16_t *)p; - - if (pas16->pos >= SOUNDBUFLEN) - return; - - opl3_poll(&pas16->opl, &pas16->opl_buffer[pas16->pos * 2], &pas16->opl_buffer[(pas16->pos * 2) + 1]); - sb_dsp_poll(&pas16->dsp, &pas16->dsp_buffer[pas16->pos * 2], &pas16->dsp_buffer[(pas16->pos * 2) + 1]); - if (!(pas16->audiofilt & PAS16_FILT_MUTE)) { - pas16->pcm_buffer[0][pas16->pos] = 0; - pas16->pcm_buffer[1][pas16->pos] = 0; + for (; pas16->pos < sound_pos_global; pas16->pos++) + { + pas16->pcm_buffer[0][pas16->pos] = 0; + pas16->pcm_buffer[1][pas16->pos] = 0; + } } else { - pas16->pcm_buffer[0][pas16->pos] = (int16_t)pas16->pcm_dat_l; - pas16->pcm_buffer[1][pas16->pos] = (int16_t)pas16->pcm_dat_r; + for (; pas16->pos < sound_pos_global; pas16->pos++) + { + pas16->pcm_buffer[0][pas16->pos] = (int16_t)pas16->pcm_dat_l; + pas16->pcm_buffer[1][pas16->pos] = (int16_t)pas16->pcm_dat_r; + } } - pas16->pos++; } void pas16_get_buffer(int16_t *buffer, int len, void *p) @@ -710,14 +711,19 @@ void pas16_get_buffer(int16_t *buffer, int len, void *p) pas16_t *pas16 = (pas16_t *)p; int c; + opl3_update2(&pas16->opl); + sb_dsp_update(&pas16->dsp); + pas16_update(pas16); for (c = 0; c < len * 2; c++) { - buffer[c] += pas16->opl_buffer[c]; - buffer[c] += (int16_t)(sb_iir(c & 1, (float)pas16->dsp_buffer[c]) / 1.3) / 2; + buffer[c] += pas16->opl.buffer[c]; + buffer[c] += (int16_t)(sb_iir(c & 1, (float)pas16->dsp.buffer[c]) / 1.3) / 2; buffer[c] += (pas16->pcm_buffer[c & 1][c >> 1] / 2); } pas16->pos = 0; + pas16->opl.pos = 0; + pas16->dsp.pos = 0; } void *pas16_init() @@ -732,7 +738,7 @@ void *pas16_init() timer_add(pas16_pcm_poll, &pas16->pit.c[0], &pas16->pit.enable[0], pas16); - sound_add_handler(pas16_poll, pas16_get_buffer, pas16); + sound_add_handler(pas16_get_buffer, pas16); return pas16; } diff --git a/src/sound_pssj.c b/src/sound_pssj.c index 2e6064d..06702a9 100644 --- a/src/sound_pssj.c +++ b/src/sound_pssj.c @@ -102,11 +102,18 @@ static uint8_t pssj_read(uint16_t port, void *p) } } +static void pssj_update(pssj_t *pssj) +{ + for (; pssj->pos < sound_pos_global; pssj->pos++) + pssj->buffer[pssj->pos] = (((int8_t)(pssj->dac_val ^ 0x80) * 0x20) * pssj->amplitude) / 15; +} + static void pssj_callback(void *p) { pssj_t *pssj = (pssj_t *)p; int data; + pssj_update(pssj); if (pssj->ctrl & 2) { if ((pssj->ctrl & 3) == 3) @@ -160,18 +167,13 @@ 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_poll(void *p) -{ - pssj_t *pssj = (pssj_t *)p; - - pssj->buffer[pssj->pos++] = (((int8_t)(pssj->dac_val ^ 0x80) * 0x20) * pssj->amplitude) / 15; -} - static void pssj_get_buffer(int16_t *buffer, int len, void *p) { pssj_t *pssj = (pssj_t *)p; int c; + pssj_update(pssj); + for (c = 0; c < len * 2; c++) buffer[c] += pssj->buffer[c >> 1]; @@ -187,7 +189,7 @@ void *pssj_init() io_sethandler(0x00C4, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); timer_add(pssj_callback, &pssj->timer_count, &pssj->enable, pssj); - sound_add_handler(pssj_poll, pssj_get_buffer, pssj); + sound_add_handler(pssj_get_buffer, pssj); return pssj; } diff --git a/src/sound_resid.cc b/src/sound_resid.cc index c338e09..4a234b5 100644 --- a/src/sound_resid.cc +++ b/src/sound_resid.cc @@ -89,7 +89,7 @@ void sid_write(uint16_t addr, uint8_t val, void *p) psid->sid->write(addr & 0x1f,val); } -#define CLOCK_DELTA (int)((14318180.0 / 16.0) / 48000.0) +#define CLOCK_DELTA(n) (int)(((14318180.0 * n) / 16.0) / 48000.0) static void fillbuf2(int& count, int16_t *buf, int len) { @@ -102,7 +102,7 @@ static void fillbuf2(int& count, int16_t *buf, int len) void sid_fillbuf(int16_t *buf, int len, void *p) { // psid_t *psid = (psid_t *)p; - int x = CLOCK_DELTA; + int x = CLOCK_DELTA(len); fillbuf2(x, buf, len); } diff --git a/src/sound_sb.c b/src/sound_sb.c index 2a76ff1..3933a7e 100644 --- a/src/sound_sb.c +++ b/src/sound_sb.c @@ -31,10 +31,6 @@ typedef struct sb_t mpu401_uart_t mpu; emu8k_t emu8k; - int16_t opl_buffer[SOUNDBUFLEN * 2]; - int16_t dsp_buffer[SOUNDBUFLEN * 2]; - int16_t emu8k_buffer[SOUNDBUFLEN * 2]; - int pos; } sb_t; @@ -45,68 +41,31 @@ static int sb_att[]= 39036,46395,55140,65535 }; - - -static void sb_opl2_poll(void *p) -{ - sb_t *sb = (sb_t *)p; - - if (sb->pos >= SOUNDBUFLEN) return; - - opl2_poll(&sb->opl, &sb->opl_buffer[sb->pos * 2], &sb->opl_buffer[(sb->pos * 2) + 1]); - sb_dsp_poll(&sb->dsp, &sb->dsp_buffer[sb->pos * 2], &sb->dsp_buffer[(sb->pos * 2) + 1]); - sb->pos++; -} - -static void sb_opl3_poll(void *p) -{ - sb_t *sb = (sb_t *)p; - - if (sb->pos >= SOUNDBUFLEN) return; - - opl3_poll(&sb->opl, &sb->opl_buffer[sb->pos * 2], &sb->opl_buffer[(sb->pos * 2) + 1]); - sb_dsp_poll(&sb->dsp, &sb->dsp_buffer[sb->pos * 2], &sb->dsp_buffer[(sb->pos * 2) + 1]); - sb->pos++; -} - -static void sb_emu8k_poll(void *p) -{ - sb_t *sb = (sb_t *)p; - - if (sb->pos >= SOUNDBUFLEN) return; - - opl3_poll(&sb->opl, &sb->opl_buffer[sb->pos * 2], &sb->opl_buffer[(sb->pos * 2) + 1]); - sb_dsp_poll(&sb->dsp, &sb->dsp_buffer[sb->pos * 2], &sb->dsp_buffer[(sb->pos * 2) + 1]); - emu8k_poll_getsamp(&sb->emu8k, &sb->emu8k_buffer[sb->pos * 2], &sb->emu8k_buffer[(sb->pos * 2) + 1]); - sb->pos++; -} - -static void sb_get_buffer(int16_t *buffer, int len, void *p) +static void sb_get_buffer_opl2(int16_t *buffer, int len, void *p) { sb_t *sb = (sb_t *)p; sb_mixer_t *mixer = &sb->mixer; int c; + opl2_update2(&sb->opl); + sb_dsp_update(&sb->dsp); for (c = 0; c < len * 2; c += 2) { int16_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 += ((sb->emu8k_buffer[c] * mixer->fm_l) >> 16); - out_r += ((sb->emu8k_buffer[c + 1] * 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); if (sb->mixer.filter) { - out_l += (int)(((sb_iir(0, (float)sb->dsp_buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 16; - out_r += (int)(((sb_iir(1, (float)sb->dsp_buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 16; + out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 16; + out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 16; } else { - out_l += ((int32_t)(sb->dsp_buffer[c] * mixer->voice_l) / 3) >> 16; - out_r += ((int32_t)(sb->dsp_buffer[c + 1] * mixer->voice_r) / 3) >> 16; + out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 16; + out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 16; } out_l = (out_l * mixer->master_l) >> 16; @@ -129,8 +88,119 @@ static void sb_get_buffer(int16_t *buffer, int len, void *p) } sb->pos = 0; + sb->opl.pos = 0; + sb->dsp.pos = 0; } +static void sb_get_buffer_opl3(int16_t *buffer, int len, void *p) +{ + sb_t *sb = (sb_t *)p; + sb_mixer_t *mixer = &sb->mixer; + + int c; + + opl3_update2(&sb->opl); + sb_dsp_update(&sb->dsp); + for (c = 0; c < len * 2; c += 2) + { + int c_emu8k = (((c/2) * 44100) / 48000)*2; + int16_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); + + if (sb->mixer.filter) + { + out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 16; + out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 16; + } + else + { + out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 16; + out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 16; + } + + out_l = (out_l * mixer->master_l) >> 16; + out_r = (out_r * mixer->master_r) >> 16; + + if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8) + { + if (mixer->bass_l>8) out_l = (out_l + (((int16_t) low_iir(0, (float)out_l) * (mixer->bass_l - 8)) >> 1)) * ((15 - mixer->bass_l) + 16) >> 5; + if (mixer->bass_r>8) out_r = (out_r + (((int16_t) low_iir(1, (float)out_r) * (mixer->bass_r - 8)) >> 1)) * ((15 - mixer->bass_r) + 16) >> 5; + if (mixer->treble_l>8) out_l = (out_l + (((int16_t) high_iir(0, (float)out_l) * (mixer->treble_l - 8)) >> 1)) * ((15 - mixer->treble_l) + 16) >> 5; + if (mixer->treble_r>8) out_r = (out_r + (((int16_t) high_iir(1, (float)out_r) * (mixer->treble_r - 8)) >> 1)) * ((15 - mixer->treble_r) + 16) >> 5; + if (mixer->bass_l<8) out_l = (out_l + (((int16_t) low_cut_iir(0, (float)out_l) * (8 - mixer->bass_l)) >> 1)) * (mixer->bass_l + 16) >> 5; + if (mixer->bass_r<8) out_r = (out_r + (((int16_t) low_cut_iir(1, (float)out_r) * (8 - mixer->bass_r)) >> 1)) * (mixer->bass_r + 16) >> 5; + if (mixer->treble_l<8) out_l = (out_l + (((int16_t)high_cut_iir(0, (float)out_l) * (8 - mixer->treble_l)) >> 1)) * (mixer->treble_l + 16) >> 5; + if (mixer->treble_r<8) out_r = (out_r + (((int16_t)high_cut_iir(1, (float)out_r) * (8 - mixer->treble_r)) >> 1)) * (mixer->treble_r + 16) >> 5; + } + + buffer[c] += out_l; + buffer[c + 1] += out_r; + } + + sb->pos = 0; + sb->opl.pos = 0; + sb->dsp.pos = 0; + sb->emu8k.pos = 0; +} + +static void sb_get_buffer_emu8k(int16_t *buffer, int len, void *p) +{ + sb_t *sb = (sb_t *)p; + sb_mixer_t *mixer = &sb->mixer; + + int c; + + opl3_update2(&sb->opl); + sb_dsp_update(&sb->dsp); + emu8k_update(&sb->emu8k); + for (c = 0; c < len * 2; c += 2) + { + int c_emu8k = (((c/2) * 44100) / 48000)*2; + int16_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 += ((sb->emu8k.buffer[c_emu8k] * mixer->fm_l) >> 16); + out_r += ((sb->emu8k.buffer[c_emu8k + 1] * mixer->fm_l) >> 16); + + if (sb->mixer.filter) + { + out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 16; + out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 16; + } + else + { + out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 16; + out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 16; + } + + out_l = (out_l * mixer->master_l) >> 16; + out_r = (out_r * mixer->master_r) >> 16; + + if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8) + { + if (mixer->bass_l>8) out_l = (out_l + (((int16_t) low_iir(0, (float)out_l) * (mixer->bass_l - 8)) >> 1)) * ((15 - mixer->bass_l) + 16) >> 5; + if (mixer->bass_r>8) out_r = (out_r + (((int16_t) low_iir(1, (float)out_r) * (mixer->bass_r - 8)) >> 1)) * ((15 - mixer->bass_r) + 16) >> 5; + if (mixer->treble_l>8) out_l = (out_l + (((int16_t) high_iir(0, (float)out_l) * (mixer->treble_l - 8)) >> 1)) * ((15 - mixer->treble_l) + 16) >> 5; + if (mixer->treble_r>8) out_r = (out_r + (((int16_t) high_iir(1, (float)out_r) * (mixer->treble_r - 8)) >> 1)) * ((15 - mixer->treble_r) + 16) >> 5; + if (mixer->bass_l<8) out_l = (out_l + (((int16_t) low_cut_iir(0, (float)out_l) * (8 - mixer->bass_l)) >> 1)) * (mixer->bass_l + 16) >> 5; + if (mixer->bass_r<8) out_r = (out_r + (((int16_t) low_cut_iir(1, (float)out_r) * (8 - mixer->bass_r)) >> 1)) * (mixer->bass_r + 16) >> 5; + if (mixer->treble_l<8) out_l = (out_l + (((int16_t)high_cut_iir(0, (float)out_l) * (8 - mixer->treble_l)) >> 1)) * (mixer->treble_l + 16) >> 5; + if (mixer->treble_r<8) out_r = (out_r + (((int16_t)high_cut_iir(1, (float)out_r) * (8 - mixer->treble_r)) >> 1)) * (mixer->treble_r + 16) >> 5; + } + + buffer[c] += out_l; + buffer[c + 1] += out_r; + } + + sb->pos = 0; + sb->opl.pos = 0; + sb->dsp.pos = 0; + sb->emu8k.pos = 0; +} void sb_pro_mixer_write(uint16_t addr, uint8_t val, void *p) { @@ -280,7 +350,7 @@ void *sb_1_init() sb_mixer_init(&sb->mixer); io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - sound_add_handler(sb_opl2_poll, sb_get_buffer, sb); + sound_add_handler(sb_get_buffer_opl2, sb); return sb; } void *sb_15_init() @@ -297,7 +367,7 @@ void *sb_15_init() sb_mixer_init(&sb->mixer); io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - sound_add_handler(sb_opl2_poll, sb_get_buffer, sb); + sound_add_handler(sb_get_buffer_opl2, sb); return sb; } void *sb_2_init() @@ -314,7 +384,7 @@ void *sb_2_init() sb_mixer_init(&sb->mixer); io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - sound_add_handler(sb_opl2_poll, sb_get_buffer, sb); + sound_add_handler(sb_get_buffer_opl2, sb); return sb; } @@ -335,7 +405,7 @@ void *sb_pro_v1_init() io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_opl2_poll, sb_get_buffer, sb); + sound_add_handler(sb_get_buffer_opl2, sb); sb->mixer.regs[0x22] = 0xff; sb->mixer.regs[0x04] = 0xff; @@ -361,7 +431,7 @@ void *sb_pro_v2_init() io_sethandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_opl3_poll, sb_get_buffer, sb); + sound_add_handler(sb_get_buffer_opl3, sb); sb->mixer.regs[0x22] = 0xff; sb->mixer.regs[0x04] = 0xff; @@ -384,7 +454,7 @@ void *sb_16_init() io_sethandler(0x0228, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(0x0224, 0x0002, sb_16_mixer_read, NULL, NULL, sb_16_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_opl3_poll, sb_get_buffer, sb); + sound_add_handler(sb_get_buffer_opl3, sb); mpu401_uart_init(&sb->mpu, 0x330); sb->mixer.regs[0x30] = 31 << 3; @@ -423,7 +493,7 @@ void *sb_awe32_init() io_sethandler(0x0228, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(0x0224, 0x0002, sb_16_mixer_read, NULL, NULL, sb_16_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_emu8k_poll, sb_get_buffer, sb); + sound_add_handler(sb_get_buffer_emu8k, sb); mpu401_uart_init(&sb->mpu, 0x330); emu8k_init(&sb->emu8k, onboard_ram); diff --git a/src/sound_sb_dsp.c b/src/sound_sb_dsp.c index f3dbd36..d5bb023 100644 --- a/src/sound_sb_dsp.c +++ b/src/sound_sb_dsp.c @@ -283,6 +283,7 @@ void sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, 0); break; case 0x10: /*8-bit direct mode*/ + sb_dsp_update(dsp); dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8; break; case 0x14: /*8-bit single cycle DMA output*/ @@ -631,6 +632,8 @@ void pollsb(void *p) if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output) { int data[2]; + + sb_dsp_update(dsp); // pclog("Dopoll %i %02X %i\n", sb_8_length, sb_8_format, sblatcho); switch (dsp->sb_8_format) { @@ -795,6 +798,8 @@ void pollsb(void *p) } if (dsp->sb_16_enable && !dsp->sb_16_pause && dsp->sb_pausetime < 0 && dsp->sb_16_output) { + sb_dsp_update(dsp); + switch (dsp->sb_16_format) { case 0x00: /*Mono unsigned*/ @@ -918,10 +923,13 @@ void sb_poll_i(void *p) } } -void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r) +void sb_dsp_update(sb_dsp_t *dsp) { - *l = dsp->sbdatl; - *r = dsp->sbdatr; + for (; dsp->pos < sound_pos_global; dsp->pos++) + { + dsp->buffer[dsp->pos*2] = dsp->sbdatl; + dsp->buffer[dsp->pos*2 + 1] = dsp->sbdatr; + } } void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp) diff --git a/src/sound_sb_dsp.h b/src/sound_sb_dsp.h index f168886..5a2c08f 100644 --- a/src/sound_sb_dsp.h +++ b/src/sound_sb_dsp.h @@ -56,6 +56,9 @@ typedef struct sb_dsp_t int stereo; int asp_data_len; + + int16_t buffer[SOUNDBUFLEN * 2]; + int pos; } sb_dsp_t; void sb_dsp_init(sb_dsp_t *dsp, int type); @@ -71,3 +74,5 @@ void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r); void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo); void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp); + +void sb_dsp_update(sb_dsp_t *dsp); diff --git a/src/sound_sn76489.c b/src/sound_sn76489.c index c854667..1f4d559 100644 --- a/src/sound_sn76489.c +++ b/src/sound_sn76489.c @@ -17,48 +17,47 @@ static float volslog[16]= #define PSGCONST ((3579545.0 / 64.0) / 48000.0) -void sn76489_poll(void *p) +void sn76489_update(sn76489_t *sn76489) { - sn76489_t *sn76489 = (sn76489_t *)p; - int c; - int16_t result = 0; - - if (sn76489->pos >= SOUNDBUFLEN) - return; - - for (c = 1; c < 4; c++) + for (; sn76489->pos < sound_pos_global; sn76489->pos++) { - if (sn76489->latch[c] > 256) result += (int16_t) (volslog[sn76489->vol[c]] * sn76489->stat[c]); - else result += (int16_t) (volslog[sn76489->vol[c]] * 127); + int c; + int16_t result = 0; + + for (c = 1; c < 4; c++) + { + if (sn76489->latch[c] > 256) result += (int16_t) (volslog[sn76489->vol[c]] * sn76489->stat[c]); + else result += (int16_t) (volslog[sn76489->vol[c]] * 127); - sn76489->count[c] -= (256 * PSGCONST); - while ((int)sn76489->count[c] < 0) - { - sn76489->count[c] += sn76489->latch[c]; - sn76489->stat[c] = -sn76489->stat[c]; + sn76489->count[c] -= (256 * PSGCONST); + while ((int)sn76489->count[c] < 0) + { + sn76489->count[c] += sn76489->latch[c]; + sn76489->stat[c] = -sn76489->stat[c]; + } } - } - result += (((sn76489->shift & 1) ^ 1) * 127 * volslog[sn76489->vol[0]] * 2); + result += (((sn76489->shift & 1) ^ 1) * 127 * volslog[sn76489->vol[0]] * 2); - sn76489->count[0] -= (512 * PSGCONST); - while ((int)sn76489->count[0] < 0 && sn76489->latch[0]) - { - sn76489->count[0] += (sn76489->latch[0] * 4); - if (!(sn76489->noise & 4)) + sn76489->count[0] -= (512 * PSGCONST); + while ((int)sn76489->count[0] < 0 && sn76489->latch[0]) { - if (sn76489->shift & 1) - sn76489->shift |= 0x8000; - sn76489->shift >>= 1; + sn76489->count[0] += (sn76489->latch[0] * 4); + if (!(sn76489->noise & 4)) + { + if (sn76489->shift & 1) + sn76489->shift |= 0x8000; + sn76489->shift >>= 1; + } + else + { + if ((sn76489->shift & 1) ^ ((sn76489->shift >> 1) & 1)) + sn76489->shift |= 0x8000; + sn76489->shift >>= 1; + } } - else - { - if ((sn76489->shift & 1) ^ ((sn76489->shift >> 1) & 1)) - sn76489->shift |= 0x8000; - sn76489->shift >>= 1; - } - } - sn76489->buffer[sn76489->pos++] = result; + sn76489->buffer[sn76489->pos] = result; + } } void sn76489_get_buffer(int16_t *buffer, int len, void *p) @@ -67,6 +66,8 @@ void sn76489_get_buffer(int16_t *buffer, int len, void *p) int c; + sn76489_update(sn76489); + if (!sn76489_mute) { for (c = 0; c < len * 2; c++) @@ -81,6 +82,8 @@ void sn76489_write(uint16_t addr, uint8_t data, void *p) sn76489_t *sn76489 = (sn76489_t *)p; int freq; + sn76489_update(sn76489); + if (data & 0x80) { sn76489->firstdat = data; @@ -176,7 +179,7 @@ void sn74689_set_extra_divide(sn76489_t *sn76489, int enable) void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type) { - sound_add_handler(sn76489_poll, sn76489_get_buffer, sn76489); + sound_add_handler(sn76489_get_buffer, sn76489); sn76489->latch[0] = sn76489->latch[1] = sn76489->latch[2] = sn76489->latch[3] = 0x3FF << 6; sn76489->vol[0] = 0; diff --git a/src/sound_speaker.c b/src/sound_speaker.c index eac0a2a..cb19821 100644 --- a/src/sound_speaker.c +++ b/src/sound_speaker.c @@ -11,31 +11,42 @@ static int speaker_pos = 0; int speaker_gated = 0; int speaker_enable = 0, was_speaker_enable = 0; -static void speaker_poll(void *p) +void speaker_update() { - if (speaker_pos >= SOUNDBUFLEN) return; - + int16_t val; + // printf("SPeaker - %i %i %i %02X\n",speakval,gated,speakon,pit.m[2]); if (speaker_gated && was_speaker_enable) { if (!pit.m[2] || pit.m[2]==4) - speaker_buffer[speaker_pos] = speakval; + val = speakval; else if (pit.l[2] < 0x40) - speaker_buffer[speaker_pos] = 0xa00; + val = 0xa00; else - speaker_buffer[speaker_pos] = speakon ? 0x1400 : 0; + val = speakon ? 0x1400 : 0; } else - speaker_buffer[speaker_pos] = was_speaker_enable ? 0x1400 : 0; - speaker_pos++; + val = was_speaker_enable ? 0x1400 : 0; + if (!speaker_enable) was_speaker_enable = 0; + + if (speaker_pos != sound_pos_global) + speaker_buffer[speaker_pos] = val; + + if (!speaker_gated) + val = 0; + + for (; speaker_pos < sound_pos_global; speaker_pos++) + speaker_buffer[speaker_pos] = val; } static void speaker_get_buffer(int16_t *buffer, int len, void *p) { int c; + speaker_update(); + if (!speaker_mute) { for (c = 0; c < len * 2; c++) @@ -47,6 +58,6 @@ static void speaker_get_buffer(int16_t *buffer, int len, void *p) void speaker_init() { - sound_add_handler(speaker_poll, speaker_get_buffer, NULL); + sound_add_handler(speaker_get_buffer, NULL); speaker_mute = 0; } diff --git a/src/sound_speaker.h b/src/sound_speaker.h index 15f9a01..01c9dfa 100644 --- a/src/sound_speaker.h +++ b/src/sound_speaker.h @@ -4,3 +4,5 @@ extern int speaker_mute; extern int speaker_gated; extern int speaker_enable, was_speaker_enable; + +void speaker_update(); diff --git a/src/sound_ssi2001.c b/src/sound_ssi2001.c index dd7139c..55208d5 100644 --- a/src/sound_ssi2001.c +++ b/src/sound_ssi2001.c @@ -13,14 +13,13 @@ typedef struct ssi2001_t int pos; } ssi2001_t; -static void ssi2001_poll(void *p) +static void ssi2001_update(ssi2001_t *ssi2001) { - ssi2001_t *ssi2001 = (ssi2001_t *)p; + if (ssi2001->pos >= sound_pos_global) + return; - if (ssi2001->pos >= SOUNDBUFLEN) return; - - sid_fillbuf(&ssi2001->buffer[ssi2001->pos], 1, ssi2001->psid); - ssi2001->pos++; + sid_fillbuf(&ssi2001->buffer[ssi2001->pos], sound_pos_global - ssi2001->pos, ssi2001->psid); + ssi2001->pos = sound_pos_global; } static void ssi2001_get_buffer(int16_t *buffer, int len, void *p) @@ -28,6 +27,8 @@ static void ssi2001_get_buffer(int16_t *buffer, int len, void *p) ssi2001_t *ssi2001 = (ssi2001_t *)p; int c; + ssi2001_update(ssi2001); + for (c = 0; c < len * 2; c++) buffer[c] += ssi2001->buffer[c >> 1] / 2; @@ -36,12 +37,19 @@ static void ssi2001_get_buffer(int16_t *buffer, int len, void *p) static uint8_t ssi2001_read(uint16_t addr, void *p) { + ssi2001_t *ssi2001 = (ssi2001_t *)p; + + ssi2001_update(ssi2001); + return sid_read(addr, p); } static void ssi2001_write(uint16_t addr, uint8_t val, void *p) { - return sid_write(addr, val, p); + ssi2001_t *ssi2001 = (ssi2001_t *)p; + + ssi2001_update(ssi2001); + sid_write(addr, val, p); } void *ssi2001_init() @@ -52,8 +60,8 @@ void *ssi2001_init() pclog("ssi2001_init\n"); ssi2001->psid = sid_init(); sid_reset(ssi2001->psid); - io_sethandler(0x0280, 0x0020, ssi2001_read, NULL, NULL, ssi2001_write, NULL, NULL, &ssi2001); - sound_add_handler(ssi2001_poll, ssi2001_get_buffer, ssi2001); + io_sethandler(0x0280, 0x0020, ssi2001_read, NULL, NULL, ssi2001_write, NULL, NULL, ssi2001); + sound_add_handler(ssi2001_get_buffer, ssi2001); return ssi2001; } diff --git a/src/sound_wss.c b/src/sound_wss.c index 5253cb5..b4fb8a2 100644 --- a/src/sound_wss.c +++ b/src/sound_wss.c @@ -35,11 +35,6 @@ typedef struct wss_t ad1848_t ad1848; opl_t opl; - - int16_t opl_buffer[SOUNDBUFLEN * 2]; - int16_t pcm_buffer[2][SOUNDBUFLEN]; - - int pos; } wss_t; uint8_t wss_read(uint16_t addr, void *p) @@ -62,32 +57,22 @@ void wss_write(uint16_t addr, uint8_t val, void *p) ad1848_setirq(&wss->ad1848, wss_irq[(val >> 3) & 7]); } -static void wss_poll(void *p) -{ - wss_t *wss = (wss_t *)p; - - if (wss->pos >= SOUNDBUFLEN) - return; - - opl3_poll(&wss->opl, &wss->opl_buffer[wss->pos * 2], &wss->opl_buffer[(wss->pos * 2) + 1]); - ad1848_poll(&wss->ad1848, &wss->pcm_buffer[0][wss->pos], &wss->pcm_buffer[1][wss->pos]); - - wss->pos++; -} - static void wss_get_buffer(int16_t *buffer, int len, void *p) { wss_t *wss = (wss_t *)p; int c; + opl3_update2(&wss->opl); + ad1848_update(&wss->ad1848); for (c = 0; c < len * 2; c++) { - buffer[c] += wss->opl_buffer[c]; - buffer[c] += (wss->pcm_buffer[c & 1][c >> 1] / 2); + buffer[c] += wss->opl.buffer[c]; + buffer[c] += (wss->ad1848.buffer[c] / 2); } - wss->pos = 0; + wss->opl.pos = 0; + wss->ad1848.pos = 0; } void *wss_init() @@ -108,7 +93,7 @@ void *wss_init() io_sethandler(0x0530, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss); io_sethandler(0x0534, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848); - sound_add_handler(wss_poll, wss_get_buffer, wss); + sound_add_handler(wss_get_buffer, wss); return wss; } @@ -120,6 +105,13 @@ void wss_close(void *p) free(wss); } +void wss_speed_changed(void *p) +{ + wss_t *wss = (wss_t *)p; + + ad1848_speed_changed(&wss->ad1848); +} + device_t wss_device = { "Windows Sound System", @@ -127,7 +119,7 @@ device_t wss_device = wss_init, wss_close, NULL, - NULL, + wss_speed_changed, NULL, NULL }; diff --git a/src/timer.h b/src/timer.h index 7c8d4f5..b695969 100644 --- a/src/timer.h +++ b/src/timer.h @@ -1,3 +1,6 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ + extern int timer_start; #define timer_start_period(cycles) \ @@ -49,3 +52,5 @@ extern int timer_one; #define TIMER_SHIFT 6 extern int TIMER_USEC; + +#endif /*_TIMER_H_*/