Skip to content

Commit

Permalink
sound: Poll SN76489 at 125 kHz
Browse files Browse the repository at this point in the history
Polling the SN76489 at 125 kHz (the native "update" rate on real hardware, 4 MHz
/ 32) improves the audio quality of multi-voice sample playback, by
significantly reducing the time spent in "in-between" states where not all
voices have yet had their volumes updated.

As part of this, the handling of SN write is modified to a poll as part of the
125 kHz update routine. This allows multiple writes with the chip enable held
active to be honoured (eg the Castlevania III music conversion).
  • Loading branch information
sarah-walker-pcem committed Jul 23, 2023
1 parent 44b4252 commit 8e92d06
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 33 deletions.
2 changes: 1 addition & 1 deletion src/6502.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ static inline void polltime(int c)
via_poll(&sysvia, c);
via_poll(&uservia, c);
video_poll(c, 1);
sound_poll(c);
otherstuffcount -= c;
if (motoron) {
if (fdc_time) {
Expand Down Expand Up @@ -1057,7 +1058,6 @@ static void otherstuff_poll(void) {
acia_poll(&sysacia);
if (sound_music5000)
music2000_poll();
sound_poll();
if (!tapelcount) {
tape_poll();
tapelcount = tapellatch;
Expand Down
4 changes: 2 additions & 2 deletions src/resid.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ void sid_init()
psid->sid->write(c,0);

if (!psid->sid->set_sampling_parameters((float)cycles_per_sec, method,
(float) FREQ_SO, 0.9*((float) FREQ_SO)/2.0))
(float) FREQ_SID, 0.9*((float) FREQ_SID)/2.0))
{
// printf("reSID failed!\n");
}
Expand All @@ -72,7 +72,7 @@ void sid_reset()
void sid_settype(int resamp, int model)
{
sampling_method method=(resamp)?SAMPLE_RESAMPLE_INTERPOLATE:SAMPLE_INTERPOLATE;
if (!psid->sid->set_sampling_parameters((float)1000000, method,(float) FREQ_SO, 0.9*((float) FREQ_SO)/2.0))
if (!psid->sid->set_sampling_parameters((float)1000000, method,(float) FREQ_SID, 0.9*((float) FREQ_SID)/2.0))
{
// rpclog("Change failed\n");
}
Expand Down
12 changes: 8 additions & 4 deletions src/sn76489.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "sn76489.h"
#include "sound.h"
#include "via.h"
#include "uservia.h"
#include "sysvia.h"

uint8_t sn_freqhi[4], sn_freqlo[4];
uint8_t sn_vol[4];
Expand Down Expand Up @@ -69,6 +69,10 @@ void sn_fillbuf(int16_t *buffer, int len)
{
int c, d;
static int sidcount = 0;
uint8_t sdb_data;

if (sysvia_get_sn_data(&sdb_data))
sn_write(sdb_data);

for (d = 0; d < len; d++)
{
Expand All @@ -78,7 +82,7 @@ void sn_fillbuf(int16_t *buffer, int len)
if (sn_latch[c] > 256) buffer[d] += (int16_t) (snwaves[curwave][sn_stat[c]] * volslog[sn_vol[c]]);
else buffer[d] += (int16_t) (volslog[sn_vol[c]] * 127);

sn_count[c] -= 8192;
sn_count[c] -= 2048;
while ((int)sn_count[c] < 0 && sn_latch[c])
{
sn_count[c] += sn_latch[c];
Expand All @@ -94,7 +98,7 @@ void sn_fillbuf(int16_t *buffer, int len)
}
else buffer[d] += (((sn_shift & 1) ^ 1) * 127 * volslog[sn_vol[0]] * 2);

sn_count[0] -= 512;
sn_count[0] -= 128;
while ((int)sn_count[0] < 0 && sn_latch[0])
{
sn_count[0] += (sn_latch[0] * 2);
Expand All @@ -119,7 +123,7 @@ void sn_fillbuf(int16_t *buffer, int len)
// buffer[d] += (lpt_dac * 32);

sidcount++;
if (sidcount == 624)
if (sidcount == 2496)
{
sidcount = 0;
if (!sn_rect_dir)
Expand Down
66 changes: 46 additions & 20 deletions src/sound.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,24 @@ static ALLEGRO_MIXER *mixer;
static ALLEGRO_AUDIO_STREAM *stream;

static int sound_pos = 0;
static int sound_sn_pos = 0;

static short sound_buffer[BUFLEN_SO];

#define NCoef 4
static int sound_sn76489_cycles = 0, sound_poll_cycles = 0;

#define NCoef 2
static float iir(float NewSample) {
static const float ACoef[NCoef+1] = {
0.30631912757971225000,
0.00000000000000000000,
-0.61263825515942449000,
0.00000000000000000000,
0.30631912757971225000
0.9844825527642453,
-1.9689651055284907,
0.9844825527642453
};

static const float BCoef[NCoef+1] = {
1.00000000000000000000,
-1.86772356053227330000,
1.08459167506874430000,
-0.37711292573951394000,
0.17253125052500490000
1,
-1.9687243044104659,
0.9692059066465155
};

static float y[NCoef+1]; //output samples
Expand All @@ -60,25 +60,29 @@ static float iir(float NewSample) {
return y[0];
}

void sound_poll(void)
static void sound_poll_all(void)
{
float *buf;
int c;

if ((sound_internal || sound_beebsid) && stream) {
int16_t temp_buffer[2] = {0};

if (sound_beebsid)
sid_fillbuf(sound_buffer + sound_pos, 2);
if (sound_internal)
sn_fillbuf(sound_buffer + sound_pos, 2);
sid_fillbuf(temp_buffer, 2);
if (sound_paula)
paula_fillbuf(sound_buffer + sound_pos, 2);
paula_fillbuf(temp_buffer, 2);
if (sound_dac) {
sound_buffer[sound_pos] += (((int)lpt_dac - 0x80) * 32);
sound_buffer[sound_pos + 1] += (((int)lpt_dac - 0x80) * 32);
temp_buffer[0] += (((int)lpt_dac - 0x80) * 32);
temp_buffer[1] += (((int)lpt_dac - 0x80) * 32);
}

// skip forward 2 mono samples
sound_pos += 2;
for (c = 0; c < 8/2; c++) {
sound_buffer[sound_pos + c] += temp_buffer[0];
sound_buffer[sound_pos + c + 4] += temp_buffer[1];
}
// skip forward 8 mono samples
sound_pos += 8;
if (sound_pos == BUFLEN_SO) {
if ((buf = al_get_audio_stream_fragment(stream))) {
if (sound_filter) {
Expand All @@ -93,11 +97,33 @@ void sound_poll(void)
} else
log_debug("sound: overrun");
sound_pos = 0;
sound_sn_pos = 0;
memset(sound_buffer, 0, sizeof(sound_buffer));
}
}
}

void sound_poll(int cycles)
{
sound_sn76489_cycles -= cycles;
if (sound_sn76489_cycles < 0)
{
sound_sn76489_cycles += 16;

if (sound_internal)
sn_fillbuf(&sound_buffer[sound_sn_pos], 1);

sound_sn_pos++;

sound_poll_cycles -= 16;
if (sound_poll_cycles < 0)
{
sound_poll_cycles += 128;
sound_poll_all();
}
}
}

static ALLEGRO_VOICE *sound_create_voice(void)
{
ALLEGRO_VOICE *voice;
Expand Down
7 changes: 4 additions & 3 deletions src/sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@

/* Source frequencies in Hz */

#define FREQ_SO 31250 // normal sound
#define FREQ_SO 125000 // normal sound
#define FREQ_SID 31250 // BeebSID
#define FREQ_DD 44100 // disc drive noise
#define FREQ_M5 46875 // music 5000

/* Source buffer lengths in time samples */

#define BUFLEN_SO 2000 // 64ms @ 31.25KHz (must be multiple of 2)
#define BUFLEN_SO 8000 // 64ms @ 125KHz (must be multiple of 8)
#define BUFLEN_DD 4410 // 100ms @ 44.1KHz
#define BUFLEN_M5 1500 // 64ms @ 46.875KHz (must be multiple of 3)

Expand All @@ -20,6 +21,6 @@ extern bool sound_ddnoise, sound_tape;
extern bool sound_music5000, sound_filter, sound_paula;

void sound_init(void);
void sound_poll(void);
void sound_poll(int cycles);

#endif
10 changes: 7 additions & 3 deletions src/sysvia.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,6 @@ static void sysvia_write_IC32(uint8_t val)

sysvia_update_sdb();

if (!(IC32 & 1) && (oldIC32 & 1))
sn_write(sdbval);

scrsize = ((IC32 & 0x10) ? 2 : 0) | ((IC32 & 0x20) ? 1 : 0);

log_debug("sysvia: IC32=%02X", IC32);
Expand Down Expand Up @@ -194,3 +191,10 @@ void sysvia_loadstate(FILE *f)
IC32=getc(f);
scrsize=((IC32&16)?2:0)|((IC32&32)?1:0);
}

int sysvia_get_sn_data(uint8_t *data)
{
*data = sdbval;

return !(IC32 & 1);
}
2 changes: 2 additions & 0 deletions src/sysvia.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ void sysvia_set_ca2(int level);
void sysvia_set_cb1(int level);
void sysvia_set_cb2(int level);

int sysvia_get_sn_data(uint8_t *data);

#endif

0 comments on commit 8e92d06

Please sign in to comment.