Skip to content

Commit 18b23e4

Browse files
committed
Introduce sound playback "until playback complete" option (#231)
- Add new event raised when a synthesized sound completes rendering on the speaker - Update SoundExpressions::play() functions to allow the use of this new event as an optional terminating condition - Fix output inversion bug in MicroBitAudio::isPlaying()
1 parent be855ae commit 18b23e4

File tree

5 files changed

+33
-10
lines changed

5 files changed

+33
-10
lines changed

inc/SoundEmojiSynthesizer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ DEALINGS IN THE SOFTWARE.
2727

2828
#include "DataStream.h"
2929

30+
#ifndef CONFIG_EMOJI_SYNTHESIZER_OUTPUT_BUFFER_DEPTH
31+
#define CONFIG_EMOJI_SYNTHESIZER_OUTPUT_BUFFER_DEPTH 3
32+
#endif
33+
3034
#define EMOJI_SYNTHESIZER_SAMPLE_RATE 44100
3135
#define EMOJI_SYNTHESIZER_TONE_WIDTH 1024
3236
#define EMOJI_SYNTHESIZER_TONE_WIDTH_F 1024.0f
@@ -55,6 +59,8 @@ DEALINGS IN THE SOFTWARE.
5559
#define DEVICE_ID_SOUND_EMOJI_SYNTHESIZER_9 3019
5660

5761
#define DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_DONE 1
62+
#define DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_PLAYBACK_COMPLETE 2
63+
5864

5965
namespace codal
6066
{
@@ -124,6 +130,7 @@ namespace codal
124130
float sampleRange; // The maximum sample value that can be output.
125131
uint16_t orMask; // A bitmask that is logically OR'd with each output sample.
126132
int bufferSize; // The number of samples to create in a single buffer before scheduling it for playback
133+
int playbackCompleteIn; // The number of DMA buffers to generate befor next issuing a DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_PLAYBACK_COMPLETE event
127134

128135
float frequency; // The instantaneous frequency currently being generated within an effect.
129136
float volume; // The instantaneous volume currently being generated within an effect.

inc/SoundExpressions.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,26 @@ namespace codal
4848

4949
/**
5050
* Plays a sound encoded as a series of decimal encoded effects or specified by name.
51-
* Blocks until the sound is complete.
51+
* Blocks until the sound generation is complete, and the synthesizer is ready to accept new requests.
52+
* @param sound a string representing the sound effect to play, in the form descripbed by parseSoundExperession().
53+
* @param event the event to wait for - either DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_DONE (default) or DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_PLAYBACK_COMPLETE.
5254
*/
53-
void play(ManagedString sound);
55+
void play(ManagedString sound, uint16_t event = DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_DONE);
5456

5557
/**
5658
* Plays a sound encoded as a series of decimal encoded effects or specified by name.
5759
* Does not block.
60+
* @param a string representing the sound effect to play, in the form descripbed by parseSoundExperession().
5861
*/
5962
void playAsync(ManagedString sound);
6063

6164
/**
62-
* Plays a sound encoded as an array of one or more SoundEffect structures.
63-
* Blocks until the sound is complete.
65+
* Plays a sound encoded as a series of decimal encoded effects or specified by name.
66+
* Blocks until the sound generation is complete, and the synthesizer is ready to accept new requests.
67+
* @param sound a string representing the sound effect to play, in the form descripbed by parseSoundExperession().
68+
* @param event the event to wait for - either DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_DONE (default) or DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_PLAYBACK_COMPLETE.
6469
*/
65-
void play(ManagedBuffer sound);
70+
void play(ManagedBuffer sound, uint16_t event = DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_DONE);
6671

6772
/**
6873
* Plays a sound encoded as an array of one or more SoundEffect structures.

source/MicroBitAudio.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,5 +330,5 @@ bool MicroBitAudio::isPlaying()
330330
uint32_t start = mixer.getSilenceStartTime();
331331
uint32_t end = mixer.getSilenceEndTime();
332332

333-
return ((start && t >= (start + CONFIG_AUDIO_MIXER_OUTPUT_LATENCY_US)) && (end == 0 || t < (end + CONFIG_AUDIO_MIXER_OUTPUT_LATENCY_US - 100)));
333+
return !((start && t >= (start + CONFIG_AUDIO_MIXER_OUTPUT_LATENCY_US)) && (end == 0 || t < (end + CONFIG_AUDIO_MIXER_OUTPUT_LATENCY_US - 100)));
334334
}

source/SoundEmojiSynthesizer.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ SoundEmojiSynthesizer::SoundEmojiSynthesizer(uint16_t id, int sampleRate) : Coda
4242
this->position = 0.0f;
4343
this->effect = NULL;
4444
this->partialBuffer = NULL;
45+
this->playbackCompleteIn = 0;
4546
this->buffer2 = ManagedBuffer(bufferSize);
4647

4748
this->samplesToWrite = 0;
@@ -205,6 +206,15 @@ ManagedBuffer SoundEmojiSynthesizer::pull()
205206
// Issue a Pull Request so that we are always receiver driven, and we're done.
206207
downStream->pullRequest();
207208

209+
// Issue a deferred DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_PLAYBACK_COMPLETE event if requested.
210+
if (playbackCompleteIn > 0)
211+
{
212+
playbackCompleteIn--;
213+
214+
if (playbackCompleteIn == 0)
215+
Event(id, DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_PLAYBACK_COMPLETE);
216+
}
217+
208218
return output;
209219
}
210220

@@ -237,6 +247,7 @@ ManagedBuffer SoundEmojiSynthesizer::fillOutputBuffer()
237247

238248
// Flip our status bit and fire the event
239249
status &= ~EMOJI_SYNTHESIZER_STATUS_STOPPING;
250+
playbackCompleteIn = CONFIG_EMOJI_SYNTHESIZER_OUTPUT_BUFFER_DEPTH+2;
240251
Event(id, DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_DONE);
241252
lock.notify();
242253
}

source/SoundExpressions.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ SoundExpressions::~SoundExpressions()
5353
* Plays a sound encoded as an array of one or more SoundEffect structures.
5454
* Blocks until the sound is complete.
5555
*/
56-
void SoundExpressions::play(ManagedBuffer sound)
56+
void SoundExpressions::play(ManagedBuffer sound, uint16_t event)
5757
{
58-
fiber_wake_on_event(synth.id, DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_DONE);
58+
fiber_wake_on_event(synth.id, event);
5959
playAsync(sound);
6060
schedule();
6161
}
@@ -69,8 +69,8 @@ void SoundExpressions::playAsync(ManagedBuffer sound)
6969
synth.play(sound);
7070
}
7171

72-
void SoundExpressions::play(ManagedString sound) {
73-
fiber_wake_on_event(synth.id, DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_DONE);
72+
void SoundExpressions::play(ManagedString sound, uint16_t event) {
73+
fiber_wake_on_event(synth.id, event);
7474
playAsync(sound);
7575
schedule();
7676
}

0 commit comments

Comments
 (0)