Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/modules/bjs_interpreter/audio_js.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#if !defined(LITE_VERSION) && !defined(DISABLE_INTERPRETER)
#include "audio_js.h"

#include "modules/others/audio.h"

JSValue native_playAudioFile(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv) {
if (argc < 1) { return JS_NewBool(false); }

Expand All @@ -18,14 +20,15 @@ JSValue native_tone(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv)

uint32_t freq = 500;
uint32_t duration = 1000;
int nonBlocking = false;
bool nonBlocking = false;

if (argc > 0) { JS_ToUint32(ctx, &freq, argv[0]); }
if (argc > 1) { JS_ToUint32(ctx, &duration, argv[1]); }
if (argc > 2) { nonBlocking = JS_ToInt32(ctx, &nonBlocking, argv[2]); }
if (argc > 2) { nonBlocking = JS_ToBool(ctx, argv[2]); }

#if defined(HAS_SPEAKER)
if (!nonBlocking) { serialCli.parse("tone " + String(freq) + " " + String(duration)); }
if (nonBlocking) _tone(freq, duration, PLAYBACK_ASYNC);
else serialCli.parse("tone " + String(freq) + " " + String(duration));
#else
if (bruceConfigPins.buzzer > 0) tone((uint8_t)bruceConfigPins.buzzer, freq, duration);
#endif
Expand Down
24 changes: 18 additions & 6 deletions src/modules/others/audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -659,13 +659,16 @@ bool isAudioFile(const String &filepath) {
filepath.endsWith(".aac") || filepath.endsWith(".flac");
}

void playTone(unsigned int frequency, unsigned long duration, short waveType) {
void playTone(unsigned int frequency, unsigned long duration, short waveType, PlaybackMode mode) {
if (!bruceConfig.soundEnabled) return;

// Stop any current playback
if (isAudioPlaying()) { stopAudioPlayback(); }

_setup_codec_speaker(true);

if (frequency == 0 || duration == 0) {
if (frequency == 0 && duration > 0) { delay(duration); }
if (frequency == 0 && duration > 0 && mode == PLAYBACK_BLOCKING) { delay(duration); }
_setup_codec_speaker(false);
return;
}
Expand Down Expand Up @@ -719,6 +722,14 @@ void playTone(unsigned int frequency, unsigned long duration, short waveType) {
return;
}

// === ASYNC MODE ===
// The playback task does not watch the keys, so a key press during the tone
// stays for the caller instead of being consumed to cut the tone short.
if (mode == PLAYBACK_ASYNC) {
startAsyncPlayback(wav, file, out, "tone");
return;
}

while (wav->isRunning()) {
if (!wav->loop() || check(AnyKeyPress)) { wav->stop(); }
vTaskDelay(pdMS_TO_TICKS(1));
Expand Down Expand Up @@ -812,23 +823,24 @@ static void cardputerTone(unsigned int frequency, unsigned long duration) {
}
#endif

void _tone(unsigned int frequency, unsigned long duration) {
void _tone(unsigned int frequency, unsigned long duration, PlaybackMode mode) {
if (!bruceConfig.soundEnabled) return;

#if defined(HAS_SPEAKER)
#if defined(ARDUINO_M5STACK_CARDPUTER)
// No async path here: cardputerTone() writes the samples itself
cardputerTone(frequency, duration);
#elif __has_include(<M5Unified.h>)
if (frequency == 0) {
if (duration > 0) delay(duration);
if (duration > 0 && mode == PLAYBACK_BLOCKING) delay(duration);
} else {
uint8_t m5vol = (bruceConfig.soundVolume * 255) / AUDIO_VOLUME_MAX;
M5.Speaker.setVolume(m5vol);
M5.Speaker.tone(frequency, duration);
if (duration > 0) delay(duration);
if (duration > 0 && mode == PLAYBACK_BLOCKING) delay(duration);
}
#else
playTone(frequency, duration, 0);
playTone(frequency, duration, 0, mode);
#endif
#else
// No I2S speaker: fall back to the buzzer, which stays silent until a pin is configured.
Expand Down
7 changes: 5 additions & 2 deletions src/modules/others/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ bool playAudioFile(FS *fs, String filepath, PlaybackMode mode = PLAYBACK_BLOCKIN
bool playAudioRTTTLString(String song, PlaybackMode mode = PLAYBACK_BLOCKING);
bool tts(String text, PlaybackMode mode = PLAYBACK_BLOCKING);
bool isAudioFile(const String &filePath);
void playTone(unsigned int frequency, unsigned long duration = 0UL, short waveType = 0);
void _tone(unsigned int frequency, unsigned long duration = 0UL);
void playTone(
unsigned int frequency, unsigned long duration = 0UL, short waveType = 0,
PlaybackMode mode = PLAYBACK_BLOCKING
);
void _tone(unsigned int frequency, unsigned long duration = 0UL, PlaybackMode mode = PLAYBACK_BLOCKING);

// NEW: Async playback control API
bool stopAudioPlayback(); // Stop current playback
Expand Down