Skip to content

Commit

Permalink
spec update
Browse files Browse the repository at this point in the history
reverb defaults to 40 now
more system exclusive support
code refactoring
data entry fine support
fine-tuning support
mod depth support
key shift support (untested though as i don't have MIDIs that support it)
fix no note midis crashing the program
fix mobile regex
  • Loading branch information
spessasus committed Jun 9, 2024
1 parent d1b43e0 commit d24f2fc
Show file tree
Hide file tree
Showing 13 changed files with 469 additions and 299 deletions.
51 changes: 34 additions & 17 deletions src/spessasynth_lib/sequencer/sequencer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {readBytesAsUintBigEndian} from "../utils/byte_functions.js";
*/

const MIN_NOTE_TIME = 0.02;
const MAX_NOTEONS_PER_S = 200;

// an array with preset default values
const defaultControllerArray = new Int16Array(127);
Expand All @@ -20,6 +19,7 @@ defaultControllerArray[midiControllers.expressionController] = 127;
defaultControllerArray[midiControllers.pan] = 64;
defaultControllerArray[midiControllers.releaseTime] = 64;
defaultControllerArray[midiControllers.brightness] = 64;
defaultControllerArray[midiControllers.effects1Depth] = 40;

export class Sequencer {
/**
Expand Down Expand Up @@ -89,7 +89,6 @@ export class Sequencer {
*/
this.midiPortChannelOffsets = {};

this.noteOnsPerS = 0;

/**
* @type {Object<string, function(MIDI)>}
Expand Down Expand Up @@ -177,8 +176,12 @@ export class Sequencer {
this.stop();
this.playingNotes = [];
this.pausedTime = undefined;
this._playTo(time);
const isNotFinished = this._playTo(time);
this.absoluteStartTime = this.now - time / this.playbackRate;
if(!isNotFinished)
{
return;
}
this.play();
if(this.renderer)
{
Expand All @@ -196,8 +199,12 @@ export class Sequencer {
}
this.playingNotes = [];
this.pausedTime = undefined;
this._playTo(0, ticks);
const isNotFinished = this._playTo(0, ticks);
this.absoluteStartTime = this.now - this.playedTime / this.playbackRate;
if(!isNotFinished)
{
return;
}
this.play();
if(this.renderer)
{
Expand Down Expand Up @@ -256,8 +263,7 @@ export class Sequencer {
* @type {number}
*/
this.duration = this.ticksToSeconds(this.midiData.lastVoiceEventTick);

console.info(`%cTotal song time: ${formatTime(Math.round(this.duration)).time}`, consoleColors.recognized);
console.info(`%cTotal song time: ${formatTime(Math.ceil(this.duration)).time}`, consoleColors.recognized);
this.midiPortChannelOffset = 0;
this.midiPortChannelOffsets = {};

Expand All @@ -269,6 +275,12 @@ export class Sequencer {
}

this.synth.resetControllers();
if(this.duration <= 1)
{
console.info(`%cVery short song: (${formatTime(Math.round(this.duration)).time}). Disabling loop!`,
consoleColors.warn);
this.loop = false;
}
this.play(true);
}

Expand Down Expand Up @@ -459,6 +471,7 @@ export class Sequencer {
* @private
* @param time {number} in seconds
* @param ticks {number} optional MIDI ticks, when given is used instead of time
* @returns {boolean} true if the midi file is not finished
*/
_playTo(time, ticks = undefined)
{
Expand Down Expand Up @@ -580,6 +593,11 @@ export class Sequencer {
// find next event
trackIndex = this._findFirstEventIndex();
let nextEvent = this.tracks[trackIndex][this.eventIndex[trackIndex]];
if(nextEvent === undefined)
{
this.stop();
return false;
}
this.playedTime += this.oneTickToSeconds * (nextEvent.ticks - event.ticks);
}

Expand Down Expand Up @@ -620,7 +638,7 @@ export class Sequencer {
}
})
}
window.abba = savedControllers;
return true;
}

/**
Expand All @@ -631,7 +649,8 @@ export class Sequencer {
{

// reset the time if necesarry
if(resetTime) {
if(resetTime)
{
this.currentTime = 0;
return;
}
Expand All @@ -658,8 +677,11 @@ export class Sequencer {
this.synth.noteOn(n.channel, n.midiNote, n.velocity);
});

if(this.playbackInterval)
{
clearInterval(this.playbackInterval);
}
this.playbackInterval = setInterval(this._processTick.bind(this));
setInterval( () =>this.noteOnsPerS = 0, 100);
}

/**
Expand All @@ -680,7 +702,7 @@ export class Sequencer {

// find next event
trackIndex = this._findFirstEventIndex();
if(this.tracks[trackIndex].length <= this.eventIndex[trackIndex])
if(this.tracks[trackIndex].length < this.eventIndex[trackIndex])
{
// song has ended
if(this.loop)
Expand All @@ -699,13 +721,13 @@ export class Sequencer {
this.playedTime += this.oneTickToSeconds * (eventNext.ticks - event.ticks);

// loop
if((this.midiData.loop.end <= event.ticks) && this.loop)
if((this.midiData.loop.end < event.ticks) && this.loop)
{
this.setTimeTicks(this.midiData.loop.start);
return;
}
// if song has ended
else if(current > this.duration + 0.1)
else if(current >= this.duration)
{
if(this.loop)
{
Expand Down Expand Up @@ -756,11 +778,6 @@ export class Sequencer {
case messageTypes.noteOn:
const velocity = event.messageData[1];
if(velocity > 0) {
if(this.synth.highPerformanceMode && (this.noteOnsPerS > MAX_NOTEONS_PER_S && velocity < 40) || this.noteOnsPerS > MAX_NOTEONS_PER_S * 2)
{
return;
}
this.noteOnsPerS++;
this.synth.noteOn(statusByteData.channel, event.messageData[0], velocity);
this.playingNotes.push({
midiNote: event.messageData[0],
Expand Down
2 changes: 0 additions & 2 deletions src/spessasynth_lib/soundfont/chunk/modulators.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ export const modulatorSources = {
channelPressure: 13,
pitchWheel: 14,
pitchWheelRange: 16,
channelTuning: 17,
channelTranspose: 18,
link: 127
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class MidiChannel {
});

this.reverb = new GainNode(this.ctx, {
gain: 0
gain: 40 / 127
});
this.reverb.connect(targetReverbNode);

Expand Down Expand Up @@ -652,6 +652,12 @@ export class MidiChannel {
}


if(!this.lockedControllers[midiControllers.effects1Depth])
{
this.reverb.gain.value = 40 / 127;
}


if(!this.lockedControllers[midiControllers.pan])
{
this.panner.pan.value = 0;
Expand Down
Loading

0 comments on commit d24f2fc

Please sign in to comment.