diff --git a/src/spessasynth_lib/midi_parser/midi_loader.js b/src/spessasynth_lib/midi_parser/midi_loader.js index b7a197ab..03a09ba3 100644 --- a/src/spessasynth_lib/midi_parser/midi_loader.js +++ b/src/spessasynth_lib/midi_parser/midi_loader.js @@ -6,6 +6,7 @@ import { readBytesAsUintBigEndian, readVariableLengthQuantity } from "../utils/byte_functions.js"; +import { consoleColors } from '../utils/other.js' export class MIDI{ /** * Parses a given midi file @@ -187,10 +188,15 @@ export class MIDI{ } } this.tracks.push(track); - console.log("Parsed", this.tracks.length, "/", this.tracksAmount); + console.log(`%cParsed %c${this.tracks.length}%c / %c${this.tracksAmount}`, + consoleColors.info, + consoleColors.value, + consoleColors.info, + consoleColors.value); } - this.lastEventTick = Math.max(...this.tracks.map(t => t[t.length - 1].ticks)); + this.lastEventTick = Math.max(...this.tracks.map(track => + track[track.length - 1].ticks)); const firstNoteOns = []; for(const t of this.tracks) { @@ -202,7 +208,9 @@ export class MIDI{ } this.firstNoteOn = Math.min(...firstNoteOns); - console.log("MIDI file parsed. Total tick time:", this.lastEventTick); + console.log(`%cMIDI file parsed. Total tick time: %c${this.lastEventTick}`, + consoleColors.info, + consoleColors.recognized); if(loopStart === null ) { @@ -219,7 +227,6 @@ export class MIDI{ * @type {{start: number, end: number}} */ this.loop = {start: loopStart, end: loopEnd}; - console.log("loop", this.loop); // get track name this.midiName = ""; diff --git a/src/spessasynth_lib/sequencer/sequencer.js b/src/spessasynth_lib/sequencer/sequencer.js index 6c60d241..b02cf873 100644 --- a/src/spessasynth_lib/sequencer/sequencer.js +++ b/src/spessasynth_lib/sequencer/sequencer.js @@ -136,9 +136,9 @@ export class Sequencer { * Same as Audio.duration (seconds) * @type {number} */ - this.duration = this.ticksToSeconds(this.events[this.events.length - 1].ticks); + this.duration = this.ticksToSeconds(this.events.findLast(e => e.messageStatusByte >> 4 === 8 || (e.messageStatusByte >> 4 === 9 && e.messageData[1] === 0)).ticks) + 1; - console.log(`TOTAL TIME: ${formatTime(Math.round(this.duration)).time}`); + console.log(`%cTOTAL TIME: ${formatTime(Math.round(this.duration)).time}`, consoleColors.recognized); if(this.renderer) { diff --git a/src/spessasynth_lib/synthetizer/buffer_voice/midi_channel.js b/src/spessasynth_lib/synthetizer/buffer_voice/midi_channel.js index 268f24e9..04fb0dd8 100644 --- a/src/spessasynth_lib/synthetizer/buffer_voice/midi_channel.js +++ b/src/spessasynth_lib/synthetizer/buffer_voice/midi_channel.js @@ -52,26 +52,27 @@ export class MidiChannel { this.panner = new StereoPannerNode(this.ctx); this.gainController = new GainNode(this.ctx, { - gain: 1 + gain: CHANNEL_LOUDNESS }); - // note -> panner -> gain -> out + // note -> panner -> gain -> out + // \-> chorus -> delay -/ this.panner.connect(this.gainController); this.gainController.connect(this.outputNode); - // chorus test - // const delay = new DelayNode(this.ctx, { - // delayTime: 0.02 - // }); - // this.gainController.connect(delay); - // delay.connect(this.outputNode); - // - // const delay2 = new DelayNode(this.ctx, { - // delayTime: 0.03 - // }); - // this.gainController.connect(delay2); - // delay2.connect(this.outputNode); + this.chorusController = new GainNode(this.ctx, { + gain: 0 + }); + this.delayLine = new DelayNode(this.ctx, { + delayTime: 0.017 + }); + + this.panner.connect(this.chorusController); + this.chorusController.connect(this.delayLine); + + this.delayLine.connect(this.gainController); + this.resetControllers(); @@ -145,6 +146,10 @@ export class MidiChannel { this.setExpression(expression) break; + case midiControllers.effects3Depth: + this.setChorus(value); + break; + case midiControllers.NRPNMsb: this.setNRPCoarse(value); break; @@ -311,6 +316,15 @@ export class MidiChannel { return this.playingNotes.reduce((amt, voice) => amt + voice.sampleNodes.length, 0) + this.stoppingNotes.reduce((amt, voice) => amt + voice.sampleNodes.length, 0); } + /** + * @param chorus {number} 0-127 + */ + setChorus(chorus) + { + this.chorusLevel = chorus; + this.chorusController.gain.value = chorus / 127; + } + setVolume(volume) { this.channelVolume = volume / 127; this.gainController.gain.value = this.getGain(); @@ -533,6 +547,7 @@ export class MidiChannel { this.channelPitchBendRange = 2; this.holdPedal = false; this.gainController.gain.value = 1; + this.chorusController.gain.value = 0; this.panner.pan.value = 0; this.pitchBend = 0; this.modulation = 0; diff --git a/src/spessasynth_lib/synthetizer/synthetizer.js b/src/spessasynth_lib/synthetizer/synthetizer.js index 77c07252..09c3467e 100644 --- a/src/spessasynth_lib/synthetizer/synthetizer.js +++ b/src/spessasynth_lib/synthetizer/synthetizer.js @@ -242,6 +242,7 @@ export class Synthetizer { this.onControllerChange(chNr, midiControllers.pan, 64); this.onControllerChange(chNr, midiControllers.expressionController, 127); this.onControllerChange(chNr, midiControllers.modulationWheel, 0); + this.onControllerChange(chNr, midiControllers.effects3Depth, 0); } if(this.onPitchWheel) { diff --git a/src/website/ui/synthetizer_ui.js b/src/website/ui/synthetizer_ui.js index 6ca57c0b..0a785545 100644 --- a/src/website/ui/synthetizer_ui.js +++ b/src/website/ui/synthetizer_ui.js @@ -171,6 +171,11 @@ export class SynthetizerUI // mod wheel this.controllers[channel].mod.update(value); break; + + case midiControllers.effects3Depth: + // chorus + this.controllers[channel].chorus.update(value); + break; } } @@ -191,6 +196,7 @@ export class SynthetizerUI * pan: Meter, * expression: Meter, * mod: Meter, + * chorus: Meter, * preset: HTMLSelectElement, * presetReset: HTMLDivElement * }} ChannelController @@ -280,6 +286,18 @@ export class SynthetizerUI modulation.update(0); controller.appendChild(modulation.div); + // chorus + const chorus = new Meter(this.channelColors[channelNumber], + "Chorus: ", + 0, + 127, + true, + val => { + this.synth.controllerChange(channelNumber, midiControllers.effects3Depth, val); + }); + chorus.update(0); + controller.appendChild(chorus.div); + // create it here so we can use it in the callback function const presetReset = document.createElement("div"); @@ -318,6 +336,7 @@ export class SynthetizerUI expression: expression, volume: volume, mod: modulation, + chorus: chorus, preset: presetSelector, presetReset: presetReset };