Skip to content

Commit c6ad303

Browse files
committed
Stereo sound support in SGU-1 and Emu
1 parent 90956b2 commit c6ad303

5 files changed

Lines changed: 23 additions & 17 deletions

File tree

src/chips/sgu1.cc

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ void sgu1_init(sgu1_t* sgu, const sgu1_desc_t* desc) {
3535
sgu->sample_period = (desc->tick_hz * SGU1_FIXEDPOINT_SCALE) / desc->sound_hz;
3636
sgu->sample_counter = sgu->sample_period;
3737
sgu->sample_mag = desc->magnitude;
38-
sgu->sample_accum_count = 1.0f;
38+
sgu->sample_accum_count[0] = sgu->sample_accum_count[1] = 1.0f;
3939
sgu->su = new SoundUnit();
4040
sgu->tick_period = (desc->tick_hz * SGU1_FIXEDPOINT_SCALE) / (CHIP_CLOCK / CHIP_DIVIDER);
4141
sgu->tick_counter = sgu->tick_period;
@@ -48,9 +48,9 @@ void sgu1_reset(sgu1_t* sgu) {
4848
memset(sgu->reg, 0, sizeof(sgu->reg));
4949
sgu->tick_counter = sgu->tick_period;
5050
sgu->sample_counter = sgu->sample_period;
51-
sgu->sample = 0.0f;
52-
sgu->sample_accum = 0.0f;
53-
sgu->sample_accum_count = 1.0f;
51+
sgu->sample[0] = sgu->sample[1] = 0.0f;
52+
sgu->sample_accum[0] = sgu->sample_accum[1] = 0.0f;
53+
sgu->sample_accum_count[0] = sgu->sample_accum_count[1] = 1.0f;
5454
sgu->pins = 0;
5555
}
5656

@@ -62,9 +62,10 @@ static uint64_t _sgu1_tick(sgu1_t* sgu, uint64_t pins) {
6262
sgu->tick_counter += sgu->tick_period;
6363
short l, r;
6464
SGU_SU->NextSample(&l, &r);
65-
int sample = ((int)l + (int)r) >> 1;
66-
sgu->sample_accum += ((float)sample / 32767.0f);
67-
sgu->sample_accum_count += 1.0f;
65+
sgu->sample_accum[0] += ((float)l / 32767.0f);
66+
sgu->sample_accum_count[0] += 1.0f;
67+
sgu->sample_accum[1] += ((float)r / 32767.0f);
68+
sgu->sample_accum_count[1] += 1.0f;
6869

6970
for (int i = 0; i < SGU1_NUM_CHANNELS; i++) {
7071
sgu->voice[i].sample_buffer[sgu->voice[i].sample_pos++] = (float)SGU_SU->GetSample(i);
@@ -78,10 +79,12 @@ static uint64_t _sgu1_tick(sgu1_t* sgu, uint64_t pins) {
7879
sgu->sample_counter -= SGU1_FIXEDPOINT_SCALE;
7980
if (sgu->sample_counter <= 0) {
8081
sgu->sample_counter += sgu->sample_period;
81-
float s = sgu->sample_accum / sgu->sample_accum_count;
82-
sgu->sample = sgu->sample_mag * s;
83-
sgu->sample_accum = 0.0f;
84-
sgu->sample_accum_count = 0.0f;
82+
float l = sgu->sample_accum[0] / sgu->sample_accum_count[0];
83+
sgu->sample[0] = sgu->sample_mag * l;
84+
float r = sgu->sample_accum[1] / sgu->sample_accum_count[1];
85+
sgu->sample[1] = sgu->sample_mag * r;
86+
sgu->sample_accum[0] = sgu->sample_accum[1] = 0.0f;
87+
sgu->sample_accum_count[0] = sgu->sample_accum_count[1] = 0.0f;
8588
pins |= SGU1_SAMPLE;
8689
}
8790
else {

src/chips/sgu1.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,10 @@ typedef struct {
183183
// sample generation state
184184
int sample_period;
185185
int sample_counter;
186-
float sample_accum;
187-
float sample_accum_count;
188186
float sample_mag;
189-
float sample;
187+
float sample_accum[2];
188+
float sample_accum_count[2];
189+
float sample[2]; // Left, Right
190190
// voice visualization
191191
struct {
192192
int sample_pos;

src/systems/x65.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ void x65_init(x65_t* sys, const x65_desc_t* desc) {
3737
sys->joystick_type = desc->joystick_type;
3838
sys->debug = desc->debug;
3939
sys->audio.callback = desc->audio.callback;
40-
sys->audio.num_samples = _X65_DEFAULT(desc->audio.num_samples, X65_DEFAULT_AUDIO_SAMPLES);
40+
sys->audio.num_samples = _X65_DEFAULT(desc->audio.num_samples, X65_DEFAULT_AUDIO_SAMPLES) * X65_AUDIO_CHANNELS;
4141
CHIPS_ASSERT(sys->audio.num_samples <= X65_MAX_AUDIO_SAMPLES);
4242

4343
// initialize the hardware
@@ -225,7 +225,8 @@ static uint64_t _x65_tick(x65_t* sys, uint64_t pins) {
225225
sgu_pins = sgu1_tick(&sys->sgu, sgu_pins);
226226
if (sgu_pins & SGU1_SAMPLE) {
227227
// new audio sample ready
228-
sys->audio.sample_buffer[sys->audio.sample_pos++] = sys->sgu.sample;
228+
sys->audio.sample_buffer[sys->audio.sample_pos++] = sys->sgu.sample[0];
229+
sys->audio.sample_buffer[sys->audio.sample_pos++] = sys->sgu.sample[1];
229230
if (sys->audio.sample_pos == sys->audio.num_samples) {
230231
if (sys->audio.callback.func) {
231232
sys->audio.callback.func(

src/systems/x65.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern "C" {
5050
#define X65_FREQUENCY (1826300) // clock frequency in Hz
5151
#define X65_MAX_AUDIO_SAMPLES (1024) // max number of audio samples in internal sample buffer
5252
#define X65_DEFAULT_AUDIO_SAMPLES (128) // default number of samples in internal sample buffer
53+
#define X65_AUDIO_CHANNELS (2) // stereo output
5354

5455
// X65 joystick types
5556
typedef enum {

src/x65.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ static void* labels = NULL;
109109
// audio-streaming callback
110110
static void push_audio(const float* samples, int num_samples, void* user_data) {
111111
(void)user_data;
112-
saudio_push(samples, num_samples);
112+
saudio_push(samples, num_samples / X65_AUDIO_CHANNELS);
113113
}
114114

115115
// get x65_desc_t struct based on joystick type
@@ -147,6 +147,7 @@ static void app_load_rom_labels(const char* rom_file) {
147147

148148
void app_init(void) {
149149
saudio_setup(&(saudio_desc){
150+
.num_channels = X65_AUDIO_CHANNELS,
150151
.logger.func = slog_func,
151152
});
152153
x65_joystick_type_t joy_type = arguments.joy ? X65_JOYSTICKTYPE_DIGITAL_1 : X65_JOYSTICKTYPE_NONE;

0 commit comments

Comments
 (0)