From da94257a818be35d75e3f41b62db1b72487aba85 Mon Sep 17 00:00:00 2001 From: Zachary Gramana Date: Mon, 16 Sep 2019 10:57:58 -0700 Subject: [PATCH] Adds AudioOut version of the piu/Sound example Demonstrates some advanced capabilities of the AudioOut class, as well as how to accomplish the same tasks as done with the Sound class. In addition, reproduces a device lockup issue when stopping an audio playback stream by enqueuing `Flush`. --- examples/piu/audioout/main.js | 194 ++++++++++++++++++++++++++ examples/piu/audioout/manifest.json | 53 +++++++ examples/piu/audioout/play.png | Bin 0 -> 22324 bytes examples/piu/audioout/volume-down.png | Bin 0 -> 10530 bytes examples/piu/audioout/volume-up.png | Bin 0 -> 11446 bytes 5 files changed, 247 insertions(+) create mode 100644 examples/piu/audioout/main.js create mode 100644 examples/piu/audioout/manifest.json create mode 100644 examples/piu/audioout/play.png create mode 100644 examples/piu/audioout/volume-down.png create mode 100644 examples/piu/audioout/volume-up.png diff --git a/examples/piu/audioout/main.js b/examples/piu/audioout/main.js new file mode 100644 index 0000000000..46c19310aa --- /dev/null +++ b/examples/piu/audioout/main.js @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2019 Moddable Tech, Inc. + * + * This file is part of the Moddable SDK. + * + * This work is licensed under the + * Creative Commons Attribution 4.0 International License. + * To view a copy of this license, visit + * . + * or send a letter to Creative Commons, PO Box 1866, + * Mountain View, CA 94042, USA. + * + */ + +import {} from "piu/MC"; +import AudioOut from "pins/audioout" +import Sound from "piu/Sound"; // To easily get the sound setings from the manifest +import Resource from "Resource"; + +const WHITE = "white"; + +const backgroundSkin = new Skin({ fill: WHITE }); +const buttonSkin = new Skin({ fill: ["#0033cc", "#668cff"] }); +const volumeBarSkin = new Skin({ fill: ["#efefef", "#202020"] }); + +const volumeDownTexture = new Texture({ path: "volume-down.png" }); +const volumeDownSkin = new Skin({ + texture: volumeDownTexture, color: WHITE, + height: 40, width: 40 +}); + +const volumeUpTexture = new Texture({ path: "volume-up.png" }); +const volumeUpSkin = new Skin({ + texture: volumeUpTexture, color: WHITE, + height: 55, width: 55 +}); + +const playTexture = new Texture({ path: "play.png" }); +const playSkin = new Skin({ + texture: playTexture, color: WHITE, + height: 55, width: 55 +}); + +class ButtonBehavior extends Behavior { + onCreate(button, data) { + this.data = data; + } + onTouchBegan(button) { + button.state = 1; + } + onTouchEnded(button) { + button.state = 0; + } +} + +class SoundAppBehavior extends Behavior { + onCreate(application, data) { + this.data = data; + this.soundVolume = 0.5; + this.audio = new AudioOut({ + bitsPerSample: Sound.bitsPerSample, + numChannels: Sound.numChannels, + sampleRate: Sound.sampleRate, + streams: 1 + }); + this.audio.callback = (newState) => { + trace('...done\n'); + application.state = newState; + }; + this.audio.start(); + } + onDisplaying(application) { + let data = this.data; + if (undefined !== global.button) { // M5Stack + let button = global.button; + button.a.onChanged = function() { + if (this.read()) { + application.delegate("volumeDown"); + } + } + button.b.onChanged = function() { + if (this.read()) { + application.delegate("volumeUp"); + } + } + button.c.onChanged = function() { + if (this.read()) { + application.delegate("toggleSound"); + } + } + } + } + setVolume(vol) { + this.audio.enqueue(0, AudioOut.Volume, (255 * vol)); + this.data["VOLUME"].delegate("onVolumeChanged", vol); + } + volumeDown(application) { + if (this.soundVolume >= 0.1) { + this.soundVolume -= 0.1; + } else { + this.soundVolume = 0; + } + this.setVolume(this.soundVolume); + } + volumeUp(application) { + if (this.soundVolume < 1) { + this.soundVolume += 0.1; + this.data["VOLUME"].delegate("onVolumeChanged", this.soundVolume); + } + this.setVolume(this.soundVolume); + } + toggleSound(application, shouldPlay) { + if (shouldPlay) + { + trace('=> Playing sound'); + this.audio.enqueue(0, AudioOut.Flush); + this.audio.enqueue(0, AudioOut.Samples, this.data.sound); + this.audio.enqueue(0, AudioOut.Callback, false); + } else { + trace('=> Stopping sound playback!\n'); + this.audio.enqueue(0, AudioOut.Flush); + } + } +} + +const VolumeBar = Content.template($ => ({ + top: 0, bottom: 0, left: 0, right: 3, skin: volumeBarSkin +})); + +const SoundApp = Application.template($ => ({ + skin: backgroundSkin, + contents: [ + Row($, { + anchor: "VOLUME", top: 10, height: 50, left: 20, right: 23, + contents: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(item => new VolumeBar($, { state: (item < 5)? 1 : 0 })), + Behavior: class extends Behavior { + onCreate(row, data) { + this.data = data; + } + onVolumeChanged(row, volume) { + if (volume) { + volume *= 10; + volume = Math.round(volume) - 1; + row.content(volume).state = 1; + if (row.content(volume).next) row.content(volume).next.state = 0; + } else { + row.first.state = 0; + } + } + } + }), + Container($, { + active: true, height: 70, bottom: 0, left: 28, width: 70, skin: buttonSkin, + contents: [ + Content($, { skin: volumeDownSkin }) + ], + Behavior: class extends ButtonBehavior { + onTouchEnded(button) { + super.onTouchEnded(button); + application.delegate("volumeDown"); + } + } + }), + Container($, { + active: true, height: 70, bottom: 0, left: 125, width: 70, skin: buttonSkin, + contents: [ + Content($, { skin: volumeUpSkin }) + ], + Behavior: class extends ButtonBehavior { + onTouchEnded(button) { + super.onTouchEnded(button); + application.delegate("volumeUp"); + } + } + }), + Container($, { + active: true, height: 70, bottom: 0, right: 28, width: 70, skin: buttonSkin, + contents: [ + Content($, { skin: playSkin }) + ], + Behavior: class extends ButtonBehavior { + onTouchEnded(button) { + super.onTouchEnded(button); + application.state = !application.state; + application.delegate("toggleSound", application.state); + } + } + }), + ], + Behavior: SoundAppBehavior +})); + +export default new SoundApp({ sound: new Resource("bflatmajor.maud")}, { displayListLength: 1024, touchCount: 1 }); + diff --git a/examples/piu/audioout/manifest.json b/examples/piu/audioout/manifest.json new file mode 100644 index 0000000000..c4b8714a4c --- /dev/null +++ b/examples/piu/audioout/manifest.json @@ -0,0 +1,53 @@ +{ + "include": [ + "$(MODDABLE)/examples/manifest_base.json", + "$(MODDABLE)/examples/manifest_piu.json", + ], + "config": { + "rotation": 90, + "autorotate": false, + }, + "modules": { + "*": [ + "./main" + ], + "pins/*": [ + "$(MODULES)/pins/i2s/*" + ], + "piu/Sound": [ + "$(MODULES)/piu/MC/piuSound" + ] + }, + "resources": { + "*": "$(MODDABLE)/examples/assets/sounds/bflatmajor", + "*-mask": [ + "./volume-down", + "./volume-up", + "./play" + ] + }, + "platforms": { + "esp32/m5stack_fire": {}, + "esp32/moddable_two": { + "defines": { + "audioOut": { + "bitsPerSample": 16, + "numChannels": 1, + "sampleRate": 32000, + "format": "ima", + "streams": 1, + "queueLength": 4, + "i2s": { + "dac": 1 + } + } + }, + }, + "mac": {}, + "win": {}, + "...": { + "error": "Platform not supported" + }, + } +} + diff --git a/examples/piu/audioout/play.png b/examples/piu/audioout/play.png new file mode 100644 index 0000000000000000000000000000000000000000..adffd2e73b79991d8996c281185ecab8cb3677cb GIT binary patch literal 22324 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 literal 0 HcmV?d00001 diff --git a/examples/piu/audioout/volume-down.png b/examples/piu/audioout/volume-down.png new file mode 100644 index 0000000000000000000000000000000000000000..c51e172a2ff34aff242c765e3cbc472f23b5493e GIT binary patch literal 10530 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 literal 0 HcmV?d00001 diff --git a/examples/piu/audioout/volume-up.png b/examples/piu/audioout/volume-up.png new file mode 100644 index 0000000000000000000000000000000000000000..dee974445353f26af10ed697ed30709fce119f4a GIT binary patch literal 11446 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 WyW&a=G>kvK>64RImMWDn4f-EW(o~B8 literal 0 HcmV?d00001