Defining a new instrument built on a separate soundfont

• Sep 11, 2022 - 15:45

I'm trying to create a new instrument in the ìnstrument.xml file that would not use the default sf3 file of Musescore but a separate sf2 soundfont.

The goal is that when I add that instrument to my score, the right "sound" is selected for that instrument in the Mixer, that right "sound" belonging to the other soundfont.

For now, with my instrument's definition, every time I add a new occurrence of it in a score, I have to go in the mixer and select the right "sound" from the other soundfont. I would like this to automatic. Deduced from the instrument's definition.

I based myself on the Soundfont, MIDI velocity and instruments.xml chapter of the handbook.

Let's take the example of the Triangle.

This is the original Triangle instrument definition:

 
<Instrument id="triangle"><!--orig-->
    <family>unpitched-metal-percussion</family>
    <longName>Triangle</longName>
    <shortName>Trgl.</shortName>
    <description>Triangle</description>
    <musicXMLid>metal.triangle</musicXMLid>
    ...
    <Channel>
        <controller ctrl="0" value="1"/>
        <program value="48"/>
        <!--Orchestra Kit-->
    </Channel>
    ...
</Instrument>

First, I don't understand why ctrl_0_value has a value of 1. I expected to find 0 as it should be using the "Musescore_General.sf3" soundfont.

This my redefinition of the triangle:

<Instrument id="triangle-sss"> <!-- symphonic sounds soundfont -->
      <family>unpitched-metal-percussion</family>
      <longName>Triangle SSS</longName>
      <shortName>Trgl.</shortName>
      <description>Triangle SSS</description>
      <musicXMLid>metal.triangle</musicXMLid>
      <clef>PERC</clef>
      <stafftype staffTypePreset="perc1Line">percussion</stafftype>
      <barlineSpan>1</barlineSpan>
      <drumset>1</drumset>
      <singleNoteDynamics>0</singleNoteDynamics>
      <Drum pitch="55">
            <head>cross</head> <!--Mute Triangle-->
            <line>0</line>
            <voice>0</voice>
            <name>Mute Triangle</name>
            <stem>2</stem>
            <shortcut>B</shortcut>
      </Drum>
      <Drum pitch="57"> <!--Open Triangle-->
            <head>normal</head>
            <line>0</line>
            <voice>0</voice>
            <name>Open Triangle</name>
            <stem>2</stem>
            <shortcut>A</shortcut>
      </Drum>
      <Drum pitch="56"> <!--Half-open Triangle-->
            <head>xcircle</head>
            <line>0</line>
            <voice>0</voice>
            <name>Half-openTriangle</name>
            <stem>2</stem>
            <shortcut>C</shortcut>
      </Drum>
      <Channel>
            <controller ctrl="0" value="1"/><!-- 1->2 ??? -->
            <program value="48"/><!-- 48->50 ??? -->
      </Channel>
      <genre>common</genre>
      <genre>orchestra</genre>
      <genre>concertband</genre>
</Instrument>

Secondly, which values should I put in ctrl_0_value and ctrl_32_value in order to assign this instrument to the 2nd soundfont, being "Symphonic Sounds.sf2"

Synthethizer.png

This is the soundfont as seen in sforzando:
triangle_sf2.png

Thanks!


Comments

I'm far from an expert in this area, but since mixer assignments are stored in the score and synth settings can be "saved to score"; perhaps you can find a hint by looking at the same score that starts with just MSGeneral sounds and then reassign a single sound and compare the results?

In reply to by jeetee

Good idea! I compared the same instrument, once with the right sound, manually set, and once with the default sound, and I came to this:

<Channel> <!-- SymphonicSounds.sf2 expected to be in 2nd position -->
  <controller ctrl="0" value="2"/>
  <controller ctrl="32" value="1"/>
  <program value="50"/>
  <synti>Fluid</synti>
</Channel>

However, this means that the handbook on instruments and soundfonts is not correct.

This is what is said :
refer the 1st ordered soundfont with expected ctrl_0_value(=0) and expected ctrl_32_value,
refer the 2nd ordered soundfont with expected ctrl_0_value(=1) and expected+1 ctrl_32_value,

All the Musescore default instruments are using the ctrl_0_value=1.
And mines (using the second soundfont) must use ctrl_0_value=2

So the doc the should be updated as
refer the 1st ordered soundfont with expected ctrl_0_value(=1) and expected ctrl_32_value,
refer the 2nd ordered soundfont with expected ctrl_0_value(=2) and expected+1 ctrl_32_value,

l double checked my files after I saw the above comment
The wiki page is in fact partly incorrect because it represents a oversimplified relationship between soundfont and ctrl_0_value ctrl_32_value, hope the explanation below help you, please correct the handbook after you test and confirm.

Re 1st question: That Triangle use <drumset>1</drumset>, it is a percussion sound. Use percussion sound if you want to use Drumset palette in Input mode
That Triangle uses 1st (Musescore default) soundfont's Bank128 Preset 48.
Reference 1st soundfont's Bank128 as ctrl_0_value=1, ctrl_32_value=0 in xml.
In musescore default xml and soundfont, Bank is used differently in two type of sound,
percussion sound use Bank128 only,
non-percussion sound Bank0 = instrument's normal sound.
eg
Default soundfont's Bank128 Preset x = various percussion sound
Default soundfont's Bank 0 Preset 0 = Piano normal
Default soundfont's Bank 0 Preset 12 = Marimba normal
Default soundfont's Bank 0 Preset 24 = Guitar open

<program value="48"/> is always the Preset value shown in Polyphone, it is not affected by other values mentioned.
In musescore default xml and soundfont, Preset is used differently in two type of sound,
percussion sound's preset number represents the taste/style ,
non-percussion sound's preset number represents instrument.
eg
Default soundfont's Bank128 Preset 0 = Standard
Default soundfont's Bank128 Preset 16 = Power
Default soundfont's Bank128 Preset 48 = Orchestra Kit
Pitch 36=Bass Drum 1
Pitch 38=Acoustic Snare

Re 2nd question: To reference 2nd soundfont's Bank 128 as ctrl_0_value=2, ctrl_32_value=1.
This is true if and only if the 1st soundfont's Bank128 is occupied, 1st (Musescore default) soundfont is Bank128 occupied.
Use program_value=Preset value shown in Polyphone, it is not affected by other values.

Copy and paste method
You may not need to learn the ctrl0 ctlr32 logic.
Edit and finalize your custom soundfont, load soundfonts in synthesizer, keep default soundfont as 1st, order others as desired, click Set as default, then don't rearrange banks and presets in your soundfonts and don't rearrange the order of soundfonts in the synthesizer anymore , because these affects what your custom instruments.xml point to.
New score, add instruments, choose sound you desire in Mixer, save as mscx.
Open mscx as plaintext and see its Channel definition , copy and paste to create custom instruments.xml.

TLDR

If you really want to get down to the nitty gritty:
there are two different usage of Bank and Preset inside Musescore default xml and soundfont

Non-percussion

  • Musescore3's default use different Preset to represent different instruments , it's from GM I suppose
  • Musescore use Bank in a way that seems different from other app and mainstream MIDI keyboards. Don't want to learn what MSB, LSB, BankSelect are? Use an editor that show Bank number directly.
  • Musescore3's default use Bank 0 as default normal sound for each instrument ; Bank 17 for instruments' Expressive version = Single note dynamics = CC2 modulator instead of the default Note-On velocity modulator. To use SND set <singleNoteDynamics>1</singleNoteDynamics>, it is equal to ticking the Use Single Note Dynamics box in Staff properties
  • Do not bother to think too much about the ctrl_0_value and ctrl_32_value, they do not have real independent meaning, they are used together to calculate the Bank you want in a messy end-to-end manner.

The logic:
1st soundfont Bank 0-127 => ctrl_0_value=0, ctrl_32_value=0,1,2...127
1st soundfont Bank 128 => ctrl_0_value=1, ctrl_32_value=0
2nd soundfont Bank 0-126 => ctrl_0_value=1, ctrl_32_value=1,2,3...127
2nd soundfont Bank 127 => ctrl_0_value=2, ctrl_32_value=0
2nd soundfont Bank 128 => ctrl_0_value=2, ctrl_32_value=1
3rd soundfont Bank 0... => ctrl_0_value=2, ctrl_32_value=2,3,4....

Why 1st soundfont's Bank 128 is reference by ctrl_0_value=1, ctrl_32_value=0 ?
The ctrl_32_value has a space of 128 bits(0 to 127) that need to be fill up to proceed to the next ctrl_0_value.

Why 2nd soundfont use Bank number + 1 in ctrl_32_value?
Its ctrl_32_value starts from 1, because the 1st soundfont's Bank 128 occupy the ctrl_32_value 0

  • I keep all my custom soundfonts' Bank 128 occupied to keep things simple, you can create empty sound in Polyphone.
    For example if you use more than two soundfonts and the 2nd soundfont does not have Bank128 occupied, you will have to calculate and see that 3rd soundfont starts from ctrl_32_value 64 if 2nd soundfont has max Bank 62 only:
    1st soundfont Bank 0-127 => ctrl_0_value=0, ctrl_32_value=0,1,2...127
    1st soundfont Bank 128 => ctrl_0_value=1, ctrl_32_value=0
    2nd soundfont Bank 0-62 => ctrl_0_value=1, ctrl_32_value=1,2,3...63
    3rd soundfont Bank 0... => ctrl_0_value=2, ctrl_32_value=64,65,66...
    Then .............................. => ctrl_0_value=2, ctrl_32_value=..127
    Then .............................. => ctrl_0_value=3, ctrl_32_value=0

Percussion

  • To use the Drumset palette in Input mode, you must use a percussion sound.
  • <drumset>1</drumset> is equal to Ticking the Drumset checkbox in the Mixer
  • Percussion sound has a keyboard layout that's different from other instruments: each note represent a different sound sample. I think its from Percussion layout in GM
  • <Drum pitch=n> defines the sound sample is represented by that pitch/note and its appearance eg notehead etc
  • Musescore default xml use default soundfont's Bank 128 for percussion and different Preset for different taste. Bank128 of 1st soundfont == ctrl_0_value=1, ctrl_32_value=0.
  • You are not restricted to use 128, any bank number will work if <channel> points to the correct sound and <drumset>1</drumset>.

Why messy ctrl_0_value and ctrl_32_value?

I don't know the source code but I suppose there're some typo and miscalculation originated from the data storage limit of ctrl_32_value. My guess is, they are designed from the start and supposed to represent something each, independently , ie the soundfont number(ctrl_0_value) and bank number(ctrl_32_value) because common sense would lead to such design. But then it turned out the custom xml feature didn't get enough attention, and with public expectation for better sound quality and other reasons, developers make decision to throw away the current system at a certain point and stop fixing those.

Do you still have an unanswered question? Please log in first to post your question.