Skip to content

Repository files navigation

Samplotron

Hardware WAV Sampler

Build Main Firmware

Samplotron is a standalone hardware sampler played with an external MIDI controller or its built-in 16-key pad. Load your own WAV files from an SD card, assign sounds to notes, and play one-shots or loops with per-sample volume control. Two encoders and an OLED display let you browse, preview, assign, and save sounds directly on the device.

Open the interactive build guide — build your own Samplotron in 21 steps

Explore the interactive build guide → Follow animated wiring diagrams and firmware screen demonstrations, from connecting your first component to playing samples. Pause, replay and build at your own pace.

Watch Samplotron in action

Watch Samplotron in action — play the video on YouTube

For a walkthrough with screen photos, see the musician's manual. Firmware binaries are available in the latest main release.

Technical Details

Samplotron uses an ESP32 with PSRAM, built with the esp-wrover-kit PlatformIO board configuration, and an ES8388 audio codec. It plays mono PCM16 WAV files at 44.1 kHz through a shared 32-voice engine. Short assigned samples can be preloaded into RAM; longer samples stream from SD.

Controls

The front panel uses two rotary encoders with push buttons and a 4×4 matrix keypad:

Screen / control Action Effect
Main / left encoder Rotate Select LIB, VOL, SHOT/LOOP, or SAVE.
Main / right button on LIB Click Open the sample library.
Main / right encoder on VOL Rotate Set the last triggered or previewed sample's volume from 0 to 100, in steps of 5, for subsequent triggers.
Main / right encoder on SHOT/LOOP Rotate or click Toggle the sample's playback mode. Switching to SHOT also fades out its running loops.
Main / right button on SAVE Click Save the setup to SD.
Main / left button Click Show the output waveform; use either encoder or button to return.
Library / right encoder Rotate Browse samples.
Library / right button Click Preview the selected sample.
Library / right button Hold for 700 ms Learn a note for the selected sample or panic function.
Library / left encoder Rotate Switch between sample assignment and PANIC MODE.
Library or note assignment / left button Click Return to the previous screen.
Keypad Press a key Trigger its assigned sample, or supply a note while learning an assignment.

VOL and SHOT/LOOP appear after a sample has been triggered or previewed. SAVE appears when there are unsaved changes. One sample can be assigned to only one note at a time; learning a new note removes its previous assignment.

MIDI and keypad behavior

External MIDI Note On messages with nonzero velocity trigger samples on any MIDI channel. Playback level comes from the sample's VOL setting; MIDI velocity does not change loudness. Note Off, sustain, pitch bend, and MIDI clock do not control playback.

The keypad sends notes 36..51 in the measured physical key order and uses the same assignments as MIDI IN. Hold the right button in LIB, then press a keypad key or play a MIDI note to assign the selected sample. Holding a keypad key does not repeat it, and releasing a key does not stop playback.

SHOT plays the sample once. LOOP repeats it until stopped; another press retriggers it from the beginning. Change the sample to SHOT to stop its loops, or use the learned panic note to fade out all voices and clear pending triggers. To assign panic, select PANIC MODE with the left encoder in LIB, hold the right button, and send the desired note.

How playback works

At startup, the firmware scans /samples, loads saved assignments, and prepares eligible samples in RAM. Preloading is limited to supported files no longer than 5 seconds that fit within the configured RAM budget (1 MiB by default). Other supported files stream from SD; failed preloads fall back to streaming. Missing or unsupported files are marked unavailable when assignments are prepared.

Each trigger starts a voice. Retriggering the same sample fades out its older voices, and if all 32 slots are occupied, the oldest voice is replaced. RAM and SD playback use the same decoder and mixer, with float summation and a look-ahead peak limiter before PCM16 conversion. Each voice has a short 35-frame (about 0.8 ms) ramp at the file boundaries. Outside these ramps, a single voice at VOL=100 keeps its original digital level; overlapping voices are attenuated when their sum would exceed full scale. The audio task runs on core 1; the UI and sample loader run on core 0 and communicate with it through queues.

Saving stores assignments, assigned sample volumes, playback modes, and the panic note in /sampler_config.json, and refreshes RAM preparation. Save between performances: the save process waits for playback to finish and can stop running loops before rebuilding the sample pool.

Hardware and connections

Component Connection
SD card over SPI CS GPIO13, MISO GPIO2, MOSI GPIO15, SCK GPIO14
ES8388 audio over I2S BCLK GPIO27, WS GPIO25, DOUT GPIO26; speaker amplifier enable GPIO21 held LOW (off)
ES8388 control bus SDA GPIO33, SCL GPIO32; address 0x10
SSD1309 OLED and MCP23017 shared I2C bus SDA GPIO23, SCL GPIO18; OLED 0x3C or 0x3D, MCP23017 0x27
Left encoder MCP23017 GPA0 / GPA1 / GPA2: A / B / switch
Right encoder MCP23017 GPA3 / GPA4 / GPA5: A / B / switch
4×4 keypad MCP23017 GPB0–GPB3: rows; GPB4–GPB7: columns
MIDI input GPIO22, Serial2, 31250 baud

Pin assignments are defined in include/pins.h; keypad note mapping is in include/keypad_mapping.h. The technical documentation includes interrupt pins, keypad scanning details, and hardware notes.

The audio output uses one headphones-out channel (mono) through a potentiometer wired as a voltage divider: one outer lug to the headphone signal, the other outer lug to ground, and the wiper to the output jack tip. Connect the jack sleeve to ground. At the headphone socket, use tip (L) or ring (R) relative to sleeve (ground), leaving the other channel unconnected. Both channels carry the same mono signal;

The output jack sleeve must be connected to both headphone output ground and the ESP32 GND pin. Bring all device-side grounds to one star point, but keep them electrically isolated from the enclosure. Do not connect ground to the enclosure, including through jack or potentiometer mounting hardware: this can introduce OLED interference into the audio output.

For normal operation, use the current build's dedicated power path: 9 V jack → step-down to 5 V → B0505S-3WR3 isolator → the AudioKit board's BAT connector. The builder recommends good-quality guitar-pedal supplies over USB power. USB is still used for firmware programming. See audio wiring, grounding and power for the divider connections and isolated ground routing.

The separate L/R speaker terminals carry a switching, speaker-level signal from bridge-tied Class-D amplifiers; neither terminal is ground. Use headphones out for the mixer connection. Firmware keeps the speaker amplifiers, line-in and microphone capture paths disabled.

Preparing samples and first use

  1. Prepare a FAT32 SD card and create a /samples directory at its root.
  2. Copy up to 32 WAV files into that directory. Use uncompressed PCM, 16-bit, 44.1 kHz, mono, with a .wav or .WAV extension. Subdirectories are not scanned; the loaded list is sorted by filename.
  3. Insert the card, power on, and wait for Ready.
  4. Open LIB, preview a sample, then hold the right button and send a MIDI note or press a keypad key to assign it.
  5. Trigger the sound, set VOL and SHOT/LOOP, then select SAVE before powering off.

During boot, every loaded library entry (up to 32, including unassigned samples) is checked for the supported WAV format and valid file structure. The display shows progress and the rejected count. Rejected entries remain visible in LIB with ! and a reason; they cannot play. Results are cached in RAM: restart after changing files on the SD card.

No configuration file is required for first boot; without one, the device starts with no assignments, one-shot playback, and the default RAM budget.

On Linux, install FFmpeg using your distribution's package manager (for example, sudo apt install ffmpeg on Debian/Ubuntu). Run this in Bash, setting samples_dir to the directory containing your WAV files:

samples_dir="/path/to/your samples"
(
    cd -- "$samples_dir" || exit 1
    mkdir -p -- samplotron || exit 1
    for file in *.[wW][aA][vV]; do
        [ -f "$file" ] || continue
        ffmpeg -nostdin -n -i "./$file" -map 0:a:0 -ac 1 -ar 44100 \
            -c:a pcm_s16le -map_metadata -1 "samplotron/${file%.*}.wav" || exit 1
    done
)

This converts WAV files directly in the selected directory to uncompressed PCM16, 44.1 kHz, mono. Originals are preserved; output goes into its samplotron subdirectory, ready to copy to /samples on the SD card. Existing output files are not overwritten. This command does not trim silence or normalize volume.

The repository also includes a batch conversion command, requiring ffmpeg and Make:

make convert-samples SAMPLES_DIR=/path/to/sample-copies

Run it on copies of your source recordings: it replaces WAV files in place, converts them to PCM16/44.1 kHz/mono, trims leading silence using a −45 dB threshold and 10 ms duration, and applies gain calculated for a −1 dBFS source peak target.

Configuration and diagnostics

Display orientation is configured by DisplayConfig::ROTATE_180 in include/display_config.h. It defaults to true (180° rotation); set it to false for the original orientation. Rebuild and upload the firmware after changing it. This applies to all screens in the main firmware and the input diagnostic firmware.

The on-device SAVE action writes /sampler_config.json. For manual configuration, including the RAM budget and panic note, see the configuration format. Changing the RAM budget requires a reboot.

The main firmware prints keypad initialization and key-press diagnostics at 115200 baud. Dedicated firmware environments are available for testing encoders and MIDI input:

make upload-debug
make upload-debug-midi
make monitor

Each upload replaces the firmware on the board. Restore normal operation with make upload-main.

Build and upload

Install PlatformIO CLI (pio) or the PlatformIO IDE extension, then run these commands from the project root:

pio run -e esp-wrover-kit
pio run -e esp-wrover-kit -t upload

With Make installed, the equivalents are make build-main and make upload-main. Dependencies and PSRAM settings are declared in platformio.ini.

To flash without building, download firmware.bin, bootloader.bin, partitions.bin, and boot_app0.bin from the same main-latest release, then follow the prebuilt firmware instructions.

Save failures appear on the OLED as compact codes such as SAVE E15. See save error codes for their meanings and diagnosis without a serial monitor.

Tests

Run the native tests without an ESP32 connected:

pio test -e native

make test runs the same command. The tests in test/ cover UI navigation, sample and panic assignment, keypad mapping, saving state, and routing playback requests to RAM or SD, including fallback and loop controls. The audio mixer regression tests exercise the production Samplotron mixer with a simulated output: unity solo playback, summation, 32 full-scale voices, linked limiting, look-ahead/release, backpressure, tail draining, idle silence and fade retries. Run it alone with pio test -e native -f test_audio_mixer. The full playback regression (pio test -e native -f test_audio_playback) also runs the production WAV decoder, voice engine, RAM/SD source adapters, fades and mixer; it checks simultaneous/staggered playback, 6 ms retriggers, nonzero endpoints and repeated slot reuse. The test_i2s_transport suite separately covers the ESP32 block writer and a continuously advancing simulated output clock. See audio regression coverage. Shared hardware stubs live in test/support/; audio timing, SD throughput, and physical wiring require checks on the device.

Code structure

The source is organized around application flow, playback, and hardware access:

See the technical documentation for the full module map, configuration schema, and tuning constants.

About

Samplotron is an ESP32 hardware sampler for musicians and producers: play WAVs from SD, map samples to MIDI notes, tweak per-sample volume and shot/loop mode, and save live-ready setups on device.

Topics

Resources

Stars

32 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages