pxt-common-packages
Version:
Microsoft MakeCode (PXT) common packages
129 lines (106 loc) • 3.98 kB
text/typescript
namespace pxsim.music {
export function playInstructions(b: RefBuffer) {
setupOnStopAll();
return AudioContextManager.playInstructionsAsync(b.data)
}
export function queuePlayInstructions(when: number, b: RefBuffer) {
setupOnStopAll();
AudioContextManager.queuePlayInstructions(when, b)
}
export function stopPlaying() {
AudioContextManager.muteAllChannels()
if (sequencers) {
for (const seq of sequencers) {
seq.sequencer.stop();
seq.sequencer.dispose();
}
}
}
export function forceOutput(mode: number) { }
export const SEQUENCER_STOP_MESSAGE = 3243;
export const SEQUENCER_TICK_MESSAGE = 3244;
export const SEQUENCER_STATE_CHANGE_MESSAGE = 3245;
export const SEQUENCER_LOOPED_MESSAGE = 3246;
interface SequencerWithId {
id: number;
sequencer: Sequencer;
}
let sequencers: SequencerWithId[];
let nextSequencerId = 0;
let onStopAllSetup = false;
function setupOnStopAll() {
if (!onStopAllSetup) {
onStopAllSetup = true;
pxsim.AudioContextManager.onStopAll(() => {
AudioContextManager.muteAllChannels();
if (sequencers) {
for (const seq of sequencers) {
seq.sequencer.stop();
seq.sequencer.dispose();
}
sequencers = [];
}
})
}
}
export async function _createSequencer(): Promise<number> {
setupOnStopAll();
if (!sequencers) {
sequencers = [];
}
const res = {
id: nextSequencerId++,
sequencer: new Sequencer()
};
sequencers.push(res)
await res.sequencer.initAsync();
res.sequencer.addEventListener("stop", () => {
board().bus.queue(SEQUENCER_STOP_MESSAGE, res.id);
});
res.sequencer.addEventListener("state-change", () => {
board().bus.queue(SEQUENCER_STATE_CHANGE_MESSAGE, res.id);
});
res.sequencer.addEventListener("looped", () => {
board().bus.queue(SEQUENCER_LOOPED_MESSAGE, res.id);
});
res.sequencer.addEventListener("tick", () => {
board().bus.queue(SEQUENCER_TICK_MESSAGE, res.id);
});
return res.id;
}
export function _sequencerState(id: number): string {
return lookupSequencer(id)?.state();
}
export function _sequencerCurrentTick(id: number): number {
return lookupSequencer(id)?.currentTick();
}
export function _sequencerPlaySong(id: number, song: RefBuffer, loop: boolean): void {
const decoded = decodeSong(song.data);
lookupSequencer(id)?.start(decoded, loop);
}
export function _sequencerStop(id: number): void {
lookupSequencer(id)?.stop();
}
export function _sequencerSetVolume(id: number, volume: number): void {
lookupSequencer(id)?.setVolume(volume);
}
export function _sequencerSetVolumeForAll(volume: number): void {
for (const seq of sequencers) {
seq.sequencer.setVolume(volume);
}
}
export function _sequencerSetTrackVolume(id: number, trackIndex: number, volume: number): void {
lookupSequencer(id)?.setTrackVolume(trackIndex, volume);
}
export function _sequencerSetDrumTrackVolume(id: number, trackIndex: number, drumIndex: number, volume: number): void {
lookupSequencer(id)?.setDrumTrackVolume(trackIndex, drumIndex, volume);
}
export function _sequencerDispose(id: number) {
lookupSequencer(id)?.dispose();
sequencers = sequencers.filter(s => s.id !== id);
}
function lookupSequencer(id: number) {
for (const seq of sequencers) if (seq.id === id) return seq.sequencer;
return undefined;
}
}