@@ -104,6 +104,24 @@ void common_hal_audiobusio_i2s_construct(audiobusio_i2s_obj_t *self,
104104
105105 self -> playing = false;
106106 audio_dma_init (& self -> dma );
107+
108+ if (self -> state_machine .in ) {
109+ self -> buffer [0 ] = m_malloc (self -> buffer_size );
110+ if (self -> buffer [0 ] == NULL ) {
111+ common_hal_audiobusio_i2s_deinit (self );
112+ m_malloc_fail (self -> buffer_size );
113+ }
114+ memset (self -> buffer [0 ], 0 , self -> buffer_size );
115+
116+ self -> buffer [1 ] = m_malloc (self -> buffer_size );
117+ if (self -> buffer [1 ] == NULL ) {
118+ common_hal_audiobusio_i2s_deinit (self );
119+ m_malloc_fail (self -> buffer_size );
120+ }
121+ memset (self -> buffer [1 ], 0 , self -> buffer_size );
122+
123+ self -> last_buf_idx = 1 ; // Which buffer to use first, toggle between 0 and 1
124+ }
107125}
108126
109127void i2s_configure_audio_dma (audiobusio_i2s_obj_t * self , mp_obj_t sample , bool loop , uint32_t sample_rate , uint8_t bits_per_sample , bool force ) {
@@ -159,6 +177,9 @@ void common_hal_audiobusio_i2s_deinit(audiobusio_i2s_obj_t *self) {
159177 common_hal_rp2pio_statemachine_deinit (& self -> state_machine );
160178
161179 audio_dma_deinit (& self -> dma );
180+
181+ self -> buffer [0 ] = NULL ;
182+ self -> buffer [1 ] = NULL ;
162183}
163184
164185// output_buffer may be a byte buffer or a halfword buffer.
@@ -173,21 +194,18 @@ uint32_t common_hal_audiobusio_i2s_record_to_buffer(audiobusio_i2s_obj_t *self,
173194 i2s_configure_audio_dma (self , self , true, self -> sample_rate , self -> bits_per_sample , true);
174195
175196 size_t output_count = 0 ;
176- int16_t * buffer ;
177- size_t buffer_length ;
197+ int16_t * buffer [2 ];
198+ int8_t buffer_idx = 1 ;
199+ size_t buffer_length = MIN ((output_buffer_length - output_count ), self -> buffer_size / sizeof (int16_t ));
178200
179201 while (output_count < output_buffer_length ) {
180- // Do other things while we wait for the buffer to fill.
181- while (self -> last_record_index == self -> dma .input_index ) {
182- RUN_BACKGROUND_TASKS ;
183- }
184- self -> last_record_index = self -> dma .input_index ;
185-
186- buffer = (int16_t * )audio_dma_get_buffer (& self -> dma );
187- buffer_length = MIN ((output_buffer_length - output_count ), self -> buffer_size / sizeof (int16_t ));
202+ do {
203+ buffer_idx = !buffer_idx ;
204+ buffer [buffer_idx ] = (int16_t * )audio_dma_get_buffer (& self -> dma );
205+ } while (buffer [buffer_idx ] == NULL || buffer [0 ] == buffer [1 ]);
188206
189207 for (size_t i = 0 ; i < buffer_length ; i ++ ) {
190- output_buffer [i + output_count ] = buffer [i ];
208+ output_buffer [i + output_count ] = buffer [buffer_idx ][ i ];
191209 }
192210
193211 output_count += buffer_length ;
@@ -304,9 +322,10 @@ void audiobusio_i2s_reset_buffer(audiobusio_i2s_obj_t *self,
304322 mp_raise_NotImplementedError (MP_ERROR_TEXT ("Single channel output not supported." ));
305323 }
306324
325+ memset (self -> buffer [0 ], 0 , self -> buffer_size );
326+ memset (self -> buffer [1 ], 0 , self -> buffer_size );
327+
307328 i2s_configure_audio_dma (self , self , true, self -> sample_rate , self -> bits_per_sample , false);
308- self -> last_record_index = -1 ;
309- self -> last_sample_index = -1 ;
310329}
311330
312331audioio_get_buffer_result_t audiobusio_i2s_get_buffer (audiobusio_i2s_obj_t * self ,
@@ -322,14 +341,22 @@ audioio_get_buffer_result_t audiobusio_i2s_get_buffer(audiobusio_i2s_obj_t *self
322341 mp_raise_NotImplementedError (MP_ERROR_TEXT ("Single channel output not supported." ));
323342 }
324343
325- // Do other things while we wait for the buffer to fill.
326- while (self -> last_sample_index == self -> dma .input_index ) {
327- RUN_BACKGROUND_TASKS ;
328- }
329- self -> last_sample_index = self -> dma .input_index ;
344+ // Switch our buffers to the other buffer
345+ self -> last_buf_idx = !self -> last_buf_idx ;
330346
347+ uint8_t * dma_buffer ;
348+ do {
349+ dma_buffer = audio_dma_get_buffer (& self -> dma );
350+ } while (dma_buffer == NULL );
351+
352+ // Copy dma buffer to output buffer
353+ memcpy (self -> buffer [self -> last_buf_idx ], dma_buffer , self -> buffer_size );
354+
355+ // Finally pass our buffer and length to the calling audio function
356+ * buffer = (uint8_t * )self -> buffer [self -> last_buf_idx ];
331357 * buffer_length = self -> buffer_size ;
332- * buffer = audio_dma_get_buffer (& self -> dma );
358+
359+ // I2S always returns more data unless an error occured (see audiocore/__init__.h)
333360 return GET_BUFFER_MORE_DATA ;
334361}
335362
0 commit comments