REF / Music API / SampleMgr

Ascene . Agraph . Aengine
Anode . Modulator . Envelope
Songbook . Song . TimeKeeper
Voices . SampleMgr . StreamMgr
Loader . Async . Plot
Random . Rhythm . Util
MIDI . OSC . HID . Piano
Music Theory with Tonal

right-click to navigate to page sections


You use audio sample files to produce music.
You hunger for new, unusual samples for inspiration.
The internet has samples.

SampleMgr describes, collects and organizes your sample files. Use it to fill up your local drive with the samples you want rather than a random pile that come with music apps.

SampleMgr manages audio sample files and communicates their location to Hz.Samplo or other sample file consumer. SampleMgr supports asynchronous (background) downloading, caching and serving of network-based samples.

Samples are organized on concepts of repository, library, bank, and voice. We can think of a repository as equivalent to a github repository (repo) that obeys a standard directory structure. We currently support two file organizing schemes below a repository:

  1. repo/bank/voice, eg: MIDIJS/FatBoy/accordion
  2. repo/voice, eg: DrumKits/AkaiXR10
Concept Description
repo name+internet URL containing sample libraries or banks.
bank collection of voices
voice collection of sound files organized either by MIDI key or name (eg bd, hh)

Repo File

Since the internet is a big place, we introduce the repo file. This file is a list of your favorite repositories (their location and contents). It is used to map a lightweight reference to one or more URLs which, in turn, represent a key to our local cache. Hz ships with a default repo file, shown below. You can create your own repo file and TOC-files to suit your own tastes.

All this machinery is presented in order to make literally thousands of internet-hosted sample files easily accessible automatically and portably. Of course you have your own personal collection of sample files and these can be either be explicitly organized into your repo file or presented to SampleMgr directly in your songs.

SampleMgr API

Overview

For the common use-case where you knowc a bank and a voice, you only need a single method to ensure sample files are available on your computer as shown here:

let asamps = await SampleMgr.PreloadSamples("MIDIJS/FatBoy", "accordion");

Once complete, you'll find 88 sample files below your current workspace:

${WS}/_cache/github/paulrosen/midi-js-soundfonts/FatBoy/accordion-mp3

Next, to make these files known to Hz.Samplo:

await samplo.LoadPreset(asamps.AsPreset(), "MIDIJS/FatBoy_accordion"); 

You can find this complete example here.

SampleMgr
SampleMgr method Description
async Init(repolist?) Optional, returns a promise that resolves to an initialized SMgrRepolist. If filename isn't provided, the default is returned.
async PreloadSamples(bank, voice, repolist=null) Ensures that the bank+voice sample files are available in the local cache. Returns a promise that resolves to a Voice instance.
AsPresetFromLocalVoice(cwd, name, voicedata) Returns a Hz.Samplo preset that refers to a locally defined voice. voicedata is either an array or a dictionary.
GetRepolists() Returns an array of names of repolists.
GetRepolist(name) Returns the named SMgrRepoList.
SMgrRepolist
SMgrRepolist method Description
GetFile() Returns the filename associated with this repolist.
async Initialize() Ensures that all TOC files supporting the repo are loaded.
GetBankNames() Returns a list of bank names known to the repo.
GetBank(name) Returns a SMgrBank for the named repo bank.
SMgrBank
SMgrBank method Description
GetName() returns the bank name.
GetVoiceNames() returns the list of voices present in the bank.
GetVoice(name) returns the SMgrVoice for the voicename in the bank.
SMgrVoice
SMgrVoice method Description
AsPreset() returns a HzSamplePlayer preset that refers to a locally cached voice files.
GetName() returns the voice's name
GetBank() returns the voice's bank name
IsPercussive() returns true if the voice is percussive
IsTonal() returns true if the voice is tonal
GetCategory() returns either "tonal" or "percussive"
GetURLs() returns an array of local sample file references
GetNumPercSamps() returns 0 or the size of the samples array
GetNumTonalSamps() returns 0 or the number of entries in the samples object
GetURLForNote(note) returns [fileref, transpose]
GetURLForIndex(i) returns fileref at i

Examples

See here for an example.

Repo File

The repo file is a JSON formatted dictionary that maps a repo name to a repo TOC (table of contents) file. When you request samples for VCSL/handchimes, we first locate the repo named VCSL in the repolist, then find handchimes in its TOC. There we'll find an enumeration of the voice sample files.

{
    "Dirt": {
        "URL": "https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master",
        "TOC": "tocs/dirt-samples.json",
        "CacheDir":  "github/tidalcycles/Dirt-Samples"
    },
    "Strudel": {
        "URL": "https://raw.githubusercontent.com/tidalcycles/strudel/main/website/public",
        "TOC": "tocs/strudel.json",
        "CacheDir":  "github/tidalcycles/strudel"
    },
    "DrumKits": {
        "URL": "https://raw.githubusercontent.com/ritchse/tidal-drum-machines/main/machines",
        "TOC": "tocs/tidal-drum-machines.json",
        "CacheDir":  "github/ritchse/tidal-drum-machines",
        "Multibank": 1
    },
    "VCSL": {
        "URL": "https://raw.githubusercontent.com/sgossner/VCSL/master",
        "TOC": "tocs/vcsl.json",
        "CacheDir":  "github/sgossner/VCSL"
    },
    "midi-js-soundfonts": {
        "URL": "https://raw.githubusercontent.com/paulrosen/midi-js-soundfonts/master",
        "TOC": "tocs/midi-js-soundfonts.json",
        "CacheDir":  "github/paulrosen/midi-js-soundfonts",
        "Multibank": 1,
        "LICENSE": "MIT, Copyright (C) 2012 Benjamin Gleitzman (gleitz@mit.edu)"
    },
    "loophole": {
        "URL": "https://loophole-letters.vercel.app/samples",
        "TOC": "tocs/loophole.json",
        "CacheDir":  "loophole-letters.vercel.app/samples"
    }
}

Repo TOC File

The Repo TOC file is a JSON formatted dictionary that maps voice names to their collection of sample files. Here's a portion of the VCSL TOC file. We've selected this subset because it shows the difference between tonal and percussive voices. The first is a dictionary whose keys are note-names and percussion voice are an array indexed by a voice variation/index. In both cases the value of each entry is a relative pathname to a sample file.

{
  "handchimes": {
    "A#3": "Idiophones/Struck Idiophones/Hand Chimes/sus_A#3_r01_main.wav",
    "A#5": "Idiophones/Struck Idiophones/Hand Chimes/sus_A#5_r01_main.wav",
    "A4": "Idiophones/Struck Idiophones/Hand Chimes/sus_A4_r01_main.wav",
    "C3": "Idiophones/Struck Idiophones/Hand Chimes/sus_C3_r01_main.wav",
    "C4": "Idiophones/Struck Idiophones/Hand Chimes/sus_C4_r01_main.wav",
    "C5": "Idiophones/Struck Idiophones/Hand Chimes/sus_C5_r01_main.wav",
    "C6": "Idiophones/Struck Idiophones/Hand Chimes/sus_C6_r01_main.wav",
    "D3": "Idiophones/Struck Idiophones/Hand Chimes/sus_D3_r01_main.wav",
    "D4": "Idiophones/Struck Idiophones/Hand Chimes/sus_D4_r01_main.wav",
    "D5": "Idiophones/Struck Idiophones/Hand Chimes/sus_D5_r01_main.wav",
    "E3": "Idiophones/Struck Idiophones/Hand Chimes/sus_E3_r01_main.wav",
    "E4": "Idiophones/Struck Idiophones/Hand Chimes/sus_E4_r01_main.wav",
    "E5": "Idiophones/Struck Idiophones/Hand Chimes/sus_E5_r01_main.wav",
    "F#3": "Idiophones/Struck Idiophones/Hand Chimes/sus_F#3_r01_main.wav",
    "F#4": "Idiophones/Struck Idiophones/Hand Chimes/sus_F#4_r01_main.wav",
    "F#5": "Idiophones/Struck Idiophones/Hand Chimes/sus_F#5_r01_main.wav",
    "G#3": "Idiophones/Struck Idiophones/Hand Chimes/sus_G#3_r01_main.wav",
    "G#4": "Idiophones/Struck Idiophones/Hand Chimes/sus_G#4_r01_main.wav",
    "G#5": "Idiophones/Struck Idiophones/Hand Chimes/sus_G#5_r01_main.wav"
  },
  "hihat": [
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_Close_rr1_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_Close_rr2_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitC_v1_rr1_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitC_v1_rr2_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitC_v2_rr1_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitC_v2_rr2_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitC_v3_rr1_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitC_v3_rr2_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitC_v4_rr1_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitC_v4_rr2_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitLoose_rr1_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitLoose_rr2_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitOC_rr5_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitO_rr1_Mid.wav",
    "Idiophones/Struck Idiophones/Hi-Hat Cymbal/HiHat_HitO_rr2_Mid.wav"
  ],
 }

Credits

SampleMgr was inspired by the sample-handling in Strudel.

home .. topics .. interface .. reference .. examples .. tipjar