import { Note, toCents } from './scale.mjs'; import GuitarFuzz from './vend/guitar-fuzz.mjs'; import Trombone from './vend/trombone.mjs'; const audioCtx = new AudioContext(); const fuzzWave = new PeriodicWave(audioCtx, { real: GuitarFuzz.real, imag: GuitarFuzz.imag }); const tromboneWave = new PeriodicWave(audioCtx, { real: Trombone.real, imag: Trombone.imag }); const globalGain = new GainNode(audioCtx, { gain: 0.06 }) export default class { // oscillatornodes notes = []; // offsets is an array of offsets in cents from A4. constructor(offsets) { console.debug('Player#constructor', this, offsets); this.offsets = offsets; this.notes = offsets.map(o => new OscillatorNode(audioCtx, { frequency: 440, // a above middle c (c4) detune: o, // type: 'sine', type: 'custom', periodicWave: tromboneWave, })); this.notes.forEach(n => n.connect(globalGain).connect(audioCtx.destination)); } start() { console.debug('Player#start', this); this.notes.forEach(n => n.start()); } stop() { console.debug('Player#stop', this); this.notes.forEach(n => n.stop()); } test() { const cNote = Note.fromString('C'); console.assert(cNote.distanceTo(cNote) === 0); const dNote = Note.fromString('D'); console.assert(cNote.distanceTo(dNote) === 2); const dSharpNote = Note.fromString('D♯'); console.assert(cNote.distanceTo(dSharpNote) === 3); const aNote = Note.fromString('A', 'A to A'); console.assert(toCents([aNote, 4], [aNote, 3]) === -1200); const bNote = Note.fromString('B'); console.assert(toCents([aNote, 4], [bNote, 4]) == 200, 'A4 to B4 is 200 cents'); // E F F# G G# A const eNote = Note.fromString('E'); console.assert(toCents([aNote, 4], [eNote, 4]) === -500, 'E4 is 500 cents lower than A4'); console.assert(toCents([aNote, 4], [bNote, 3]) === -1000, 'A4 to B3 is 100 cents above -1200'); } }