3636#define BUFFER_EXPANSION (4) // smooth out the samples via linear interpolation
3737#define OUT_CHUNK_SIZE (BUFFER_EXPANSION * AUDIO_CHUNK_SIZE)
3838
39- static volatile bool audio_running = false;
39+ typedef enum {
40+ AUDIO_OUTPUT_STATE_IDLE ,
41+ AUDIO_OUTPUT_STATE_DATA_READY ,
42+ AUDIO_OUTPUT_STATE_DATA_WRITTEN ,
43+ } audio_output_state_t ;
44+
4045static uint8_t audio_output_buffer [OUT_CHUNK_SIZE ];
41- static volatile int audio_output_read ;
42- static volatile bool audio_fetecher_scheduled ;
46+ static volatile audio_output_state_t audio_output_state ;
47+ static volatile bool audio_fetcher_scheduled ;
4348
4449microbit_audio_frame_obj_t * microbit_audio_frame_make_new (void );
4550
51+ static inline bool audio_is_running (void ) {
52+ return audio_source_iter != NULL ;
53+ }
54+
4655void microbit_audio_stop (void ) {
4756 audio_source_iter = NULL ;
48- audio_running = false;
4957}
5058
5159STATIC void audio_buffer_ready (void ) {
5260 uint32_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION ();
53- int x = audio_output_read ;
54- audio_output_read = 0 ;
61+ audio_output_state_t old_state = audio_output_state ;
62+ audio_output_state = AUDIO_OUTPUT_STATE_DATA_READY ;
5563 MICROPY_END_ATOMIC_SECTION (atomic_state );
56- if (x == -2 ) {
64+ if (old_state == AUDIO_OUTPUT_STATE_IDLE ) {
5765 microbit_hal_audio_ready_callback ();
5866 }
5967}
6068
6169STATIC void audio_data_fetcher (void ) {
62- audio_fetecher_scheduled = false;
70+ audio_fetcher_scheduled = false;
6371 if (audio_source_iter == NULL ) {
64- microbit_audio_stop ();
6572 return ;
6673 }
6774 mp_obj_t buffer_obj ;
@@ -78,11 +85,9 @@ STATIC void audio_data_fetcher(void) {
7885 }
7986 if (buffer_obj == MP_OBJ_STOP_ITERATION ) {
8087 // End of audio iterator
81- audio_source_iter = NULL ;
8288 microbit_audio_stop ();
8389 } else if (mp_obj_get_type (buffer_obj ) != & microbit_audio_frame_type ) {
8490 // Audio iterator did not return an AudioFrame
85- audio_source_iter = NULL ;
8691 microbit_audio_stop ();
8792 mp_sched_exception (mp_obj_new_exception_msg (& mp_type_TypeError , MP_ERROR_TEXT ("not an AudioFrame" )));
8893 } else {
@@ -110,28 +115,28 @@ STATIC mp_obj_t audio_data_fetcher_wrapper(mp_obj_t arg) {
110115STATIC MP_DEFINE_CONST_FUN_OBJ_1 (audio_data_fetcher_wrapper_obj , audio_data_fetcher_wrapper );
111116
112117void microbit_hal_audio_ready_callback (void ) {
113- if (audio_output_read >= 0 ) {
118+ if (audio_output_state == AUDIO_OUTPUT_STATE_DATA_READY ) {
114119 // there is data ready to send out to the audio pipeline, so send it
115120 microbit_hal_audio_write_data (& audio_output_buffer [0 ], OUT_CHUNK_SIZE );
116- audio_output_read = -1 ;
121+ audio_output_state = AUDIO_OUTPUT_STATE_DATA_WRITTEN ;
117122 } else {
118123 // no data ready, need to call this function later when data is ready
119- audio_output_read = -2 ;
124+ audio_output_state = AUDIO_OUTPUT_STATE_IDLE ;
120125 }
121- if (!audio_fetecher_scheduled ) {
126+ if (!audio_fetcher_scheduled ) {
122127 // schedule audio_data_fetcher to be executed to prepare the next buffer
123- audio_fetecher_scheduled = mp_sched_schedule (MP_OBJ_FROM_PTR (& audio_data_fetcher_wrapper_obj ), mp_const_none );
128+ audio_fetcher_scheduled = mp_sched_schedule (MP_OBJ_FROM_PTR (& audio_data_fetcher_wrapper_obj ), mp_const_none );
124129 }
125130}
126131
127132static void audio_init (uint32_t sample_rate ) {
128- audio_fetecher_scheduled = false;
129- audio_output_read = -2 ;
133+ audio_fetcher_scheduled = false;
134+ audio_output_state = AUDIO_OUTPUT_STATE_IDLE ;
130135 microbit_hal_audio_init (BUFFER_EXPANSION * sample_rate );
131136}
132137
133138void microbit_audio_play_source (mp_obj_t src , mp_obj_t pin_select , bool wait , uint32_t sample_rate ) {
134- if (audio_running ) {
139+ if (audio_is_running () ) {
135140 microbit_audio_stop ();
136141 }
137142 audio_init (sample_rate );
@@ -185,12 +190,11 @@ void microbit_audio_play_source(mp_obj_t src, mp_obj_t pin_select, bool wait, ui
185190
186191 // Get the iterator and start the audio running.
187192 audio_source_iter = mp_getiter (src , NULL );
188- audio_running = true;
189193 audio_data_fetcher ();
190194
191195 if (wait ) {
192196 // Wait the audio to exhaust the iterator.
193- while (audio_running ) {
197+ while (audio_is_running () ) {
194198 mp_handle_pending (true);
195199 microbit_hal_idle ();
196200 }
@@ -226,7 +230,7 @@ STATIC mp_obj_t play(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
226230MP_DEFINE_CONST_FUN_OBJ_KW (microbit_audio_play_obj , 0 , play );
227231
228232bool microbit_audio_is_playing (void ) {
229- return audio_running || microbit_hal_audio_is_expression_active ();
233+ return audio_is_running () || microbit_hal_audio_is_expression_active ();
230234}
231235
232236mp_obj_t is_playing (void ) {
0 commit comments