Skip to content

Commit

Permalink
Sequence player held notes fix
Browse files Browse the repository at this point in the history
  • Loading branch information
spessasus committed Sep 24, 2023
1 parent f866d3f commit dba57f4
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 6 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/node_modules/
/disabled_sf2s/
/config.json
/.idea
/.idea
/src/spessasynth_lib/synthetizer/freeverb_unused/
5 changes: 3 additions & 2 deletions src/spessasynth_lib/midi_parser/midi_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export class MIDI{
* @param fileByteArray {ShiftableByteArray}
*/
constructor(fileByteArray) {
console.groupCollapsed(`%cParsing MIDI File...`, consoleColors.info);

const headerChunk = this.readMIDIChunk(fileByteArray);
if(headerChunk.type !== "MThd")
{
Expand All @@ -31,8 +33,6 @@ export class MIDI{
// time division
this.timeDivision = readBytesAsUintBigEndian(headerChunk.data, 2);

console.log("Tracks:", this.tracksAmount, "Time division:", this.timeDivision);

/**
* Contains all the tempo changes in the file. (Ordered from last to first)
* @type {{
Expand Down Expand Up @@ -211,6 +211,7 @@ export class MIDI{
console.log(`%cMIDI file parsed. Total tick time: %c${this.lastEventTick}`,
consoleColors.info,
consoleColors.recognized);
console.groupEnd();

if(loopStart === null )
{
Expand Down
13 changes: 11 additions & 2 deletions src/spessasynth_lib/synthetizer/buffer_voice/midi_channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {Voice} from "./voice.js";
import {Preset} from "../../soundfont/chunk/presets.js";
import { consoleColors } from '../../utils/other.js'
import { midiControllers } from '../../midi_parser/midi_message.js'
import { Chorus } from './chorus.js'
import { Chorus } from '../chorus.js'

const CHANNEL_LOUDNESS = 0.5;

Expand Down Expand Up @@ -55,10 +55,15 @@ export class MidiChannel {
this.gainController = new GainNode(this.ctx, {
gain: CHANNEL_LOUDNESS
});
//this.reverb = new Freeverb(this.ctx, 0);

// note -> panner -> chorus -> gain -> out
// note -> panner -> chorus -> -> gain -> out

//const dummy = new GainNode(this.ctx, {gain: 1});
this.chorus = new Chorus(this.panner, this.gainController, 0);
//this.reverb.input.connect(dummy);
//this.reverb.connectOutput(this.gainController);

this.gainController.connect(this.outputNode);

this.resetControllers();
Expand Down Expand Up @@ -137,6 +142,10 @@ export class MidiChannel {
this.setChorus(value);
break;

// case midiControllers.effects1Depth:
// this.reverb.setLevel(value);
// break;

case midiControllers.NRPNMsb:
this.setNRPCoarse(value);
break;
Expand Down
File renamed without changes.
70 changes: 70 additions & 0 deletions src/spessasynth_lib/synthetizer/freeverb_unused/comb_filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
export class CombFilter
{
/**
* Feedback lowpass comb filter
* @param context {BaseAudioContext}
* @param delayTime {number}
*/
constructor(context, delayTime) {
//const context = inputNode.context;
this.delayLine = new DelayNode(context, {
delayTime: delayTime
});
this.lowPassFilter = new BiquadFilterNode(context, {
type: "lowpass",
frequency: 440
});
this.reasonanceGain = new GainNode(context, {
gain: 0.5
});

/* +---------------+
|reasonance gain|
+---------------+
| /|\
\|/ |
+-----+ +---------+ +-------+ +------+
|input|-->|delayLine|-->|lowpass|-->|output|
+-----+ +---------+ +-------+ +------+
| /|\
+------------------------------------+
*/
this.delayLine.connect(this.lowPassFilter);
this.lowPassFilter.connect(this.reasonanceGain);
this.reasonanceGain.connect(this.delayLine);
}

get input()
{
return this.delayLine;
}

get output()
{
return this.delayLine//this.lowPassFilter;
}

/**
* @param value {number}
*/
set dampening(value)
{
this.lowPassFilter.frequency.value = value;
}

/**
* @param value {number}
*/
set delayTime(value)
{
this.delayLine.delayTime.value = value;
}

/**
* @param value {number}
*/
set reasonance(value)
{
this.reasonanceGain.gain.value = value;
}
}
128 changes: 128 additions & 0 deletions src/spessasynth_lib/synthetizer/freeverb_unused/freeverb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Based on Freeverb, a public domain reverb implementation by Jezar at Dreampoint

import { CombFilter } from './comb_filter.js'

const COMB_FILTER_TUNINGS_LEFT = [1557, 1617, 1491, 1422];
const COMB_FILTER_TUNINGS_RIGHT = [1277, 1356, 1188, 1116];
const ALLPASS_FREQS = [225, 556, 441, 341];

const ROOM_SIZE_DEFAULT = 0.5;
const DAMPERING_DEFAULT = 3000;
export class Freeverb
{
/**
* Creates a new Freeverb instance
* @param context {BaseAudioContext}
* @param defaultLevel {number} 0-127
*/
constructor(context, defaultLevel) {
/*
* +-------------+
* +->|comb filter 1|------+
* | +-------------+ |
* left | \|/
* +--------+ 6 more +------+ +---------+ +---------+ +---------+ +---------+ +------+
* |input|->|splitter| filters here |merger|-> |allpass 1|->|allpass 2|->|allpass 3|->|allpass 4|->|output|
* +--------+ +------+ +---------+ +---------+ +---------+ +---------+ +------+
* right | /|\
* | +-------------+ |
* +->|comb filter 8|------+
* +-------------+
*
*
* i think thats how it works
*
*/
// merger and splitter
this.splitter = new ChannelSplitterNode(context, {
numberOfOutputs: 2
});
this.merger = new ChannelMergerNode(context, {
numberOfInputs: 2
});
// reverb level controllers
this.wetGain = new GainNode(context, {
gain: defaultLevel / 127
});
this.dryGain = new GainNode(context, {
gain: (127 - defaultLevel) / 127
});

this.wetGain.connect(this.splitter);

// comb filters left
this.combFiltersLeft = COMB_FILTER_TUNINGS_LEFT.map(tuning => {
const comb = new CombFilter(context, tuning / context.sampleRate);
comb.reasonance = ROOM_SIZE_DEFAULT;
comb.dampening = DAMPERING_DEFAULT;

this.splitter.connect(comb.input, 0);
comb.output.connect(this.merger, 0, 0);
return comb;
});

// comb filters right
this.combFiltersRight = COMB_FILTER_TUNINGS_RIGHT.map(tuning => {
const comb = new CombFilter(context, tuning / context.sampleRate);
comb.reasonance = ROOM_SIZE_DEFAULT;
comb.dampening = DAMPERING_DEFAULT;

this.splitter.connect(comb.input, 1);
comb.output.connect(this.merger, 0, 1);
return comb;
});
this.splitter.connect(this.merger, 1, 1);
this.splitter.connect(this.merger, 0, 0);

/**
* allpass filters
* @type {BiquadFilterNode[]}
*/
this.allpassFilters = [];
ALLPASS_FREQS.forEach((frequency, index) => {
const allpass = new BiquadFilterNode(context, {
type: 'allpass',
frequency: frequency
});

if(this.allpassFilters[index - 1])
{
this.allpassFilters[index - 1].connect(allpass);
}
this.allpassFilters.push(allpass);
});

this.merger.connect(this.allpassFilters[0]);
}

/**
* @returns {{connect: function(AudioNode)}}
*/
get input()
{
return {
connect: node => {
node.connect(this.dryGain);
node.connect(this.wetGain);
}
}
}

/**
* @param output {AudioNode}
*/
connectOutput(output)
{
this.dryGain.connect(output);
this.allpassFilters[this.allpassFilters.length - 1].connect(output);
}

/**
* @param level {number} 0-127
*/
setLevel(level)
{
this.wetGain.gain.value = level / 127;
this.dryGain.gain.value = (127 - level) / 127;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { consoleColors } from '../../utils/other.js'
import { modulatorSources } from '../../soundfont/chunk/modulators.js'
import { midiControllers } from '../../midi_parser/midi_message.js'
import { addAndClampGenerator, generatorTypes } from '../../soundfont/chunk/generators.js'
import { Chorus } from '../chorus.js'
const CHANNEL_GAIN = 0.5;

export const NON_CC_INDEX_OFFSET = 128;
Expand Down Expand Up @@ -142,7 +143,8 @@ export class WorkletChannel {
*/
this.dumpedSamples = new Set();

this.worklet.connect(this.gainController);
this.chorus = new Chorus(this.worklet, this.gainController, 0);

this.gainController.connect(this.outputNode);

this.resetControllers();
Expand Down Expand Up @@ -211,6 +213,10 @@ export class WorkletChannel {
this.setNRPFine(val);
break;

case midiControllers.effects3Depth:
this.chorus.setChorusLevel(val);
break;

case midiControllers.sustainPedal:
if(val > 64)
{
Expand Down
2 changes: 2 additions & 0 deletions src/website/sequence_recorder/sequence_player.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { MIDIDeviceHandler } from '../../spessasynth_lib/midi_handler/midi_handler.js'
import { midiControllers } from '../../spessasynth_lib/midi_parser/midi_message.js'

export class SequencePlayer
{
Expand Down Expand Up @@ -32,6 +33,7 @@ export class SequencePlayer
this.eventIndex++;
if(this.eventIndex >= this.recorder.events.length)
{
this.synth.controllerChange(this.recorder.targetChannel, midiControllers.allNotesOff, 0);
this.eventIndex = 0;
this.startTime = this.synth.currentTime;
}
Expand Down

0 comments on commit dba57f4

Please sign in to comment.