Skip to content

Commit d723177

Browse files
committed
codal_port/modaudio: Clean up audio pipeline state handling.
This commit makes the following changes which should have no change to the behaviour of the code: - rename audio_output_read to audio_output_state, and make it an enum - fix spelling of audio_fetcher_scheduled variable - remove audio_running boolean, and instead use audio_source_iter != NULL which should be equivalent - provide audio_is_running() helper function Signed-off-by: Damien George <[email protected]>
1 parent 6c51164 commit d723177

File tree

1 file changed

+26
-22
lines changed

1 file changed

+26
-22
lines changed

src/codal_port/modaudio.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,32 +36,39 @@
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+
4045
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;
4348

4449
microbit_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+
4655
void microbit_audio_stop(void) {
4756
audio_source_iter = NULL;
48-
audio_running = false;
4957
}
5058

5159
STATIC 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

6169
STATIC 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) {
110115
STATIC MP_DEFINE_CONST_FUN_OBJ_1(audio_data_fetcher_wrapper_obj, audio_data_fetcher_wrapper);
111116

112117
void 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

127132
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;
130135
microbit_hal_audio_init(BUFFER_EXPANSION * sample_rate);
131136
}
132137

133138
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()) {
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
226230
MP_DEFINE_CONST_FUN_OBJ_KW(microbit_audio_play_obj, 0, play);
227231

228232
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();
230234
}
231235

232236
mp_obj_t is_playing(void) {

0 commit comments

Comments
 (0)