- Looping: Samples can have loop points set, and one of the three loop modes can be engaged: FORWARD, SUSTAIN and PINGPONG.
- Effects: Audio effects are included, but not calibrated yet.
- GUI: Simple menu to have access to the basic features: sample set selection, effects and volume.
!Attention! ESP Arduino cores v.3.1.2 and 3.1.3 have some bug that won't allow i2s driver to install when PSRAM is enabled, please, avoid using these versions!
ESP32 SD Sampler is a polyphonic music synthesizer, which can play PCM WAV samples directly from an SD (microSD) card connected to an ESP32-S3 or ESP32-P4. Simple: one directory = one sample set. Plain text "sampler.ini" manages how samples to be spread over the keyboard. The main difference, comparing to the projects available on the net, is that this sampler WON'T try to preload all the stuff into the RAM/PSRAM to play it on demand. So it's not limited in this way by the size of the memory chip and can take really huge (per-note true sampled multi-velocity several gigabytes) sample sets. It only requires that the card is freshly formatted FAT32 and has no or very few bad blocks (actually it requires that the WAV files are written with little or no fragmentation at all). On start it analyzes existing file allocation table (FAT) and forms it's own sample lookup table to be able to access data immediately, using SDMMC with a 4-bit wide bus.
- Easy to build and to customize Arduino code for ESP32S3/ESP32P4
- Hardware would cost you about $15, including a microSD card
- Audio output is 44100Hz 16bit stereo
- Direct read-only access to the sample sets on an SD/microSD card: it's based on custom sdmmc routines and it's fast
- Size of a sample set is only limited by the card size
- Polyphony of 15-20 stereo voices depending on your MCU and card's specs
- 16/24 bit WAV files supported
- Melodic and percussive sample sets supported
- ADSR envelope, per-note configurable
- Built-in Reverb FX
- MIDI control currently supports the following messages:
- Note On
- Note Off
- Sustain (CC64)
- Pitchbend
- Attack time (CC73)
- Release time (CC72)
- Decay time (CC75)
- Sustain level (CC76)
- Reverb time (CC87)
- Reverb level (CC88)
- Reverb send (CC91)
- Human readable SAMPLER.INI controls initial parameters of a sample set globally, per-range and per-note
- You need
Arduino IDEinstalled - Next is
ESP32 Arduino core - Libraries required are:
Fixed string libraryhttps://github.com/fatlab101/FixedStringArduino MIDI libraryhttps://github.com/FortySevenEffects/arduino_midi_library- [optionally] If you want to use RGB LEDs, then also
FastLED libraryis needed https://github.com/FastLED/FastLED
- Download the zipped code or use git commands to get the project files
- Unpack and place
ESP32_SD_Samplerfolder to your Arduino projects directory - Open
ESP32_SD_Sampler.inofile with Arduino IDE - Connect your board via USB to your computer, select the corresponding
portin theToolsmenu and press theUploadbutton in the Arduino IDE
Absolutely not possible
With a freshly formatted good microSD, all effects set to THRU, it's about 17 stereo voices on S3 and 25 on P4.
There are currently 16 velocity layers (i.e. dynamic variants of each sampled note) which corresponds to the maximum count that I have found (https://freepats.zenvoid.org/Piano/acoustic-grand-piano.html).
One should put the sampler.ini file to the same folder where the corresponding WAV files are stored.
Ini syntax is described here: https://github.com/copych/ESP32_S3_Sampler/blob/main/sampler_ini_syntax.md the doc is under development and will be improved.
Here is an example of a sampler.ini file for the Salamander Grand Piano WAV-set:
[sampleset]
title = Salamander Grand Piano
; type=percussive/melodic
type=melodic
; Are all the samples of equal loudness? If true then we apply amplification according to the midi note velocity.
normalized=true
; Overall Amplification
amplify = 1.2
; ADSR times in seconds
attackTime = 0.0
decayTime = 12.0
releaseTime = 0.1
; ADSR sustain level 0.0 - 1.0
sustainLevel = 0.0
# !!!!!!!!!!!!!!! "enveloped=bool" is no longer supported, as the ADSR is always applyed
# !!!!!!!!!!!!!!! [envelope] section is no longer supported, [sampleset] now holds global settings
[filename]
# Filename elements recognized:
; <NAME> - note name in sharp (#) or flat(b) notation, i.e. both Eb and D# are valid
; <OCTAVE> - octave number
; <MIDINOTE> - sometimes sample file name contains midi note number
; <NUMBER> - parsed, but not used for now: i.e. some numbers initially used for naming, sorting or whatever
; <VELO> velocity layer
; <INSTR> instruments names (mostly percussion) used in filenames, initially they are collected from this ini file
; elements without brackets will be treated as some constant string delimeters
; these elements are case insensitive, heading and trailing spaces are trimmed.
template=<NAME><OCTAVE>v<VELO>
; we must provide these variants along with the template. The order is important: from the most quiet
; to the most loud, comma separated
veloVariants = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
; in addition we can provide optional info on how velocity layers shall be spread over
; the whole range of 0-127, giving the upper limits of each range
veloLimits = 26,34,36,43,46,50,56,64,72,80,88,96,104,112,121,127
[range]
# notes without dampers
first = F#6
last = G8
noteoff = false
# [note] sections
; instr=instrument_name(as in filename)
; noteoff=0/1 (0=ignore, 1=end note)
; speed=float_number(1.0 means unchanged (default), 1.2 means 20% faster which is higher pitch, 0.9 is 10% lower)
another sampler.ini example is for a drumkit MuldjordKit-SFZ-20201018, all the samples moved to a single folder
[sampleset]
title = Generic Drum Kit
; type=percussive/melodic
; different technics used while spreading samples over the clavier
; percussive type allows per-note fx-send level
type=percussive
; Are all the samples of equal loudness? If true then we apply amplification according to the midi note velocity.
normalized=true
; ADSR times in seconds
attackTime = 0.0
decayTime = 0.05
releaseTime = 0.2
; ADSR sustain level 0.0 - 1.0
sustainLevel = 1.0
# !!!!!!!!!!!!!!! "enveloped=bool" is no longer supported, as the ADSR is always applyed
# !!!!!!!!!!!!!!! [envelope] section is no longer supported, [sampleset] now holds global settings
[filename]
# Filename elements recognized:
; <NAME> - note name=name in sharp (#) or flat(b) notation, i.e. both Eb and D# are valid
; <OCTAVE> - octave number
; <MIDINOTE> - sometimes sample file name contains midi note number
; <NUMBER> - parsed, but not used for now: i.e. some numbers initially used for naming, sorting or whatever
; <VELO> velocity layer
; <INSTR> instruments names (mostly percussion) used in filenames, initially they are collected from this ini file
; only instrument names mentioned in this ini (in [note] or [range] sections) will be recognized
; elements without brackets will be treated as some constant string delimeters
; these elements are case insensitive, heading and trailing spaces are trimmed.
; template should be specified first in this section
template=<VELO>-<INSTR>
; we must provide these variants. The order is important: from the most quiet to the most loud, comma separated
veloVariants = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
[group]
notes = F#1,A#1,G#1
notes = G#2,A2
notes = C#2,D2
# [note] sections
; name = notename in sharp (#) or flat(b) notation, i.e. both Eb and D# are valid
; instr = instrument_name(as in filename)
; noteoff = 0/1 (0 is 'ignore', 1 is 'end note'), also yes/no, true/false are recognized
; speed = float_number (1.0 means unchanged (default), 1.2 means 20% faster which is higher pitch, 0.9 is 10% lower)
; only instrument names mentioned in this ini (in [note] or [range] sections) will be recognized
[note]
name=b0
instr=kdrumL
noteoff=false
[note]
name=c1
instr=kdrumR
noteoff=no
[note]
name=C#1
instr=SnareRest
noteoff=0
[note]
name=D1
instr=Snare
noteoff=yes
[note]
name=D#1
; assuming we have "#-SnareRest (2).WAV" files in the drumkit folder after copying all the files into a single dir.
instr=SnareRest (2)
noteoff=true
[note]
name=E1
; assuming we have "#-Snare (2).WAV" files in the drumkit folder after copying all the files into a single dir.
instr=snare (2)
noteoff=0
[note]
name=F1
instr=Tom1
noteoff=0
[note]
name=G1
instr=Tom2
noteoff=0
[note]
name=A1
instr=Tom3
noteoff=0
[note]
name=B1
instr=Tom4
noteoff=0
[note]
name=C2
instr=Tom4
noteoff=0
speed=1.15
[note]
name=F#1
instr=HiHatClosed
noteoff=0
[note]
name=A#1
instr=HiHatOpen
noteoff=1
[note]
name=C#2
instr=CrashL
noteoff=0
[note]
name=D2
instr=CrashL
noteoff=true
[note]
name=E2
instr=China
noteoff=0
[note]
name=G#2
instr=CrashR
noteoff=0
[note]
name=A2
instr=CrashR
noteoff=yes
[note]
name=D#2
instr=RideL
noteoff=0
[note]
name=B2
instr=RideR
noteoff=0
[note]
name=F2
instr=RideLBell
noteoff=0
[note]
name=A#2
instr=RideRBell
noteoff=0
