Skip to content

Commit

Permalink
Playing Sounds longer than duration and Changed Block names (#78)
Browse files Browse the repository at this point in the history
* Change name of sound blocks and added functionality to play sounds longer than duration

* Updated name for hit drum block

* Addressed PR comments

* Fixed bug with playing chords
  • Loading branch information
ebiwonjumit authored Sep 4, 2024
1 parent 7c68785 commit 972f9bc
Showing 1 changed file with 33 additions and 13 deletions.
46 changes: 33 additions & 13 deletions extensions/BeatBlox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@
*/
async function playChord(trackName, notes, startTime, noteDuration, mod = undefined) {
if (notes.length === 0) return 0;

let ret = Infinity;
for (const note of notes) {
ret = Math.min(ret, await audioAPI.playNote(trackName, note, startTime, noteDuration, mod));
Expand Down Expand Up @@ -556,6 +555,24 @@
await waitUntil(this.musicInfo.t - SCHEDULING_WINDOW);

}
async function playClipForDuration(trackName,clip, duration){
const clipDuration = await getAudioObjectDuration(clip.audio);
if(duration > clipDuration) {
let remainingDuration = duration;
while (remainingDuration > 0){
const playingDuration = Math.min(remainingDuration, clipDuration);
const t = await playClip(trackName, clip, this.musicInfo.t, playingDuration);
this.musicInfo.t += t;
await waitUntil(this.musicInfo.t - SCHEDULING_WINDOW);
remainingDuration -= playingDuration;
}
}
else{
const t = await playClip(trackName, clip, this.musicInfo.t, duration);
this.musicInfo.t += t;
await waitUntil(this.musicInfo.t - SCHEDULING_WINDOW);
}
}
return [
new Extension.Block('setInstrument', 'command', 'music', 'set instrument %webMidiInstrument', ['Synthesizer'], function (instrument) {
if (instrument === '') throw Error(`instrument cannot be empty`);
Expand All @@ -566,8 +583,12 @@
}, { args: [], timeout: I32_MAX });
}),
new Extension.Block('playNote', 'command', 'music', 'play note(s) %s %noteDurations %noteDurationsSpecial ', [ 'C3','Quarter',''], function (notes,duration, durationSpecial) {
if(typeof notes === 'object'){
if (notes instanceof List){
playNoteCommon.apply(this, [durationSpecial + duration, notes]);
}
else if(typeof notes === 'object'){
var noteName = notes.noteName;
console.log(notes);
var modifier = notes.modifier;
playNoteCommon.apply(this, [durationSpecial + duration, noteName, audioAPI.getModification(modifier,1)]);
}
Expand All @@ -582,7 +603,7 @@
playNoteCommon.apply(this, [trackName,durationSpecial + duration, 'Rest']); // internally does await instrumentPrefetch
}, { args: [], timeout: I32_MAX });
}),
new Extension.Block('playAudioClip', 'command', 'music', 'play sound %snd', [null], function (clip) {
new Extension.Block('playAudioClip', 'command', 'music', 'play clip %snd', [null], function (clip) {
setupProcess(this);
if (clip === '') throw Error(`sound cannot be empty`);
if (this.receiver.sounds.contents.length) {
Expand Down Expand Up @@ -612,9 +633,10 @@
await waitUntil(this.musicInfo.t - SCHEDULING_WINDOW);
}, { args: [], timeout: I32_MAX });
}),
new Extension.Block('playAudioClipForDuration', 'command', 'music', 'play sound %snd for duration %n secs', [null, 0], function (clip, duration) {
new Extension.Block('playAudioClipForDuration', 'command', 'music', 'play clip %snd for duration %n secs', [null, 0], function (clip, duration) {
setupProcess(this);
if (clip === '') throw Error(`sound cannot be empty`);
if (duration <= 0) throw Error(`duration must be greater than 0`);
if (this.receiver.sounds.contents.length) {
for (let i = 0; i < this.receiver.sounds.contents.length; i++) {
if (clip === this.receiver.sounds.contents[i].name) {
Expand All @@ -627,12 +649,11 @@
this.runAsyncFn(async () => {
await instrumentPrefetch; // wait for all instruments to be loaded
const trackName = this.receiver.id;
const t = await playClip(trackName, clip, this.musicInfo.t, duration);
this.musicInfo.t += t;
await waitUntil(this.musicInfo.t - SCHEDULING_WINDOW);
await playClipForDuration.apply(this,[trackName,clip,duration]);

}, { args: [], timeout: I32_MAX });
}),
new Extension.Block('playSampleForDuration', 'command', 'music', 'play sound %snd for duration %noteDurations %noteDurationsSpecial', [null, 'Quarter', ''], function (clip, duration, durationSpecial) {
new Extension.Block('playSampleForDuration', 'command', 'music', 'play clip %snd for duration %noteDurations %noteDurationsSpecial', [null, 'Quarter', ''], function (clip, duration, durationSpecial) {
setupProcess(this);
let playDuration = availableNoteDurations[duration];
if (durationSpecial != '') {
Expand All @@ -650,17 +671,16 @@
this.runAsyncFn(async () => {
await instrumentPrefetch; // wait for all instruments to be loaded
const trackName = this.receiver.id;
const clipDuration = audioAPI.convertNoteDurationToSeconds(playDuration);
const t = await playClip(trackName, clip, this.musicInfo.t, clipDuration);
this.musicInfo.t += t;
await waitUntil(this.musicInfo.t - SCHEDULING_WINDOW);
const durationInSecs = audioAPI.convertNoteDurationToSeconds(playDuration);
await playClipForDuration.apply(this,[trackName,clip,durationInSecs]);

}, { args: [], timeout: I32_MAX });
}),
new Extension.Block('stopAudio', 'command', 'music', 'stop all audio', [], function () {
stopAudio();
this.doStopAll();
}),
new Extension.Block('hitDrumsOverDuration','command','music','hit over %noteDurations drum sequence %mult%drums',['Quarter', ['Kick']], function(duration,drum){
new Extension.Block('hitDrumsOverDuration','command','music','for %noteDurations drum sequence %mult%drums',['Quarter', ['Kick']], function(duration,drum){
setupProcess(this);
if (drum.contents.length === 0) throw Error(`drum cannot be empty`);
if(duration == '') throw Error(`duration cannot be empty`);
Expand Down

0 comments on commit 972f9bc

Please sign in to comment.