From e25590539edf971fe104c4ee1ac742c8dbcd2473 Mon Sep 17 00:00:00 2001 From: Michal Moskal Date: Mon, 30 Oct 2017 18:55:23 +0000 Subject: [PATCH] Add sample-playing code --- libs/music/_locales/music-jsdoc-strings.json | 2 +- libs/music/music.cpp | 89 ++++++++++++++++++-- libs/music/shims.d.ts | 4 +- 3 files changed, 85 insertions(+), 10 deletions(-) diff --git a/libs/music/_locales/music-jsdoc-strings.json b/libs/music/_locales/music-jsdoc-strings.json index bdfe21f6..872a8255 100644 --- a/libs/music/_locales/music-jsdoc-strings.json +++ b/libs/music/_locales/music-jsdoc-strings.json @@ -1,6 +1,6 @@ { "Sound.buffer": "Returns the underlaying Buffer object.", - "Sound.play": "Play sound with given volume.", + "Sound.play": "Play sound.", "music": "Generation of music tones.", "music.beat": "Return the duration of a beat in milliseconds (the beat fraction).", "music.beat|param|fraction": "the fraction of the current whole note, eg: BeatFraction.Half", diff --git a/libs/music/music.cpp b/libs/music/music.cpp index cae81c50..613face8 100644 --- a/libs/music/music.cpp +++ b/libs/music/music.cpp @@ -5,17 +5,24 @@ #include #include #include +#include +#include +#include + #define NOTE_PAUSE 20 namespace music { uint8_t currVolume = 2; +uint8_t *lmsSoundMMap; -void writeDev(void *data, int size) { +int writeDev(void *data, int size) { + DMESG("write dev %d", size); int fd = open("/dev/lms_sound", O_WRONLY); - write(fd, data, size); + int res = write(fd, data, size); close(fd); + return res; } /** @@ -60,6 +67,76 @@ static void _playTone(uint16_t frequency, uint16_t duration, uint8_t volume) { writeDev(&cmd, sizeof(cmd)); } +static bool pumpMusicThreadRunning; +static pthread_mutex_t pumpMutex; +static Buffer currentSample; +static int samplePtr; +static pthread_cond_t sampleDone; + +static void pumpMusic() { + if (currentSample == NULL) { + if (samplePtr > 0 && *lmsSoundMMap == 0) { + samplePtr = 0; + DMESG("END"); + pthread_cond_broadcast(&sampleDone); + } + return; + } + + uint8_t buf[250]; // max size supported by hardware + buf[0] = SOUND_CMD_SERVICE; + int len = min((int)sizeof(buf) - 1, currentSample->length - samplePtr); + if (len == 0) { + DMESG("EOF"); + decrRC(currentSample); + currentSample = NULL; + return; + } + + memcpy(buf + 1, currentSample->data + samplePtr, len); + int rc = writeDev(buf, len + 1); + if (rc > 0) { + samplePtr += len; + } +} + +static void *pumpMusicThread(void *dummy) { + while (true) { + sleep_core_us(10000); + pthread_mutex_lock(&pumpMutex); + pumpMusic(); + pthread_mutex_unlock(&pumpMutex); + } +} + +void playSample(Buffer buf) { + if (lmsSoundMMap == NULL) { + int fd = open("/dev/lms_sound", O_RDWR); + lmsSoundMMap = (uint8_t*) mmap(NULL, 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + DMESG("sound map: %p", lmsSoundMMap); + close(fd); + } + + if (!pumpMusicThreadRunning) { + pumpMusicThreadRunning = true; + pthread_t pid; + pthread_create(&pid, NULL, pumpMusicThread, NULL); + pthread_detach(pid); + } + + pthread_mutex_lock(&pumpMutex); + *lmsSoundMMap = 1; // BUSY + uint8_t cmd[] = {SOUND_CMD_PLAY, (uint8_t)((currVolume / 33) + 1)}; + writeDev(cmd, 2); + decrRC(currentSample); + currentSample = buf; + incrRC(buf); + samplePtr = 44; // WAV header is 44 bytes + pumpMusic(); + pthread_cond_wait(&sampleDone, &pumpMutex); + pthread_mutex_unlock(&pumpMutex); +} + /** * Play a tone through the speaker for some amount of time. * @param frequency pitch of the tone to play in Hertz (Hz) @@ -89,14 +166,12 @@ void playTone(int frequency, int ms) { sleep_ms(1); } - /** Makes a sound bound to a buffer in WAV format. */ //% Sound fromWAV(Buffer buf) { incrRC(buf); return buf; } - } //% fixedInstances @@ -109,10 +184,10 @@ Buffer buffer(Sound snd) { return snd; } -/** Play sound with given volume. */ +/** Play sound. */ //% promise -void play(Sound snd, int volume) { - // TODO +void play(Sound snd) { + music::playSample(snd); } } \ No newline at end of file diff --git a/libs/music/shims.d.ts b/libs/music/shims.d.ts index 4cfdc542..cb3e2a62 100644 --- a/libs/music/shims.d.ts +++ b/libs/music/shims.d.ts @@ -38,9 +38,9 @@ declare interface Sound { //% property shim=SoundMethods::buffer buffer: Buffer; - /** Play sound with given volume. */ + /** Play sound. */ //% promise shim=SoundMethods::play - play(volume: int32): void; + play(): void; } // Auto-generated. Do not edit. Really.