Skip to content

Commit 57b1064

Browse files
committed
[sgu] Generate 48kHz sample, resample to sokol samplerate later
1 parent 20b8480 commit 57b1064

File tree

4 files changed

+14
-32
lines changed

4 files changed

+14
-32
lines changed

src/chips/sgu1.c

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,19 @@ void sgu1_init(sgu1_t* sgu, const sgu1_desc_t* desc) {
2323
CHIPS_ASSERT(desc->tick_hz > 0);
2424
CHIPS_ASSERT(desc->sound_hz > 0);
2525
memset(sgu, 0, sizeof(*sgu));
26-
sgu->sound_hz = desc->sound_hz;
27-
sgu->sample_period = (desc->tick_hz * SGU1_FIXEDPOINT_SCALE) / desc->sound_hz;
28-
sgu->sample_counter = sgu->sample_period;
2926
sgu->sample_mag = desc->magnitude;
3027
sgu->tick_period = (desc->tick_hz * SGU1_FIXEDPOINT_SCALE) / SGU1_CHIP_CLOCK;
3128
sgu->tick_counter = sgu->tick_period;
3229
SoundUnit_Init(&sgu->su, 65536);
33-
sgu->resampler = speex_resampler_init(SGU1_AUDIO_CHANNELS, SGU1_CHIP_CLOCK, sgu->sound_hz, 10, nullptr);
3430
}
3531

3632
void sgu1_reset(sgu1_t* sgu) {
3733
CHIPS_ASSERT(sgu);
3834
SoundUnit_Reset(&sgu->su);
3935
memset(sgu->reg, 0, sizeof(sgu->reg));
4036
sgu->tick_counter = sgu->tick_period;
41-
sgu->sample_counter = sgu->sample_period;
4237
sgu->sample[0] = sgu->sample[1] = 0.0f;
4338
sgu->pins = 0;
44-
speex_resampler_reset_mem(sgu->resampler);
4539
}
4640

4741
/* tick the sound generation, return true when new sample ready */
@@ -52,10 +46,9 @@ static uint64_t _sgu1_tick(sgu1_t* sgu, uint64_t pins) {
5246
sgu->tick_counter += sgu->tick_period;
5347
int32_t l, r;
5448
SoundUnit_NextSample(&sgu->su, &l, &r);
55-
float in[2] = { ((float)l / 32767.0f), ((float)r / 32767.0f) };
56-
spx_uint32_t in_len = 1; // 1 stereo frame
57-
spx_uint32_t out_len = 1; // room for 1 stereo frame
58-
speex_resampler_process_interleaved_float(sgu->resampler, in, &in_len, sgu->sample, &out_len);
49+
sgu->sample[0] = sgu->sample_mag * (float)l / 32767.0f;
50+
sgu->sample[1] = sgu->sample_mag * (float)r / 32767.0f;
51+
pins |= SGU1_SAMPLE;
5952

6053
for (uint8_t i = 0; i < SGU1_NUM_CHANNELS; i++) {
6154
sgu->voice[i].sample_buffer[sgu->voice[i].sample_pos++] = (float)(SoundUnit_GetSample(&sgu->su, i));
@@ -64,23 +57,9 @@ static uint64_t _sgu1_tick(sgu1_t* sgu, uint64_t pins) {
6457
}
6558
}
6659
}
67-
68-
/* new sample? */
69-
pins &= ~SGU1_SAMPLE;
70-
sgu->sample_counter -= SGU1_FIXEDPOINT_SCALE;
71-
while (sgu->sample_counter <= 0) {
72-
sgu->sample_counter += sgu->sample_period;
73-
sgu->sample[0] = sgu->sample_mag * sgu->sample[0];
74-
sgu->sample[1] = sgu->sample_mag * sgu->sample[1];
75-
pins |= SGU1_SAMPLE;
76-
}
7760
return pins;
7861
}
7962

80-
static inline uint8_t _sgu1_selected_channel(sgu1_t* sgu) {
81-
return sgu->reg[SGU1_REG_CHANNEL_SELECT] & (SGU1_NUM_CHANNELS - 1);
82-
}
83-
8463
uint8_t sgu1_reg_read(sgu1_t* sgu, uint8_t reg) {
8564
uint8_t data;
8665
if (reg < 32) {

src/chips/sgu1.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,11 @@ extern "C" {
170170
#define SGU1_VOL_SWEEP_BOUNCE (1 << 7)
171171

172172
#define SGU1_AUDIO_CHANNELS (2)
173-
#define SGU1_AUDIO_SAMPLES (4096)
173+
#define SGU1_AUDIO_SAMPLES (1024)
174174

175175
// setup parameters for sgu1_init()
176176
typedef struct {
177177
int tick_hz; // frequency at which sgu1_tick() will be called in Hz
178-
int sound_hz; // sound sample frequency
179178
float magnitude; // output sample magnitude (0=silence to 1=max volume)
180179
} sgu1_desc_t;
181180

@@ -187,10 +186,7 @@ typedef struct {
187186
uint8_t reg[32];
188187
int tick_period;
189188
int tick_counter;
190-
SpeexResamplerState* resampler;
191189
// sample generation state
192-
int sample_period;
193-
int sample_counter;
194190
float sample_mag;
195191
float sample[SGU1_AUDIO_CHANNELS]; // Left, Right
196192
// voice visualization

src/systems/x65.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ void x65_init(x65_t* sys, const x65_desc_t* desc) {
6464
&sys->sgu,
6565
&(sgu1_desc_t){
6666
.tick_hz = X65_FREQUENCY,
67-
.sound_hz = _X65_DEFAULT(desc->audio.sample_rate, 44100),
6867
.magnitude = _X65_DEFAULT(desc->audio.volume, 1.0f),
6968
});
7069
beeper_init(

src/x65.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ static struct {
6868
} dbg;
6969
x65_snapshot_t snapshots[UI_SNAPSHOT_MAX_SLOTS];
7070
#endif
71+
SpeexResamplerState* resampler;
7172
} state;
7273

7374
#ifdef CHIPS_USE_UI
@@ -110,7 +111,11 @@ static void* labels = NULL;
110111
// audio-streaming callback
111112
static void push_audio(const float* samples, int num_samples, void* user_data) {
112113
(void)user_data;
113-
saudio_push(samples, num_samples / X65_AUDIO_CHANNELS);
114+
spx_uint32_t in_len = num_samples / SGU1_AUDIO_CHANNELS;
115+
spx_uint32_t out_len = X65_MAX_AUDIO_SAMPLES;
116+
static float buf[X65_MAX_AUDIO_SAMPLES];
117+
speex_resampler_process_interleaved_float(state.resampler, samples, &in_len, buf, &out_len);
118+
saudio_push(buf, out_len);
114119
}
115120

116121
// get x65_desc_t struct based on joystick type
@@ -149,9 +154,11 @@ static void app_load_rom_labels(const char* rom_file) {
149154

150155
void app_init(void) {
151156
saudio_setup(&(saudio_desc){
152-
.num_channels = X65_AUDIO_CHANNELS,
157+
.sample_rate = SGU_CHIP_CLOCK,
158+
.num_channels = SGU_AUDIO_CHANNELS,
153159
.logger.func = slog_func,
154160
});
161+
state.resampler = speex_resampler_init(SGU1_AUDIO_CHANNELS, SGU_CHIP_CLOCK, saudio_sample_rate(), 4, 0);
155162
x65_joystick_type_t joy_type = arguments.joy ? X65_JOYSTICKTYPE_DIGITAL_1 : X65_JOYSTICKTYPE_NONE;
156163
if (sargs_exists("joystick")) {
157164
if (sargs_equals("joystick", "digital_1")) {
@@ -354,6 +361,7 @@ void app_cleanup(void) {
354361
ui_discard();
355362
#endif
356363
saudio_shutdown();
364+
speex_resampler_destroy(state.resampler);
357365
gfx_shutdown();
358366
sargs_shutdown();
359367
hid_shutdown();

0 commit comments

Comments
 (0)