Refactored sound code - slight speedup.

This commit is contained in:
TomW 2016-02-10 20:49:28 +00:00
commit 3a57341837
33 changed files with 706 additions and 535 deletions

View file

@ -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()

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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];
}

View file

@ -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

View file

@ -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++)
{

View file

@ -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);

View file

@ -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;
}

View file

@ -2,6 +2,7 @@
#include <stdlib.h>
#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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -4,3 +4,5 @@ extern int speaker_mute;
extern int speaker_gated;
extern int speaker_enable, was_speaker_enable;
void speaker_update();

View file

@ -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;
}

View file

@ -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
};

View file

@ -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_*/