Skip to content

Commit

Permalink
fix sustained voices not ending
Browse files Browse the repository at this point in the history
  • Loading branch information
spessasus committed Sep 25, 2024
1 parent ea183df commit 132df04
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 18 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@
<img src="src/website/spessasynth_logo_rounded.png" width='300' alt='SpessaSynth logo'>
</p>

**SpessaSynth** is a SoundFont2-based real-time synthesizer and MIDI player written in vanilla JavaScript.
It’s a powerful and versatile library that allows you to read, write, or play MIDI files,
read DLS files and read/write SF2/SF3 files with ease.
**SpessaSynth** is a SoundFont2-based real-time synthesizer and MIDI library written in vanilla JavaScript.
It’s a powerful and versatile library that allows you to:
- Play MIDI files using SF2/SF3/DLS files
- Write MIDI files
- Write SF2/SF3 files
- Convert DLS to SF2
- [and more!](#easy-integration)

```shell
npm install --save spessasynth_lib
```

### DLS Support now available!

<h1 align="center"><a href="https://spessasus.github.io/SpessaSynth/">Live Demo (no download needed!)</a></h1>

<h2 align="center">YouTube Video</h2>
Expand All @@ -37,7 +39,7 @@ This repository contains both the library and a complete musical web application
### Powerful SoundFont Synthesizer
- Suitable for both **real-time** and **offline** synthesis
- **Excellent SoundFont support:**
- **Generator Support**
- **Full Generator Support**
- **Modulator Support:** *First (to my knowledge) JavaScript SoundFont synth with that feature!*
- **SoundFont3 Support:** Play compressed SoundFonts!
- **Experimental SF2Pack Support:** Play soundfonts compressed with BASSMIDI! (*Note: only works with vorbis compression*)
Expand Down Expand Up @@ -119,6 +121,9 @@ This repository contains both the library and a complete musical web application

## Limitations
- Synth's performance may be suboptimal, especially on mobile devices.
- Audio may sometimes sound distored in Chrome, Edge, Brave,
etc. due to a **[Chromium Bug](https://issues.chromium.org/issues/367304685).**
I can't do anything about it, only hope that it gets fixed.

### Installation
#### Npm package
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "SpessaSynth",
"version": "3.20.27",
"version": "3.20.28",
"type": "module",
"scripts": {
"start": "node src/website/server/server.js"
Expand Down
16 changes: 8 additions & 8 deletions src/spessasynth_lib/synthetizer/worklet_processor.min.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { generatorTypes } from '../../../soundfont/read_sf2/generators.js'
export const VOLUME_ENVELOPE_SMOOTHING_FACTOR = 0.001;

const DB_SILENCE = 100;
const PERCEIVED_DB_SILENCE = 96;
const PERCEIVED_DB_SILENCE = 90;

/**
* VOL ENV STATES:
Expand All @@ -25,10 +25,18 @@ export class WorkletVolumeEnvelope
{
/**
* @param sampleRate {number} Hz
* @param initialDecay {number} cb
*/
constructor(sampleRate)
constructor(sampleRate, initialDecay)
{
this.sampleRate = sampleRate;
/**
* if sustain stge is silent,
* then we can turn off the voice when it is silent.
* We can't do that with modulated as it can silence the volume and then raise it again and the voice must keep playing
* @type {boolean}
*/
this.canEndOnSilentSustain = initialDecay / 10 >= PERCEIVED_DB_SILENCE;
}

/**
Expand Down Expand Up @@ -383,6 +391,10 @@ export class WorkletVolumeEnvelope
// fallthrough

case 4:
if(env.canEndOnSilentSustain && env.sustainDbRelative >= PERCEIVED_DB_SILENCE)
{
voice.finished = true;
}
// sustain phase: stay at sustain
while(true)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ class WorkletVoice
this.channelNumber = channel;
this.startTime = currentTime;
this.targetKey = targetKey;
this.volumeEnvelope = new WorkletVolumeEnvelope(sampleRate);
this.volumeEnvelope = new WorkletVolumeEnvelope(sampleRate, generators[generatorTypes.sustainVolEnv]);
}
/**
* Sample ID for voice.
Expand Down

0 comments on commit 132df04

Please sign in to comment.