Skip to content

Commit 779a81b

Browse files
committed
More optimization
1 parent b076427 commit 779a81b

File tree

4 files changed

+88
-70
lines changed

4 files changed

+88
-70
lines changed

sw/audio_fifo.c

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@
3131
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
3232
#endif
3333

34-
// Current samples in fifo
35-
uint32_t fifo_level(audio_fifo_t *fifo) {
36-
return fifo->samples_in_fifo;
37-
}
38-
3934
// Initialize the FIFO (called by producer_init or directly by user)
4035
void fifo_init(audio_fifo_t *fifo) {
4136
// Initialize FIFO structure
@@ -53,20 +48,6 @@ void fifo_reset(audio_fifo_t *fifo) {
5348
fifo->samples_in_fifo = 0;
5449
}
5550

56-
// Add a sample to the FIFO (called by producer)
57-
bool fifo_add_sample(audio_fifo_t *fifo, audio_sample_t sample) {
58-
if (fifo->samples_in_fifo == AUDIO_FIFO_SIZE) {
59-
return false;
60-
}
61-
fifo->buffer[fifo->write_idx] = sample;
62-
fifo->write_idx = (fifo->write_idx + 1) & (AUDIO_FIFO_BITS);
63-
fifo->samples_in_fifo++;
64-
if (fifo->samples_in_fifo >= AUDIO_FIFO_START_THRESHOLD) {
65-
fifo->state = FIFO_STATE_RUNNING;
66-
}
67-
return true;
68-
}
69-
7051
// Add multiple samples to the FIFO
7152
bool fifo_add_samples(audio_fifo_t *fifo, const audio_sample_t *samples_buffer, uint32_t num_samples_to_add) {
7253
// Check basic conditions

sw/audio_fifo.h

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
// #include "pico/sem.h"
3030

3131
// Configuration
32-
#define AUDIO_FIFO_SIZE 1024 // Must be power of 2
32+
#define AUDIO_FIFO_SIZE 256 // Must be power of 2
3333
#define AUDIO_FIFO_BITS (AUDIO_FIFO_SIZE - 1)
3434
#define AUDIO_FIFO_START_THRESHOLD (AUDIO_FIFO_SIZE >> 1) // Start playback when half full
3535

@@ -60,16 +60,47 @@ typedef struct {
6060
// FIFO management functions (implemented in audio_fifo.c)
6161
// No more get_audio_fifo() - caller owns the fifo instance(s)
6262
void fifo_init(audio_fifo_t *fifo);
63-
uint32_t fifo_level(audio_fifo_t *fifo);
6463
void fifo_reset(audio_fifo_t *fifo);
65-
bool fifo_add_sample(audio_fifo_t *fifo, audio_sample_t sample);
6664
bool fifo_add_samples(audio_fifo_t *fifo, const audio_sample_t *samples_buffer, uint32_t num_samples_to_add);
6765

66+
// Inline functions for performance
67+
inline uint32_t fifo_level(audio_fifo_t *fifo) {
68+
return fifo->samples_in_fifo;
69+
}
70+
71+
inline bool fifo_add_sample(audio_fifo_t *fifo, audio_sample_t sample) {
72+
if (fifo->samples_in_fifo == AUDIO_FIFO_SIZE) {
73+
return false;
74+
}
75+
fifo->buffer[fifo->write_idx] = sample;
76+
fifo->write_idx = (fifo->write_idx + 1) & AUDIO_FIFO_BITS;
77+
fifo->samples_in_fifo++;
78+
if (fifo->samples_in_fifo >= AUDIO_FIFO_START_THRESHOLD) {
79+
fifo->state = FIFO_STATE_RUNNING;
80+
}
81+
return true;
82+
}
83+
6884
uint32_t fifo_take_samples(audio_fifo_t *fifo, uint32_t num_samples);
6985

7086
inline uint32_t fifo_free_space(audio_fifo_t *fifo) {
7187
return AUDIO_FIFO_SIZE - fifo->samples_in_fifo;
7288
}
89+
90+
// Inline version of fifo_take_samples for performance-critical code
91+
inline uint32_t fifo_take_samples_inline(audio_fifo_t *fifo, uint32_t num_samples) {
92+
if (fifo->state == FIFO_STATE_STOPPED) {
93+
return 0;
94+
}
95+
uint32_t samples_returned = fifo->samples_in_fifo < num_samples ? fifo->samples_in_fifo : num_samples;
96+
fifo->read_idx = (fifo->read_idx + samples_returned) & AUDIO_FIFO_BITS;
97+
fifo->samples_in_fifo -= samples_returned;
98+
if (fifo->samples_in_fifo == 0) {
99+
fifo->state = FIFO_STATE_STOPPED;
100+
}
101+
return samples_returned;
102+
}
103+
73104
// Helper for consumer to get one sample, this is a more fundamental FIFO op
74105

75106
#ifdef __cplusplus

sw/picogus.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ int main()
11091109

11101110
#ifdef SOUND_SB
11111111
puts("Initializing SoundBlaster DSP");
1112-
sbdsp_init();
1112+
// sbdsp_init();
11131113
#endif // SOUND_SB
11141114
#ifdef SOUND_OPL
11151115
puts("Creating OPL");

sw/sbplay.cpp

Lines changed: 53 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ extern "C" void OPL_Pico_WriteRegister(unsigned int reg_num, unsigned int value)
3838
#include "audio_fifo.h"
3939
#if SOUND_SB
4040
extern int16_t sbdsp_sample();
41+
extern void sbdsp_init();
4142
#endif // SOUND_SB
4243
#if defined(SOUND_SB) || defined(USB_MOUSE) || defined(SOUND_MPU)
4344
#include "pico_pic.h"
@@ -94,11 +95,9 @@ static constexpr uint32_t fixed_ratio(uint16_t a, uint16_t b) {
9495

9596
static constexpr uint32_t opl_ratio = fixed_ratio(49716, 44100);
9697
static audio_fifo_t opl_out_fifo;
97-
static constexpr uint32_t OPL_SAMPLE_COUNT = 2;
98-
static constexpr uint32_t OPL_BUFFER_BITS = (OPL_SAMPLE_COUNT << 1) - 1;
99-
static constexpr uint32_t OPL_OUT_SAMPLE_COUNT = 1;//(OPL_SAMPLE_COUNT * 44100 / 49716);// - 1;
100-
static int16_t opl_buffer[OPL_SAMPLE_COUNT << 1] = {0};
101-
uint32_t opl_frac = 0;
98+
static int16_t opl_current_sample = 0;
99+
static int16_t opl_next_sample = 0;
100+
static bool opl_need_new_sample = true;
102101

103102
/**
104103
* Linear interpolation in fixed-point
@@ -133,20 +132,21 @@ void audio_sample_handler(void) {
133132

134133
#ifdef CDROM
135134
static uint32_t cd_index = 0;
136-
const uint32_t has_cd_samples = fifo_take_samples(cd_fifo, 2);
135+
const uint32_t has_cd_samples = fifo_take_samples_inline(cd_fifo, 2);
137136
if (has_cd_samples) {
138-
sample_l += cd_fifo->buffer[(cd_index++) & AUDIO_FIFO_BITS];
139-
sample_r += cd_fifo->buffer[(cd_index++) & AUDIO_FIFO_BITS];
137+
sample_l += cd_fifo->buffer[cd_index++];
138+
sample_r += cd_fifo->buffer[cd_index++];
139+
cd_index &= AUDIO_FIFO_BITS;
140140
}
141141
#endif
142142

143143
static uint32_t opl_out_index = 0;
144-
const uint32_t has_opl_samples = fifo_take_samples(&opl_out_fifo, 1);
144+
const uint32_t has_opl_samples = fifo_take_samples_inline(&opl_out_fifo, 1);
145145
if (has_opl_samples) {
146-
uint32_t idx = opl_out_index & AUDIO_FIFO_BITS;
147-
sample_l += opl_out_fifo.buffer[idx];
148-
sample_r += opl_out_fifo.buffer[idx];
149-
++opl_out_index;
146+
int16_t opl_sample = opl_out_fifo.buffer[opl_out_index++];
147+
sample_l += opl_sample;
148+
sample_r += opl_sample;
149+
opl_out_index &= AUDIO_FIFO_BITS;
150150
}
151151

152152
const sample_pair clamped = {.data16 = {
@@ -177,12 +177,18 @@ void play_adlib() {
177177
MPU401_Init(settings.MPU.delaySysex, settings.MPU.fakeAllNotesOff);
178178
#endif
179179

180+
#if SOUND_SB
181+
sbdsp_init();
182+
#endif
180183
init_audio();
181184

182185
printf("opl_ratio: %x ", opl_ratio);
183186
uint32_t opl_pos = 0;
184-
uint32_t opl_index = 0;
185-
uint32_t opl_buffer_idx = 0x0;
187+
188+
// Initialize OPL samples
189+
OPL_Pico_simple(&opl_current_sample, 1);
190+
OPL_Pico_simple(&opl_next_sample, 1);
191+
opl_need_new_sample = false;
186192

187193
cd_fifo = cdrom_audio_fifo_peek(&cdrom);
188194

@@ -192,43 +198,43 @@ void play_adlib() {
192198
pwm_init(pwm_slice_num, &pwm_c, false);
193199
pwm_set_irq_enabled(pwm_slice_num, true);
194200
irq_set_exclusive_handler(PWM_IRQ_WRAP, audio_sample_handler);
201+
irq_set_priority(PWM_IRQ_WRAP, PICO_LOWEST_IRQ_PRIORITY);
195202
irq_set_enabled(PWM_IRQ_WRAP, true);
196-
irq_set_priority(PWM_IRQ_WRAP, 255);
197203
pwm_set_enabled(pwm_slice_num, true);
198204

199205
for (;;) {
200206
#if CDROM
201-
cdrom_audio_callback(&cdrom, 1024);
202-
#endif
203-
uint32_t render_opl_samples = MIN(fifo_free_space(&opl_out_fifo), OPL_OUT_SAMPLE_COUNT);
204-
if (fifo_free_space(&opl_out_fifo) >= render_opl_samples) {
205-
if (
206-
((opl_index & OPL_SAMPLE_COUNT) && opl_buffer_idx != 0x0) ||
207-
(!(opl_index & OPL_SAMPLE_COUNT) && opl_buffer_idx != OPL_SAMPLE_COUNT)
208-
) {
209-
opl_buffer_idx = (opl_index + OPL_SAMPLE_COUNT) & OPL_SAMPLE_COUNT;
210-
// bool notfirst = false;
211-
while (opl_cmd_buffer.tail != opl_cmd_buffer.head) {
212-
// if (!notfirst) {
213-
#ifndef PICOW
214-
// gpio_xor_mask(LED_PIN);
215-
#endif
216-
// notfirst = true;
217-
// }
218-
auto cmd = opl_cmd_buffer.cmds[opl_cmd_buffer.tail];
219-
OPL_Pico_WriteRegister(cmd.addr, cmd.data);
220-
++opl_cmd_buffer.tail;
221-
}
222-
OPL_Pico_simple(opl_buffer + opl_buffer_idx, OPL_SAMPLE_COUNT);
223-
}
224-
for (int i = 0; i < render_opl_samples; ++i) {
225-
opl_index = (opl_pos >> FRAC_BITS);
226-
fifo_add_sample(&opl_out_fifo, lerp_fixed(
227-
opl_buffer[opl_index & OPL_BUFFER_BITS],
228-
opl_buffer[(opl_index + 1) & OPL_BUFFER_BITS],
229-
opl_pos & FRAC_MASK)
230-
);
231-
opl_pos += opl_ratio;
207+
cdrom_audio_callback(&cdrom, 256);
208+
#endif
209+
// Process any pending OPL commands
210+
while (opl_cmd_buffer.tail != opl_cmd_buffer.head) {
211+
auto cmd = opl_cmd_buffer.cmds[opl_cmd_buffer.tail];
212+
OPL_Pico_WriteRegister(cmd.addr, cmd.data);
213+
++opl_cmd_buffer.tail;
214+
}
215+
216+
// Generate OPL samples and add to output FIFO
217+
while (fifo_free_space(&opl_out_fifo) > 0) {
218+
// Interpolate at current position
219+
fifo_add_sample(&opl_out_fifo, lerp_fixed(
220+
opl_current_sample,
221+
opl_next_sample,
222+
opl_pos & FRAC_MASK
223+
));
224+
225+
// Advance position
226+
opl_pos += opl_ratio;
227+
228+
// While we've advanced past one or more OPL samples
229+
while ((opl_pos >> FRAC_BITS) > 0) {
230+
// Move to next sample
231+
opl_current_sample = opl_next_sample;
232+
233+
// Generate new next sample
234+
OPL_Pico_simple(&opl_next_sample, 1);
235+
236+
// Subtract 1.0 from position
237+
opl_pos -= (1u << FRAC_BITS);
232238
}
233239
}
234240
#ifdef USB_STACK

0 commit comments

Comments
 (0)