davy7125 / soundfont-standard-v3

Attempt for a collaborative work around an update to the soundfont format.
30 stars 1 forks source link

proposal for backwards-compatible update to SF2 format #4

Open mrbumpy409 opened 4 years ago

mrbumpy409 commented 4 years ago

While I think most of your proposed changes to the SoundFont format should take place under a new format version & extension (I'd go with .sf4, personally), there are some features that could be added to the sf2 format without breaking compatibility with existing sf2 players. Adding these features would be a nice incremental upgrade for the sf2 format while also being less ambitious to implement. We would also be more likely to gain support for these features in existing SoundFont synths such as FluidSynth and BASSMIDI rather than the complete engine overhaul likely necessary to support all of the features in your full proposal. Here are my ideas:

Round-Robins

This is probably the number one upgrade that would improve the realism of SoundFont instruments, making it possible to avoid the "machine gun effect" that happens when the same sample is triggered over and over. Round-robin samples would be specified at the sample and/or instrument level as follows:

Round-Robin Samples

Identical sample names with a suffix formatted "_rr#", where # is an integer from 1 to 99, will cycle automatically when played within an instrument. For example, let's say a SoundFont contains the following samples:

The software will recognize these samples as an array of three round-robin samples for "pizz-C6". If the sample "pizz-C6_rr1" is assigned to an instrument, the first note that triggers this sample assignment will play "pizz-C6_rr1", and subsequent notes in turn will trigger "pizz-C6_rr2", then "pizz-C6_rr3", wrapping back around to "pizz-C6_rr1", etc.

If one of the round-robin samples numbered higher than 1 is assigned to an instrument, the round-robin samples would still cycle normally through the entire array, but starting on the assigned sample. So for example, if "pizz-C6_rr2" is assigned to an instrument, the samples would play in order: _rr2, _rr3, _rr1, etc.

Accommodation should also be made for linked stereo sample pairs, which can have either "L" or "R" appended to the very end of the sample name, e.g., "_rr1L", "_rr1R".

Round-Robin Instruments

Similar to how round-robin samples work, instrument zones suffixed with "_rr#" would be cycled within the preset zone. One way this method is useful is if you lack actual round-robin samples, you can create a round-robin effect through variations in the sound programming at the instrument level, then cycle these instruments within the preset.

When an instrument zone is cycled in this way, individually marked "_rrX" samples within the instrument zone will never get a chance to cycle, since the instrument is changing with every note-on event. This is the desired behavior, since the SoundFont creator should be able to control exactly which samples play with each cycled instrument.

Backwards Compatibility

SoundFont players not supporting this technique will not cycle the samples, but will still sound fine otherwise.

Key Switches

Many instruments have different articulations or play styles (e.g., bowed vs. plucked strings on a violin), and it is useful to be able to easily switch between these. A key switch is a designated key or range of keys on the keyboard that when pressed will change the active instrument to a different sound. This method is commonly used in professional sample libraries, especially for orchestral sounds where a wide variety of articulations are available for each instrument.

This would be implemented in SoundFont format in the following manner:

  1. Create an instrument but assign no samples to it. This instrument will be used as a key switch trigger zone.
  2. Name the instrument based on the bank and preset number the you wish to switch to, based on the format "bank:preset" and always using three digits to represent each number. For example, if you want the key switch to change to the sound at bank 1, preset 48, you would name the instrument: "001:048".
  3. Assign this instrument to the preset where you want this key switch to be active, giving it a key range so that only notes played within this range will trigger a preset change. Typically you would also set up a reciprocal key switch at the destination preset that would take you back to the first preset.

Backwards Compatibility

SoundFont players that don't support this method will not honor the key switch, but there would also be no adverse affect on the playback.

Release Samples

I'm only listing this because most people don't realize that release samples are already possible in the SoundFont format! Simply create a few samples of silence at the beginning of the release sample, loop this silence, then set the loop mode to "loop + end". Also set a long volume envelope release time. When you press a key, it will play only the silent loop, but upon releasing the key, the rest of the sample will play. You can even match the release sample volume to the decay of the sustain sample using the volume envelope decay phase.

Conclusion

I realize this is a short list of features, but everything would be backwards compatible with existing sf2 players, and both round-robin and key switch support would be a nice upgrade in functionality for the sf2 format without having to wait for something like sf4 to be developed and gain widespread support. The new feature set should also have a name. The one I came up with is "SoundFont eXtensions", or "SFX" for short, but I'm sure you all would have no trouble coming up with alternatives. Also, if anybody can think of other features that can be implemented in a backwards-compatible way or has improvements to the methods I've detailed above, please don't hesitate to share.

Peace and blessings to you all, -~Chris

jjceresa commented 4 years ago

Thanks you Chris for this description. To clarify my understanding, I would like confirmation about Key Switch feature from point (2) to point (3).

Assign this instrument to the preset where you want this key switch to be active, giving it a key range so that only notes played within this range will trigger a preset change.

I understand that when the MIDI key switch is received on MIDI Channel x by the synthesizer, instead of triggering a sound, it should trigger a bank:program change` (e.g 001:048) to the same MIDI Channel x. So that, future key note depressed by the musician on MIDI Channel x, will play using the new articulation (defined by preset 001:048). Please, is it correct ?

Best regards.

mrbumpy409 commented 4 years ago

@jjceresa Yes, that is correct. The key switch would essentially function the same as a program change event, in particular adhering to the rule in the MIDI spec that states the "receipt of a Program Change should not cut off any notes that were previously triggered on the channel, and which are still sustaining."