@@ -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
4040extern 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
9596static constexpr uint32_t opl_ratio = fixed_ratio(49716 , 44100 );
9697static 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