Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use channel 10 for percussion #187

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

gagern
Copy link

@gagern gagern commented Jul 25, 2016

This enables the generation of percussion as an “instrument” in the soundfont builder. It also adds that instrument to our General Midi database, with ID 0 (one-based) resp. -1 (zero-based). This does not really reflect the use in GM, but avoids a large number of case distinctions and appears mostly beneficial. This instrument is pre-selected for channel 10 (one-based), to conform with GM usage.

The soundfont builder changes fix #91. This also addresses the core of #72, but perhaps we should prevent program changes on channel 10 to completely fix that. Doing so might break some existing applications, though, so another alternative might be suppressing program changes in the MIDI file player only.

Do we need to restrict the soundfont creation to those “notes” which actually have a percussion instrument associated with them? Currently I'm using the same range used for other instruments as well, and I don't see fluidsynth complaining.

This enables the generation of “percussion” as an “instrument” in the
soundfont builder.  It also adds that instrument to our General Midi
database, with ID 0 (one-based) resp. -1 (zero-based).  This does not
really reflect the use in GM, but avoids a large number of case
distinctions and appears mostly beneficial.  This instrument is
pre-selected for channel 10 (one-based), to conform with GM usage.
This argument is never used, and I have no idea what that variable
`instrument` would be referring to in this place, since it is not
a declared variable of nearby enclosing scopes.

This is a drive-by fix, found and fixed on the way towards percussion.
@hmoffatt
Copy link

This looks good (I've hacked something similar in here). But also GM allows for multiple drum kits with different programs I think, so maybe you shouldn't force program a single program -1. The drum kits are really a whole separate bank of instruments.

@hmoffatt
Copy link

Ideally you would only include samples for which there are actually sounds in the sound font, else you are including a lot of samples of silence, but it's not easy to know which notes are used and which aren't.

@gagern
Copy link
Author

gagern commented Aug 1, 2016

@hmoffatt I realized that there could be multiple drumkits when I looked at https://github.com/musescore/MIDI.js/commit/4c1e69260c4a27bfc7cf7935396ccaabf2cbb688. And I had the same thought as you: we really should be generating exactly those keys for which there are samples in the soundfont. So I wrote a soundfont parser for Node.js and learned a lot about the soundfont format in the process. I realized that MIDI.js in particular does not make use of the loop points present in the soundfont, so it can't stretch the sustain phase arbitrarily. I also learned how it shares samples for multiple keys, and how it can reuse whole instruments in different presets, which seems particularly relevant for different drumkits. At the moment I'm considering abandoning MIDI.js and writing a wavetable synthesizer that works with the raw samples, as stored in the soundfont, and in the end ideally reproduces what fluidsynth does to turn these samples into notes, honoring as many of the soundfont generator specifications as technically possible.

@hmoffatt
Copy link

hmoffatt commented Aug 1, 2016

Nice work @gagern, I would be interested in an improved version of the soundfont converter that omitted unused notes. (Although you mentioned you wrote the sf2 parsing for Node.js, so maybe this is not easy. I was tempted to rewrite the converter in Python personally, as there is an sf2 parser module for Python also.)

Ideally the converter would extract the samples directly and also the loop parameters, so that those could be used by the sample player. I think webaudio supports looping. I think sf2 also supports different samples for different velocities...

You might be interested in https://github.com/danigb/soundfont-player which loads the existing javascript soundfont conversions and just plays individual notes without any sort of sequencing layer.

@gagern
Copy link
Author

gagern commented Aug 1, 2016

@hmoffatt: I have a version which does extract all the samples, but the metadata still needs some reformatting. Yes, WebAudio does support looping. It currently does not support exiting the loop at a scheduled point in time for the release phase, which is something sf2 supports but which is not being used in the Fluid soundfont I've been working with so far. WebAudio also supports changing the playback rate, which is vital since samples may be used for different notes than those for which they were recorded. Sf2 also assumes a configurable five-phase volume envelope (attack, hold, decay, sustain, release), and some soundfonts might sound bad unless the player learned to reproduce those as well.

I'm thinking about something along the lines of soundfont-player, but using the actual data from the sf2. Adding a sequencing layer on top of that would be fairly simple, so the core functionality would be in being able to play each note as accurately as possible.

gagern added a commit to gagern/CindyJS that referenced this pull request Aug 1, 2016
The MIDI.js verison here is one which integrates three of my PRs:
mudcube/MIDI.js#187 (percussion)
mudcube/MIDI.js#189 (MIDI.now)
mudcube/MIDI.js#190 (WebMIDI detection)

The playtone function automatically triggers loading of the plugin.  The
corresponding soundfont is loaded only when needed, which means there will
be some time between when the function calls start and when sound becomes
actually audible.

Samples are hosted on http://cindyjs.org/soundfont/ which might break
widgets delivered through HTTPS.  We need a certificate for cindyjs.org to
solve this problem, or allow configuring the soundfont through some API,
e.g. some CindyScript function.

The example is essentially taken from a Cinderella export, except for the
deletion of a duplicate play button.
gagern added a commit to gagern/CindyJS that referenced this pull request Aug 1, 2016
The MIDI.js verison here is one which integrates three of my PRs:
mudcube/MIDI.js#187 (percussion)
mudcube/MIDI.js#189 (MIDI.now)
mudcube/MIDI.js#190 (WebMIDI detection)

The playtone function automatically triggers loading of the plugin.  The
corresponding soundfont is loaded only when needed, which means there will
be some time between when the function calls start and when sound becomes
actually audible.

Samples are hosted on http://cindyjs.org/soundfont/ which might break
widgets delivered through HTTPS.  We need a certificate for cindyjs.org to
solve this problem, or allow configuring the soundfont through some API,
e.g. some CindyScript function.

The example is essentially taken from a Cinderella export, except for the
deletion of a duplicate play button.
gagern added a commit to gagern/CindyJS that referenced this pull request Aug 1, 2016
The MIDI.js verison here is one which integrates three of my PRs:
mudcube/MIDI.js#187 (percussion)
mudcube/MIDI.js#189 (MIDI.now)
mudcube/MIDI.js#190 (WebMIDI detection)

The playtone function automatically triggers loading of the plugin.  The
corresponding soundfont is loaded only when needed, which means there will
be some time between when the function calls start and when sound becomes
actually audible.

Samples are hosted on http://cindyjs.org/soundfont/ which might break
widgets delivered through HTTPS.  We need a certificate for cindyjs.org to
solve this problem, or allow configuring the soundfont through some API,
e.g. some CindyScript function.

The example is essentially taken from a Cinderella export, except for the
deletion of a duplicate play button.
montaga pushed a commit to montaga/CindyJS that referenced this pull request May 25, 2018
The MIDI.js verison here is one which integrates three of my PRs:
mudcube/MIDI.js#187 (percussion)
mudcube/MIDI.js#189 (MIDI.now)
mudcube/MIDI.js#190 (WebMIDI detection)

The playtone function automatically triggers loading of the plugin.  The
corresponding soundfont is loaded only when needed, which means there will
be some time between when the function calls start and when sound becomes
actually audible.

Samples are hosted on http://cindyjs.org/soundfont/ which might break
widgets delivered through HTTPS.  We need a certificate for cindyjs.org to
solve this problem, or allow configuring the soundfont through some API,
e.g. some CindyScript function.

The example is essentially taken from a Cinderella export, except for the
deletion of a duplicate play button.
montaga pushed a commit to montaga/CindyJS that referenced this pull request May 25, 2018
The MIDI.js verison here is one which integrates three of my PRs:
mudcube/MIDI.js#187 (percussion)
mudcube/MIDI.js#189 (MIDI.now)
mudcube/MIDI.js#190 (WebMIDI detection)

The playtone function automatically triggers loading of the plugin.  The
corresponding soundfont is loaded only when needed, which means there will
be some time between when the function calls start and when sound becomes
actually audible.

Samples are hosted on http://cindyjs.org/soundfont/ which might break
widgets delivered through HTTPS.  We need a certificate for cindyjs.org to
solve this problem, or allow configuring the soundfont through some API,
e.g. some CindyScript function.

The example is essentially taken from a Cinderella export, except for the
deletion of a duplicate play button.
montaga pushed a commit to montaga/CindyJS that referenced this pull request May 30, 2018
The MIDI.js verison here is one which integrates three of my PRs:
mudcube/MIDI.js#187 (percussion)
mudcube/MIDI.js#189 (MIDI.now)
mudcube/MIDI.js#190 (WebMIDI detection)

The playtone function automatically triggers loading of the plugin.  The
corresponding soundfont is loaded only when needed, which means there will
be some time between when the function calls start and when sound becomes
actually audible.

Samples are hosted on http://cindyjs.org/soundfont/ which might break
widgets delivered through HTTPS.  We need a certificate for cindyjs.org to
solve this problem, or allow configuring the soundfont through some API,
e.g. some CindyScript function.

The example is essentially taken from a Cinderella export, except for the
deletion of a duplicate play button.
montaga pushed a commit to montaga/CindyJS that referenced this pull request May 30, 2018
The MIDI.js verison here is one which integrates three of my PRs:
mudcube/MIDI.js#187 (percussion)
mudcube/MIDI.js#189 (MIDI.now)
mudcube/MIDI.js#190 (WebMIDI detection)

The playtone function automatically triggers loading of the plugin.  The
corresponding soundfont is loaded only when needed, which means there will
be some time between when the function calls start and when sound becomes
actually audible.

Samples are hosted on http://cindyjs.org/soundfont/ which might break
widgets delivered through HTTPS.  We need a certificate for cindyjs.org to
solve this problem, or allow configuring the soundfont through some API,
e.g. some CindyScript function.

The example is essentially taken from a Cinderella export, except for the
deletion of a duplicate play button.
Comment on lines 66 to -67

# Display instrument names.
INSTRUMENTS.each do |i|
puts " #{i}: " + MIDI::GM_PATCH_NAMES[i]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

General MIDI Percussion soundfonts
3 participants