Skip to content

Commit

Permalink
Merge pull request #49 from dxinteractive/feature/pos-and-perf
Browse files Browse the repository at this point in the history
Feature/pos and perf
  • Loading branch information
dxinteractive authored Jul 10, 2021
2 parents 7ae87ad + 465bd19 commit d0d3bd7
Show file tree
Hide file tree
Showing 17 changed files with 993 additions and 364 deletions.
60 changes: 40 additions & 20 deletions packages/mosc/src/__tests__/mosc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ describe('sortByTime', () => {
type: 'NOTE_TIME',
time: 2,
timeEnd: 2,
hz: 440
hz: 440,
label: '440'
},
{
type: 'NOTE_TIME',
time: 0,
timeEnd: 2,
hz: 550
hz: 550,
label: '550'
},
{
type: 'TEMPO',
Expand All @@ -50,7 +52,8 @@ describe('sortByTime', () => {
type: 'NOTE_TIME',
time: 0,
timeEnd: 2,
hz: 550
hz: 550,
label: '550'
},
{
type: 'TEMPO',
Expand All @@ -62,7 +65,8 @@ describe('sortByTime', () => {
type: 'NOTE_TIME',
time: 2,
timeEnd: 2,
hz: 440
hz: 440,
label: '440'
}
]);
});
Expand All @@ -83,13 +87,15 @@ describe('scoreToMs', () => {
type: 'NOTE_TIME',
time: 0,
timeEnd: 1,
hz: 440
hz: 440,
label: '440'
},
{
type: 'NOTE_TIME',
time: 1,
timeEnd: 2,
hz: 550
hz: 550,
label: '550'
},
{
type: 'TEMPO',
Expand All @@ -101,7 +107,8 @@ describe('scoreToMs', () => {
type: 'NOTE_TIME',
time: 2,
timeEnd: 3,
hz: 660
hz: 660,
label: '660'
},
{
type: 'PARAM_TIME',
Expand All @@ -122,19 +129,22 @@ describe('scoreToMs', () => {
type: 'NOTE_MS',
ms: 0,
msEnd: 500,
hz: 440
hz: 440,
label: '440'
},
{
type: 'NOTE_MS',
ms: 500,
msEnd: 1000,
hz: 550
hz: 550,
label: '550'
},
{
type: 'NOTE_MS',
ms: 1000,
msEnd: 1666.6666666666665,
hz: 660
hz: 660,
label: '660'
},
{
type: 'PARAM_MS',
Expand Down Expand Up @@ -171,31 +181,36 @@ describe('scoreToMs', () => {
type: 'NOTE_TIME',
time: 1,
timeEnd: 1,
hz: 440
hz: 440,
label: '440'
},
{
type: 'NOTE_TIME',
time: 2,
timeEnd: 2,
hz: 550
hz: 550,
label: '550'
},
{
type: 'NOTE_TIME',
time: 3,
timeEnd: 3,
hz: 660
hz: 660,
label: '660'
},
{
type: 'NOTE_TIME',
time: 4,
timeEnd: 4,
hz: 770
hz: 770,
label: '770'
},
{
type: 'NOTE_TIME',
time: 5,
timeEnd: 5,
hz: 880
hz: 880,
label: '880'
}
],
lengthTime: 5
Expand All @@ -205,31 +220,36 @@ describe('scoreToMs', () => {
type: 'NOTE_MS',
ms: 500,
msEnd: 500,
hz: 440
hz: 440,
label: '440'
},
{
type: 'NOTE_MS',
ms: 1166.6666666666665,
msEnd: 1166.6666666666665,
hz: 550
hz: 550,
label: '550'
},
{
type: 'NOTE_MS',
ms: 1833.3333333333333,
msEnd: 1833.3333333333333,
hz: 660
hz: 660,
label: '660'
},
{
type: 'NOTE_MS',
ms: 2500,
msEnd: 2500,
hz: 770
hz: 770,
label: '770'
},
{
type: 'NOTE_MS',
ms: 3500,
msEnd: 3500,
hz: 880
hz: 880,
label: '880'
}
],
lengthMs: 3500
Expand Down
40 changes: 30 additions & 10 deletions packages/mosc/src/mosc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ export type MoscNote = {
time: number;
timeEnd: number;
hz: number;
label: string;
};

export type MoscNoteMs = {
type: 'NOTE_MS';
ms: number;
msEnd: number;
hz: number;
label: string;
};

export type MoscParam = {
Expand Down Expand Up @@ -158,6 +160,7 @@ export const scoreToMs = (score: MoscScore): MoscScoreMs => {
return {
type: 'NOTE_MS',
hz: note.hz,
label: note.label,
ms: thisTimeToMs(note.time),
msEnd: thisTimeToMs(note.timeEnd)
};
Expand Down Expand Up @@ -191,14 +194,13 @@ export const scoreToMs = (score: MoscScore): MoscScoreMs => {
// soud engine base class
//

type SoundEngineEvent = 'end';
type SoundEngineEventCallback = () => void;
type SoundEngineEndEventCallback = () => void;
type SoundEngineNoteEventCallback = (noteMs: MoscNoteMs, on: boolean) => void;
type SoundEngineEventCallbackCancel = () => void;

export class SoundEngine {

scoreMs?: MoscScoreMs;
events = new Map<SoundEngineEventCallback, SoundEngineEvent>();

playing(): boolean {
return false;
Expand All @@ -222,18 +224,36 @@ export class SoundEngine {

async gotoMs(ms: number): Promise<void> {}

async setLoop(loop: boolean, startMs: number = 0, endMs: number = 0): Promise<void> {}
setLoop(loop: boolean, startMs: number = 0, endMs: number = 0): void {}
setLoopActive(loop: boolean): void {}
setLoopStart(ms: number = 0): void {}
setLoopEnd(ms: number = 0): void {}

async setLoopStart(ms: number = 0): Promise<void> {}
async setScore(scoreMs: MoscScoreMs): Promise<void> {}

async setLoopEnd(ms: number = 0): Promise<void> {}
// events

async setScore(scoreMs: MoscScoreMs): Promise<void> {}
events = {
end: new Set<SoundEngineEndEventCallback>(),
note: new Set<SoundEngineNoteEventCallback>()
};

_triggerEvent(type: string, ...params: any) {
// @ts-ignore
this.events[type].forEach(cb => cb(...params));
}

onEnd(callback: SoundEngineEndEventCallback): SoundEngineEventCallbackCancel {
this.events.end.add(callback);
return () => {
this.events.end.delete(callback);
};
}

on(eventType: SoundEngineEvent, callback: SoundEngineEventCallback): SoundEngineEventCallbackCancel {
this.events.set(callback, eventType);
onNote(callback: SoundEngineNoteEventCallback): SoundEngineEventCallbackCancel {
this.events.note.add(callback);
return () => {
this.events.delete(callback);
this.events.note.delete(callback);
};
}
}
61 changes: 44 additions & 17 deletions packages/sound-engine-tonejs/src/sound-engine-tonejs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export class SoundEngineTonejs extends SoundEngine {
_started = false;
_endMs = 0;
_loopEndMs = 0;
_activeNoteEvents = new Set<MoscItemMs>();

synth = new Tone.PolySynth(Tone.Synth, {
oscillator: {
Expand Down Expand Up @@ -81,6 +82,17 @@ export class SoundEngineTonejs extends SoundEngine {
if(!this._started) {
await Tone.start();
this._started = true;

const onEnd = () => {
this.synth.releaseAll();
this._activeNoteEvents.forEach(noteMs => {
this._triggerEvent('note', noteMs, false);
});
this._activeNoteEvents.clear();
};

Tone.Transport.on('stop', onEnd);
Tone.Transport.on('loop', onEnd);
}
}

Expand All @@ -92,24 +104,27 @@ export class SoundEngineTonejs extends SoundEngine {
async pause(): Promise<void> {
await this.start();
Tone.Transport.stop();
this.synth.releaseAll();
}

async gotoMs(ms: number): Promise<void> {
Tone.Transport.seconds = ms * 0.001;
}

async setLoop(loop: boolean, startMs: number = 0, endMs: number = 0): Promise<void> {
setLoop(loop: boolean, startMs: number = 0, endMs: number = 0): void {
this.setLoopActive(loop);
this.setLoopStart(startMs);
this.setLoopEnd(endMs);
}

setLoopActive(loop: boolean = true): void {
Tone.Transport.loop = loop;
await this.setLoopStart(startMs);
await this.setLoopEnd(endMs);
}

async setLoopStart(ms: number = 0): Promise<void> {
setLoopStart(ms: number = 0): void {
Tone.Transport.loopStart = ms * 0.001;
}

async setLoopEnd(ms: number = 0): Promise<void> {
setLoopEnd(ms: number = 0): void {
this._loopEndMs = ms;
Tone.Transport.loopEnd = (ms === 0 ? this._endMs : ms) * 0.001;
}
Expand All @@ -121,20 +136,30 @@ export class SoundEngineTonejs extends SoundEngine {
Tone.Transport.cancel();

// add all new notes to tone transport
this.scoreMs.sequence.map((item: MoscItemMs): number => {
this.scoreMs.sequence.forEach((item: MoscItemMs): void => {
if(item.type === 'NOTE_MS') {
const noteMs = item as MoscNoteMs;
return Tone.Transport.schedule((time: number) => {
Tone.Transport.schedule((time: number) => {
this.synth.triggerAttackRelease(
noteMs.hz,
(noteMs.msEnd * 0.001) - (noteMs.ms * 0.001),
time + 0.01 // schedule in the future slightly to avoid double note playing at end
time
);
}, noteMs.ms * 0.001);
this._activeNoteEvents.add(noteMs);
this._triggerEvent('note', noteMs, true);
}, noteMs.ms * 0.001 + 0.1); // schedule in the future slightly to avoid double note playing at end

Tone.Transport.schedule((time: number) => {
this._activeNoteEvents.delete(noteMs);
this._triggerEvent('note', noteMs, false);
}, noteMs.msEnd * 0.001 + 0.1);

return;
}

if(item.type === 'PARAM_MS') {
const paramMs = item as MoscParamMs;
return Tone.Transport.schedule(() => {
Tone.Transport.schedule(() => {
// this is inaccurate
// as tonejs calls these callbacks several ms ahead of schedule
// and relies on scheduled events to pass the provided time
Expand All @@ -160,24 +185,26 @@ export class SoundEngineTonejs extends SoundEngine {
}

}, paramMs.ms * 0.001);

return;
}

if(item.type === 'END_MS') {
this._endMs = (item as MoscEndMs).ms;
if(this._loopEndMs === 0) {
this.setLoopEnd(0);
}

return Tone.Transport.schedule(async () => {
Tone.Transport.schedule(async () => {
if(Tone.Transport.loop) return;

Tone.Transport.stop();
this.gotoMs(0);
this.events.forEach((type, cb) => {
if(type !== 'end') return;
cb();
});
this._triggerEvent('end', undefined);
}, this._endMs * 0.001);

return;
}

// @ts-ignore
throw new Error(`Unexpected item type ${item.type} encountered`);
});
Expand Down
1 change: 1 addition & 0 deletions packages/xenpaper-app/src/@types/typings.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
declare module 'rd-parse';
declare module 'react-copy-to-clipboard';
declare module 'react-use-dimensions';
Loading

0 comments on commit d0d3bd7

Please sign in to comment.