Refactored sound code - slight speedup.
This commit is contained in:
parent
0b6be244ac
commit
3a57341837
33 changed files with 706 additions and 535 deletions
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
47
src/sound.c
47
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
110
src/sound_opl.c
110
src/sound_opl.c
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
184
src/sound_sb.c
184
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,3 +4,5 @@ extern int speaker_mute;
|
|||
|
||||
extern int speaker_gated;
|
||||
extern int speaker_enable, was_speaker_enable;
|
||||
|
||||
void speaker_update();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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_*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue