36
36
#define BUFFER_EXPANSION (4) // smooth out the samples via linear interpolation
37
37
#define OUT_CHUNK_SIZE (BUFFER_EXPANSION * AUDIO_CHUNK_SIZE)
38
38
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
+
40
45
static 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 ;
43
48
44
49
microbit_audio_frame_obj_t * microbit_audio_frame_make_new (void );
45
50
51
+ static inline bool audio_is_running (void ) {
52
+ return audio_source_iter != NULL ;
53
+ }
54
+
46
55
void microbit_audio_stop (void ) {
47
56
audio_source_iter = NULL ;
48
- audio_running = false;
49
57
}
50
58
51
59
STATIC void audio_buffer_ready (void ) {
52
60
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 ;
55
63
MICROPY_END_ATOMIC_SECTION (atomic_state );
56
- if (x == -2 ) {
64
+ if (old_state == AUDIO_OUTPUT_STATE_IDLE ) {
57
65
microbit_hal_audio_ready_callback ();
58
66
}
59
67
}
60
68
61
69
STATIC void audio_data_fetcher (void ) {
62
- audio_fetecher_scheduled = false;
70
+ audio_fetcher_scheduled = false;
63
71
if (audio_source_iter == NULL ) {
64
- microbit_audio_stop ();
65
72
return ;
66
73
}
67
74
mp_obj_t buffer_obj ;
@@ -78,11 +85,9 @@ STATIC void audio_data_fetcher(void) {
78
85
}
79
86
if (buffer_obj == MP_OBJ_STOP_ITERATION ) {
80
87
// End of audio iterator
81
- audio_source_iter = NULL ;
82
88
microbit_audio_stop ();
83
89
} else if (mp_obj_get_type (buffer_obj ) != & microbit_audio_frame_type ) {
84
90
// Audio iterator did not return an AudioFrame
85
- audio_source_iter = NULL ;
86
91
microbit_audio_stop ();
87
92
mp_sched_exception (mp_obj_new_exception_msg (& mp_type_TypeError , MP_ERROR_TEXT ("not an AudioFrame" )));
88
93
} else {
@@ -110,28 +115,28 @@ STATIC mp_obj_t audio_data_fetcher_wrapper(mp_obj_t arg) {
110
115
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (audio_data_fetcher_wrapper_obj , audio_data_fetcher_wrapper );
111
116
112
117
void microbit_hal_audio_ready_callback (void ) {
113
- if (audio_output_read >= 0 ) {
118
+ if (audio_output_state == AUDIO_OUTPUT_STATE_DATA_READY ) {
114
119
// there is data ready to send out to the audio pipeline, so send it
115
120
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 ;
117
122
} else {
118
123
// 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 ;
120
125
}
121
- if (!audio_fetecher_scheduled ) {
126
+ if (!audio_fetcher_scheduled ) {
122
127
// 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 );
124
129
}
125
130
}
126
131
127
132
static 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 ;
130
135
microbit_hal_audio_init (BUFFER_EXPANSION * sample_rate );
131
136
}
132
137
133
138
void 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 () ) {
135
140
microbit_audio_stop ();
136
141
}
137
142
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
185
190
186
191
// Get the iterator and start the audio running.
187
192
audio_source_iter = mp_getiter (src , NULL );
188
- audio_running = true;
189
193
audio_data_fetcher ();
190
194
191
195
if (wait ) {
192
196
// Wait the audio to exhaust the iterator.
193
- while (audio_running ) {
197
+ while (audio_is_running () ) {
194
198
mp_handle_pending (true);
195
199
microbit_hal_idle ();
196
200
}
@@ -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
226
230
MP_DEFINE_CONST_FUN_OBJ_KW (microbit_audio_play_obj , 0 , play );
227
231
228
232
bool 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 ();
230
234
}
231
235
232
236
mp_obj_t is_playing (void ) {
0 commit comments