A SoundFont is a RIFF file of form sfbk: three LIST chunks, in order. INFO holds the metadata (name, author, version). sdta holds one smpl chunk, every sample's audio back to back. pdta holds the preset/instrument/sample structure, ending in shdr, a table of 46-byte sample headers that name each sample and give its start and end index into smpl. Extracting a sample is a carve of that byte range. SF3 (MuseScore) keeps this exact layout but stores each sample as an Ogg-Vorbis stream inside smpl, marked by sample-type bit 0x10, with the shdr start/end fields repurposed as byte offsets. The record drawn below is a real shdr entry, sample "tu 13" from a library SF2. Hover any field to light its bytes and read the decode; click a field with a + to open its table. Color marks kind (see the key).
Top to bottom, what a reader walks. It is a plain RIFF tree; nothing is compressed at the container level (SF2), so the whole structure is reachable by chunk-hopping.
The outer wrapper: 'RIFF', a u32 little-endian size (file length minus 8), then the form type 'sfbk'. Everything else is a child chunk of this container.
RIFF, so little-endian throughout -- the opposite of its IFF ancestor.
The catalog fields, one sub-chunk each. ifil is the SoundFont spec version (2.x for SF2, 3.x for SF3). The rest are free text.
Two numbers that decide whether the samples are PCM or Vorbis.
Every INFO string is NUL-terminated and padded to an even length.
One smpl chunk holding every sample concatenated. In SF2 this is 16-bit signed PCM, little-endian; a sample is the slice smpl[start*2 : end*2]. In SF3 it is a run of Ogg-Vorbis streams; a sample is smpl[start : end], a self-contained .ogg.
The presets: what a MIDI program change actually selects. Each record is 38 bytes -- a 20-byte name, the program and bank it answers to, an index into pbag, and three fields the spec reserves and every writer leaves zero. A terminal record named EOP ends the table, and it exists to close the last real preset's zone span rather than to describe a preset.
Bank 128 is percussion. There the program number selects a drum kit rather than an instrument, so the same two bytes mean different things depending on the bank beside them.
The instruments, which are what presets actually play. Twenty bytes of name and one index into ibag -- the shortest record in the format, because an instrument is almost entirely defined by the zones hanging off it. A terminal EOI record closes the last one.
Generators are how a zone says anything at all. Each is four bytes: a 16-bit operator naming the parameter, and a 16-bit amount whose meaning depends entirely on that operator. Two of them decide what a zone plays -- 43 is the key range and 53 is the sample index -- and by the spec's rule a zone's sampleID must be its LAST generator.
The key range packs two values into one 16-bit amount: low key in the low byte, high key in the high byte. Read it as a single number and a zone covering notes 0 to 60 becomes a zone at key 15,360, which is not a key.
The sample headers. Each record is exactly 46 bytes: a 20-byte name, five u32 indices into smpl (start, end, loop start, loop end, sample rate), then the original pitch, a correction, a stereo link, and a type. A terminal record named "EOS" marks the end of the table. The record below is the real first entry of a library SF2.
The INFO metadata, the smpl blob size, and every shdr record -- each turned into a chunk carrying its real byte offset, so samples are carveable and hex-viewable, and convert lifts them all out. Above those, the preset and instrument tables resolve into the tree they describe: which bank and program each preset answers to, the instruments its zones reach, and the key range each instrument zone maps to a sample. Those are rows and cross-references rather than byte ranges, so they carry no offset.