High-performance Python DSP toolkit built on C++ libraries via nanobind
Project description
nanodsp
High-performance Python DSP toolkit built on C++ libraries via nanobind. All processing uses float32 in a planar [channels, frames] layout with block-based APIs that accept and return AudioBuffer objects.
Backends
| Library | License | What it provides |
|---|---|---|
| signalsmith-dsp | MIT | Filters, FFT, delay, envelopes, spectral processing, rates, mix |
| DaisySP | MIT | Oscillators, effects, dynamics, drums, physical modeling, noise |
| STK | MIT | Physical modeling instruments, generators, filters, delays, effects |
| madronalib | MIT | FDN reverbs, resampling, generators, projections, windows |
| HISSTools Library | BSD-3 | Convolution, spectral processing, statistical analysis, windows |
| CHOC | ISC | FLAC codec (read/write) |
| GrainflowLib | MIT | Granular synthesis (grain collections, panning, recording, phasor) |
Requirements
- Python >= 3.10
- numpy
- C++17 compiler
- CMake >= 3.15
Install
pip install nanodsp
Or if you prefer to build from source (requires uv and cmake):
git clone https://github.com/shakfu/nanodsp.git
cd nanodsp
uv sync # install dependencies + build extension
uv run pytest # run tests
uv build # build wheel
Use make help for additional targets (build, test, lint, format, typecheck, qa, coverage, etc.).
CLI
nanodsp ships with a command-line interface accessible via nanodsp or python -m nanodsp.
# File info
nanodsp info drums.wav
nanodsp info drums.wav --json
# Process with effect chain (single file)
nanodsp process input.wav -o output.wav \
-f highpass:cutoff_hz=80 \
-f compress:ratio=4,threshold=-18 \
-f normalize_peak:target_db=-1
# Apply a preset
nanodsp process vocals.wav -o out.wav -p vocal_chain
nanodsp process input.wav -o out.wav -f lowpass:cutoff_hz=12000 -p master
# Batch mode -- process multiple files to a directory
nanodsp process *.wav -O out/ -f lowpass:cutoff_hz=2000
# Dry run -- show chain without reading/writing files
nanodsp process input.wav -n -f highpass:cutoff_hz=80 -f compress:ratio=4
# Verbose / quiet
nanodsp -v process input.wav -o out.wav -f lowpass:cutoff_hz=1000
nanodsp -q process input.wav -o out.wav -p master
# Analyze
nanodsp analyze input.wav loudness
nanodsp analyze input.wav pitch --fmin=80 --fmax=800
nanodsp analyze input.wav onsets --json
nanodsp analyze input.wav info
# Synthesize
nanodsp synth tone.wav sine --freq=440 --duration=2.0
nanodsp synth kick.wav drum --type=analog_bass_drum --freq=60
nanodsp synth melody.wav note --instrument=clarinet --freq=440 --duration=1.0
nanodsp synth seq.wav sequence --instrument=flute \
--notes='[{"freq":440,"start":0,"dur":0.5},{"freq":554,"start":0.5,"dur":0.5}]'
# Convert
nanodsp convert input.wav output.flac
nanodsp convert input.wav output.wav --sample-rate=44100 --channels=1 -b 24
# Presets
nanodsp preset list
nanodsp preset list spatial
nanodsp preset info master
nanodsp preset apply master input.wav output.wav target_lufs=-16
# Pipe (stdin/stdout streaming)
cat input.wav | nanodsp pipe -f lowpass:cutoff_hz=1000 > output.wav
cat input.wav | nanodsp pipe -p telephone > output.wav
nanodsp pipe -f highpass:cutoff_hz=80 < in.wav | nanodsp pipe -f compress:ratio=4 > out.wav
# Benchmark
nanodsp benchmark lowpass:cutoff_hz=1000
nanodsp benchmark compress:ratio=4,threshold=-20 -n 100 --duration=2.0
nanodsp benchmark reverb:preset=hall --channels=2 --json
# List available functions
nanodsp list
nanodsp list filters
nanodsp list effects
Presets
30 built-in presets across 8 categories:
| Category | Presets |
|---|---|
| mastering | master, master_pop, master_hiphop, master_classical, master_edm, master_podcast |
| voice | vocal_chain |
| spatial | room, hall, plate, cathedral, chamber |
| dynamics | gentle_compress, heavy_compress, brick_wall |
| creative | radio, underwater, megaphone, tape_warmth, shimmer, vaporwave, walkie_talkie |
| lofi | telephone, lo_fi, vinyl, 8bit |
| cleanup | dc_remove, de_noise, normalize, normalize_lufs |
Quick start
from nanodsp.buffer import AudioBuffer
from nanodsp import effects, analysis
# Read, process, write
buf = (
AudioBuffer.from_file("input.wav")
.pipe(effects.highpass, freq=80.0)
.pipe(effects.compress, threshold=-18.0, ratio=4.0)
.pipe(analysis.normalize_lufs, target_lufs=-14.0)
)
buf.write("output.wav")
Modules
nanodsp.buffer -- AudioBuffer
The central data type. A 2D float32 array with shape [channels, frames] plus metadata (sample_rate, channel_layout, label).
from nanodsp.buffer import AudioBuffer
# Construction
buf = AudioBuffer(np.zeros((2, 44100), dtype=np.float32), sample_rate=44100)
buf = AudioBuffer.from_file("input.wav") # read WAV/FLAC
buf = AudioBuffer.sine(440.0, channels=1, frames=44100, sample_rate=44100)
buf = AudioBuffer.noise(channels=2, frames=44100, sample_rate=44100)
buf = AudioBuffer.zeros(channels=1, frames=1024, sample_rate=44100)
buf = AudioBuffer.impulse(channels=1, frames=1024, sample_rate=44100)
# Properties
buf.channels # number of channels
buf.frames # number of frames
buf.sample_rate # sample rate in Hz
buf.duration # duration in seconds
buf.mono # 1D view (mono buffers only)
buf.channel(0) # 1D view of channel 0
# Channel operations
buf.to_mono("mean") # downmix
buf.to_channels(2) # upmix mono to stereo
AudioBuffer.concat_channels(a, b) # stack channels
# Arithmetic
buf + other # add
buf * 0.5 # scale
buf.gain_db(-6.0) # apply dB gain
# I/O
buf.write("output.wav") # write WAV/FLAC (detected by extension)
buf.write("output.flac", bit_depth=24)
# Pipeline
buf.pipe(effects.lowpass, freq=1000.0)
nanodsp.io -- Audio file I/O
Read and write WAV (8/16/24/32-bit PCM) and FLAC (16/24-bit) files. Zero external dependencies for WAV (uses stdlib wave); FLAC uses the CHOC codec.
from nanodsp import io
buf = io.read("file.wav") # auto-detect by extension
buf = io.read("file.flac")
io.write("out.wav", buf) # 16-bit default
io.write("out.flac", buf, bit_depth=24)
# Format-specific
buf = io.read_wav("file.wav")
io.write_wav("out.wav", buf, bit_depth=24)
buf = io.read_flac("file.flac")
io.write_flac("out.flac", buf, bit_depth=16)
# Byte-level (for stdin/stdout/pipe workflows)
buf = io.read_wav_bytes(raw_bytes) # parse WAV from bytes
raw = io.write_wav_bytes(buf, bit_depth=16) # serialize to WAV bytes
nanodsp.ops -- Core DSP operations
Low-level building blocks: delay, envelopes, FFT, convolution, sample rates, mixing, panning, normalization, cross-correlation, Hilbert transform, median filter, LMS adaptive filter.
from nanodsp import ops
# Delay
ops.delay(buf, delay_samples=100)
ops.delay_varying(buf, delays=delay_curve)
# Envelopes
ops.box_filter(buf, length=64)
ops.box_stack_filter(buf, size=32, layers=4)
ops.peak_hold(buf, length=128)
ops.peak_decay(buf, length=256)
# FFT
spectra = ops.rfft(buf) # forward real FFT
buf = ops.irfft(spectra, size=1024, sample_rate=44100) # inverse
# Convolution
ops.convolve(buf, ir, normalize=True)
# Sample rates
ops.upsample_2x(buf)
ops.oversample_roundtrip(buf)
# Mixing
ops.hadamard(buf) # Hadamard matrix mixing
ops.householder(buf) # Householder reflection
ops.crossfade(buf_a, buf_b, x=0.5)
ops.mix_buffers(a, b, c, gains=[1.0, 0.5, 0.8])
# LFO
lfo_signal = ops.lfo(frames=44100, low=0.0, high=1.0, rate=2.0)
# Normalization
ops.normalize_peak(buf, target_db=-1.0)
ops.trim_silence(buf, threshold_db=-60.0)
# Fades
ops.fade_in(buf, duration_ms=10.0)
ops.fade_out(buf, duration_ms=50.0, curve="exp")
# Panning and stereo
ops.pan(buf, position=0.3) # equal-power pan
ops.mid_side_encode(buf)
ops.mid_side_decode(buf)
ops.stereo_widen(buf, width=1.5)
# Cross-correlation
corr = ops.xcorr(buf_a, buf_b) # cross-correlation
auto = ops.xcorr(buf) # autocorrelation
# Hilbert / envelope
env = ops.hilbert(buf) # analytic signal envelope
env = ops.envelope(buf) # alias for hilbert
# Median filter
ops.median_filter(buf, kernel_size=5)
# LMS adaptive filter
output, error = ops.lms_filter(buf, ref, filter_len=32, step_size=0.01)
nanodsp.effects -- Filters, effects, dynamics, mastering
53 functions covering signalsmith biquad filters, DaisySP effects/filters/dynamics, composed effects, reverbs, mastering chains, STK effects, and automatic gain control.
Biquad filters (signalsmith)
All filter functions take freq in Hz, auto-converted to normalized frequency.
from nanodsp import effects
effects.lowpass(buf, freq=1000.0, q=0.707)
effects.highpass(buf, freq=80.0)
effects.bandpass(buf, freq=1000.0, q=2.0)
effects.notch(buf, freq=50.0)
effects.peak(buf, freq=1000.0, gain=2.0, q=1.0)
effects.peak_db(buf, freq=1000.0, db=6.0)
effects.high_shelf(buf, freq=8000.0, gain=1.5)
effects.high_shelf_db(buf, freq=8000.0, db=3.0)
effects.low_shelf(buf, freq=200.0, gain=0.8)
effects.low_shelf_db(buf, freq=200.0, db=-2.0)
effects.allpass(buf, freq=1000.0)
DaisySP effects
effects.autowah(buf, wah=0.5)
effects.chorus(buf, rate=1.0, depth=0.5)
effects.decimator(buf, downsample_factor=0.5, bitcrush_factor=0.5)
effects.flanger(buf, rate=0.2, depth=0.5, feedback=0.5)
effects.overdrive(buf, drive=0.7)
effects.phaser(buf, rate=0.3, depth=0.5, feedback=0.5)
effects.pitch_shift(buf, semitones=12.0)
effects.sample_rate_reduce(buf, factor=0.5)
effects.tremolo(buf, rate=5.0, depth=0.8)
effects.wavefold(buf, gain=2.0)
effects.bitcrush(buf, bits=8)
effects.fold(buf, gain=2.0)
effects.reverb_sc(buf, feedback=0.8, lpfreq=10000.0)
effects.dc_block(buf)
DaisySP filters
effects.svf_lowpass(buf, freq=1000.0, res=0.5)
effects.svf_highpass(buf, freq=200.0, res=0.5)
effects.svf_bandpass(buf, freq=1000.0, res=0.7)
effects.svf_notch(buf, freq=1000.0, res=0.5)
effects.svf_peak(buf, freq=1000.0, res=0.8)
effects.ladder_filter(buf, freq=800.0, res=0.6, mode="lp24")
effects.moog_ladder(buf, freq=1000.0, res=0.7)
effects.tone_lowpass(buf, freq=2000.0)
effects.tone_highpass(buf, freq=100.0)
effects.modal_bandpass(buf, freq=440.0, q=50.0)
effects.comb_filter(buf, freq=500.0, revtime=0.5)
Dynamics
effects.compress(buf, threshold=-20.0, ratio=4.0, attack=0.01, release=0.1)
effects.limit(buf, threshold=-1.0)
Composed effects
effects.saturate(buf, drive=0.7, mode="soft") # soft, hard, or tape
effects.exciter(buf, freq=3000.0, drive=0.4)
effects.de_esser(buf, freq=6000.0, threshold=-20.0)
effects.parallel_compress(buf, mix=0.5, threshold=-24.0, ratio=8.0)
effects.noise_gate(buf, threshold_db=-40.0)
effects.stereo_delay(buf, delay_l=0.25, delay_r=0.375, feedback=0.4, ping_pong=True)
effects.multiband_compress(buf, crossovers=[200.0, 2000.0, 8000.0])
Reverb
effects.reverb(buf, preset="hall", decay=2.0, mix=0.3)
# Presets: room, hall, plate, chamber, cathedral
Mastering and vocal chains
effects.master(buf, target_lufs=-14.0)
effects.vocal_chain(buf, de_ess_freq=6000.0, comp_threshold=-18.0)
STK effects
effects.stk_reverb(buf, algorithm="freeverb", decay=1.5, mix=0.3)
effects.stk_chorus(buf, mod_depth=0.02, mod_freq=1.0, mix=0.5)
effects.stk_echo(buf, delay=0.25, max_delay=1.0, mix=0.5)
Automatic gain control
effects.agc(buf, target_level=1.0, max_gain_db=60.0, average_len=100, attack=0.01, release=0.01)
nanodsp.spectral -- STFT and spectral processing
Short-time Fourier transform, spectral utilities, and spectral transforms.
from nanodsp import spectral
# STFT
spec = spectral.stft(buf, window_size=2048, hop_size=512)
buf = spectral.istft(spec)
# Spectral utilities
mag = spectral.magnitude(spec)
ph = spectral.phase(spec)
spec = spectral.from_polar(mag, ph)
spec = spectral.apply_mask(spec, mask)
spec = spectral.spectral_gate(spec, threshold_db=-40.0)
spec = spectral.spectral_emphasis(spec, low_db=-3.0, high_db=3.0)
freq = spectral.bin_freq(bin_index=10, fft_size=2048, sample_rate=44100)
b = spectral.freq_to_bin(freq=1000.0, fft_size=2048, sample_rate=44100)
# Spectral transforms
stretched = spectral.time_stretch(buf, rate=0.5) # half speed
locked = spectral.phase_lock(spec) # identity phase-locking
frozen = spectral.spectral_freeze(buf, frame_index=10) # frozen texture
morphed = spectral.spectral_morph(spec_a, spec_b, x=0.5)
shifted = spectral.pitch_shift_spectral(buf, semitones=5.0)
denoised = spectral.spectral_denoise(buf, noise_frames=10)
# EQ matching
matched = spectral.eq_match(source_buf, target_buf, strength=1.0)
nanodsp.synthesis -- Oscillators, noise, drums, physical modeling
Sound generators using DaisySP and STK backends.
from nanodsp import synthesis
# Oscillators
synthesis.oscillator(freq=440.0, waveform="saw", frames=44100)
synthesis.fm2(freq=440.0, ratio=2.0, index=1.0, frames=44100)
synthesis.formant_oscillator(freq=440.0, formant_freq=800.0, frames=44100)
synthesis.bl_oscillator(freq=440.0, waveform="saw", frames=44100)
# Noise
synthesis.white_noise(frames=44100, amp=0.5)
synthesis.clocked_noise(freq=1000.0, frames=44100)
synthesis.dust(density=100.0, frames=44100)
# Drums
synthesis.analog_bass_drum(freq=60.0, frames=44100)
synthesis.analog_snare_drum(freq=200.0, frames=44100)
synthesis.hihat(freq=3000.0, frames=44100)
synthesis.synthetic_bass_drum(freq=60.0, frames=44100)
synthesis.synthetic_snare_drum(freq=200.0, frames=44100)
# Physical modeling
synthesis.karplus_strong(buf, freq=440.0, brightness=0.5, damping=0.5)
synthesis.modal_voice(freq=440.0, frames=44100)
synthesis.string_voice(freq=440.0, frames=44100)
synthesis.pluck(freq=440.0, frames=44100)
synthesis.drip(freq=1000.0, frames=44100)
# STK synthesis
synthesis.synth_note("clarinet", freq=440.0, amplitude=0.8, duration=1.0)
synthesis.synth_sequence("flute", notes=[
{"freq": 440.0, "amp": 0.8, "start": 0.0, "dur": 0.5},
{"freq": 554.37, "amp": 0.7, "start": 0.5, "dur": 0.5},
])
Available STK instruments: clarinet, flute, brass, bowed, plucked, sitar, stifkarp, saxofony, recorder, blowbotl, blowhole, whistle.
nanodsp.analysis -- Loudness, spectral features, pitch, onsets, resampling
from nanodsp import analysis
# Loudness (ITU-R BS.1770-4)
lufs = analysis.loudness_lufs(buf)
buf = analysis.normalize_lufs(buf, target_lufs=-14.0)
# Spectral features
centroid = analysis.spectral_centroid(buf)
bandwidth = analysis.spectral_bandwidth(buf)
rolloff = analysis.spectral_rolloff(buf, percentile=0.85)
flux = analysis.spectral_flux(buf, rectify=True)
flatness = analysis.spectral_flatness_curve(buf)
chroma = analysis.chromagram(buf, n_chroma=12, tuning_hz=440.0)
# Pitch detection (YIN algorithm)
f0, confidence = analysis.pitch_detect(buf, method="yin", fmin=50.0, fmax=2000.0)
# Onset detection
onsets = analysis.onset_detect(buf, method="spectral_flux", threshold=0.5)
# Resampling
buf_48k = analysis.resample(buf, target_sr=48000.0) # madronalib backend
buf_22k = analysis.resample_fft(buf, target_sr=22050.0) # FFT-based
# GCC-PHAT delay estimation
delay_sec, corr = analysis.gcc_phat(buf, ref)
nanodsp.stream -- Real-time streaming infrastructure
Block-based processing, ring buffers, and processor chains for streaming audio.
from nanodsp.stream import (
RingBuffer, BlockProcessor, CallbackProcessor, ProcessorChain, process_blocks
)
# Ring buffer
rb = RingBuffer(channels=2, capacity=8192)
rb.write(frame_data)
chunk = rb.read(512)
# Block processor
class MyProcessor(BlockProcessor):
def process_block(self, block):
return block * 0.5
proc = MyProcessor(block_size=512)
out = proc.process(buf)
# Callback processor
proc = CallbackProcessor(block_size=512, fn=lambda b: b * 0.5)
# Chain processors
chain = ProcessorChain([proc1, proc2, proc3])
out = chain.process(buf)
# Process with overlap-add
out = process_blocks(buf, block_size=2048, hop_size=512, fn=my_spectral_fn)
nanodsp._core.grainflow -- Granular synthesis (low-level)
Direct access to GrainflowLib's granular synthesis engine.
from nanodsp._core import grainflow as gf
# Create a buffer and fill with audio data
buf = gf.GfBuffer(4096, 1, 48000)
buf.set_data(audio_array) # [channels, frames] float32
# Create a grain collection
gc = gf.GrainCollection(num_grains=8, samplerate=48000)
gc.set_buffer(buf, gf.BUF_BUFFER, 0) # 0 = set for all grains
# Set parameters (enum-based or string reflection)
gc.param_set(0, gf.PARAM_RATE, gf.PTYPE_BASE, 1.0)
gc.param_set_str(0, "delayRandom", 10.0)
# Generate a clock and process
phasor = gf.Phasor(rate=10.0, samplerate=48000)
clock = phasor.perform(256).reshape(1, 256)
traversal = np.linspace(0, 0.5, 256, dtype=np.float32).reshape(1, 256)
fm = np.zeros((1, 256), dtype=np.float32)
am = np.zeros((1, 256), dtype=np.float32)
# Returns 8-element tuple: (output, state, progress, playhead, amp, envelope, buf_ch, stream_ch)
result = gc.process(clock, traversal, fm, am, 48000)
grain_output = result[0] # [num_grains, block_size]
# Pan grains to stereo
panner = gf.Panner(in_channels=8, out_channels=2, pan_mode=gf.PAN_STEREO)
panner.set_pan_spread(0.5)
stereo = panner.process(grain_output, result[1], out_channels=2) # [2, block_size]
nanodsp._core -- C++ bindings (low-level)
Direct access to the C++ extension module with 13 submodules. All high-level Python modules build on these.
| Submodule | Backend | Contents |
|---|---|---|
filters |
signalsmith | Biquad with 16 filter designs, BiquadDesign enum |
fft |
signalsmith | FFT (complex), RealFFT (real) |
delay |
signalsmith | Delay (linear), DelayCubic (cubic interpolation) |
envelopes |
signalsmith | CubicLfo, BoxFilter, BoxStackFilter, PeakHold, PeakDecayLinear |
spectral |
signalsmith | STFT (multi-channel analysis/synthesis) |
rates |
signalsmith | Oversampler2x |
mix |
signalsmith | Hadamard, Householder, cheap_energy_crossfade |
daisysp |
DaisySP | 9 submodules, ~60 classes (oscillators, filters, effects, dynamics, drums, noise, physical modeling, control, utility) |
stk |
STK | 5 submodules, 39 classes (instruments, generators, filters, delays, effects) |
madronalib |
madronalib | FDN reverbs, resampling, generators, 18 projection functions, 6 window functions |
hisstools |
HISSTools | Convolution (mono/multi), spectral processing, 24 statistics functions, 28 window functions, partial tracking |
choc |
CHOC | FLAC read/write |
grainflow |
GrainflowLib | GfBuffer, GrainCollection, Panner, Recorder, Phasor, 37 enum constants |
from nanodsp._core import filters, fft, delay, daisysp, stk, madronalib, hisstools, grainflow
# Example: direct biquad usage
bq = filters.Biquad()
bq.lowpass(0.1, 0.707)
out = bq.process(input_array)
# Example: direct FFT
f = fft.RealFFT(1024)
spectrum = f.fft(signal)
# Example: DaisySP oscillator
osc = daisysp.oscillators.Oscillator()
osc.init(44100.0)
osc.set_freq(440.0)
samples = osc.process(1024)
Full type stubs are provided in _core.pyi for IDE autocompletion and type checking.
Architecture
nanodsp/
__init__.py # package root (__version__ only)
__main__.py # CLI entry point (argparse, subcommand handlers)
_cli.py # function/preset registries, fx parser, type coercion
_core.cpython-*.so # compiled C++ extension (nanobind)
_core.pyi # type stubs for C++ extension
_helpers.py # shared private utilities
buffer.py # AudioBuffer class
io.py # audio file I/O (WAV + FLAC)
ops.py # delay, envelopes, FFT, convolution, rates, mix, pan, xcorr, hilbert, median, LMS
effects.py # filters, effects, dynamics, reverb, mastering, AGC
spectral.py # STFT, spectral transforms, eq_match
synthesis.py # oscillators, noise, drums, physical modeling
analysis.py # loudness, spectral features, pitch, onsets, resample, gcc_phat
stream.py # ring buffer, block processors, overlap-add
Demos
16 demo scripts in demos/ showcase the full API surface. Run them all at once:
make demos # uses demos/s01.wav
make demos DEMO_INPUT=my_audio.wav # use a custom input file
Or run individual demos:
uv run python demos/demo_filters.py demos/s01.wav
uv run python demos/demo_reverb.py demos/s01.wav -o /tmp/reverb-output
uv run python demos/demo_distortion.py demos/s01.wav --no-normalize
uv run python demos/demo_synthesis.py # no input file needed
uv run python demos/demo_analysis.py demos/s01.wav # prints to stdout
| Script | Variants | What it demonstrates |
|---|---|---|
demo_filters.py |
13 | Lowpass, highpass, bandpass, notch, peak EQ, high/low shelf |
demo_modulation.py |
10 | Chorus, flanger, phaser, tremolo |
demo_distortion.py |
14 | Overdrive, wavefold, bitcrush, decimator, saturation, fold |
demo_reverb.py |
12 | FDN presets, ReverbSc, STK freeverb/jcrev/nrev/prcrev |
demo_dynamics.py |
9 | Compression, limiting, noise gate, parallel/multiband compression |
demo_delay.py |
8 | Stereo delay, ping-pong, slapback, STK echo |
demo_pitch.py |
10 | Time-domain and spectral pitch shifting |
demo_spectral.py |
12 | Time stretch, phase lock, spectral gate, tilt EQ, freeze |
demo_daisysp_filters.py |
21 | SVF, ladder, moog, tone, modal, comb filters |
demo_composed.py |
13 | Autowah, SR reduce, DC block, exciter, de-esser, vocal chain, mastering, STK chorus |
demo_spectral_extra.py |
8 | Spectral denoise, EQ match, spectral morph |
demo_ops.py |
29 | Delay, vibrato, convolution, envelopes, fades, panning, stereo widening, crossfade |
demo_resample.py |
6 | Madronalib and FFT resampling at 22k/48k/96k |
demo_synthesis.py |
44 | Oscillators, FM, noise, drums, physical modeling, STK instruments (no input file) |
demo_analysis.py |
-- | Loudness, spectral features, pitch, onsets, chromagram (stdout only) |
demo_grainflow.py |
7 | Granular clouds (basic, dense), pitch shift, sparse stochastic, stereo panning, recorder |
File-processing scripts share the same interface:
usage: demo_*.py [-h] [-o OUT_DIR] [-n] infile
positional arguments:
infile Input .wav file
options:
-o, --out-dir DIR Output directory (default: build/demo-output)
-n, --no-normalize Skip peak normalization (may clip on PCM output)
demo_synthesis.py generates sounds from scratch (no input file; takes -o and -n only). demo_analysis.py prints measurements to stdout (no audio output). demo_grainflow.py processes an input file through granular synthesis.
Development
make build # rebuild extension after C++ changes
make test # run 1163 tests
make demos # run all 16 demo scripts
make qa # test + lint + typecheck + format
make coverage # tests with coverage report
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nanodsp-0.1.3.tar.gz.
File metadata
- Download URL: nanodsp-0.1.3.tar.gz
- Upload date:
- Size: 36.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b8b76fe79b719d5ec51b68bbb094d8a86b61972dbbc5493feff74570e6138da
|
|
| MD5 |
7a8cab6dcc2394313f5b291b54b3b76d
|
|
| BLAKE2b-256 |
86b2983a0729635eb88765288dd603e05ee7ef56f6c543c1f359498ed32ba96b
|
File details
Details for the file nanodsp-0.1.3-cp314-cp314-win_amd64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp314-cp314-win_amd64.whl
- Upload date:
- Size: 737.4 kB
- Tags: CPython 3.14, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7d43d7b334e1311c1570facbe1725b461392db306d06b2e3e496ef6913508e9
|
|
| MD5 |
c7ee0c2bc6bb1cdea8e6f51adaca1b82
|
|
| BLAKE2b-256 |
752421f651405a4f45cb88f19fb53cec0cc51d682d42e58663cf799d05ef1bab
|
File details
Details for the file nanodsp-0.1.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 819.5 kB
- Tags: CPython 3.14, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c9318ada69f7e5e8246807cab9468f64cd89e01b6d3577bacdd7ac2c415fc76
|
|
| MD5 |
0c99544df4370ca402f40159b13ed364
|
|
| BLAKE2b-256 |
a7c008e4a8ce26ef0fc5a51337c45829faf9eea20b18f3edc9177c243946a359
|
File details
Details for the file nanodsp-0.1.3-cp314-cp314-macosx_11_0_arm64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp314-cp314-macosx_11_0_arm64.whl
- Upload date:
- Size: 691.7 kB
- Tags: CPython 3.14, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c7b1a38874b299b3b23ea0f01406fe8db8daff2186f9b3318e6719f0fd325b0
|
|
| MD5 |
3d3be3027e68f4f7669c79e8bf73d85b
|
|
| BLAKE2b-256 |
432bae56e76cbfa5f242bf655bae01918bd4845a71b2e4b1ddcfd13d65ae5104
|
File details
Details for the file nanodsp-0.1.3-cp314-cp314-macosx_10_15_x86_64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp314-cp314-macosx_10_15_x86_64.whl
- Upload date:
- Size: 758.1 kB
- Tags: CPython 3.14, macOS 10.15+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b015935584f53dfcaaa435b54ffacc7f97b5fff4b345fdf23539839a02f58b36
|
|
| MD5 |
2b7c43611903c7eee268aa3c5889676b
|
|
| BLAKE2b-256 |
9184c89c0836a7858502c108d27cc66571f1ac1282c7b6e00d127f39f5185237
|
File details
Details for the file nanodsp-0.1.3-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 715.5 kB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce4f55671120ebb6b485d056ba7bb2b008290790f2fb892552adeb96e2974161
|
|
| MD5 |
bc2fdbc468184225bb31fdf405a0fbc9
|
|
| BLAKE2b-256 |
cb54bf0189e3e17520448b10a366b3c28a3bf2569d057d1649ede83dc640db35
|
File details
Details for the file nanodsp-0.1.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 819.2 kB
- Tags: CPython 3.13, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf5c20370907e152de44dd850f4e268ccc9b29b2959093de3e5f28ee138e2bc9
|
|
| MD5 |
568b8cb0d4ba40050b83874ce19c5fc8
|
|
| BLAKE2b-256 |
83a5acecd9a1ab11602d3211bf33e2b2399bfa91702268e161d8f6085c57c972
|
File details
Details for the file nanodsp-0.1.3-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 691.8 kB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e476d315fcb7bec9da9054edf61f421214472b1b339d3b1fd8059589795d8fb7
|
|
| MD5 |
fb8425a9111dbb2a1cd6a15698e5fbd3
|
|
| BLAKE2b-256 |
358dcb40da8624a8c2f0fc3623659b283adb80e454c04723f6bb5b29e72ad32b
|
File details
Details for the file nanodsp-0.1.3-cp313-cp313-macosx_10_15_x86_64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp313-cp313-macosx_10_15_x86_64.whl
- Upload date:
- Size: 757.8 kB
- Tags: CPython 3.13, macOS 10.15+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9c2201f3dbcecf6595812d433657317f23d1e68b813689723fdc5c7c1128277
|
|
| MD5 |
f3bae261716795866605ff7c4867ceaf
|
|
| BLAKE2b-256 |
153cc9ae7b5f1220dba5f4aa633357f356591cdacd2baf37beaf32293b881e5b
|
File details
Details for the file nanodsp-0.1.3-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 715.6 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2569ef97c5005a7c4c7b9ff9482b48959c5451abbf9ca9974964b60f47a314a6
|
|
| MD5 |
d039df2b450ae8352c2631a5605bd13d
|
|
| BLAKE2b-256 |
6bcaa56b19cb1e2f8172c0d760d4d92950ee457d0936562870c275bb90cdc071
|
File details
Details for the file nanodsp-0.1.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 819.2 kB
- Tags: CPython 3.12, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0c3be0fdc759ba1276711b524b636baf51cf569486a40b2312f0f66b5a6bbac
|
|
| MD5 |
f1daeb4cd1197a38af8f7f46a654c5c5
|
|
| BLAKE2b-256 |
22b8c62cad3939cfbd13d924eb596959541334b2d55dc643e19f4736163e3078
|
File details
Details for the file nanodsp-0.1.3-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 691.8 kB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
897f30fcac208a4e49d5164dd636a0168907f88cdb422ecb02517ce47bc7902c
|
|
| MD5 |
ae951758a30226a959635c7f9db3eaf3
|
|
| BLAKE2b-256 |
87d612f715343155a268e9691d4234f96641bfda51bbf023d9a0e3c90b609e10
|
File details
Details for the file nanodsp-0.1.3-cp312-cp312-macosx_10_15_x86_64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp312-cp312-macosx_10_15_x86_64.whl
- Upload date:
- Size: 758.0 kB
- Tags: CPython 3.12, macOS 10.15+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cbf0140605ce2052327d9d10bcb4f4afd2cf0b6a3e0398b1808dcefc12c4bf8
|
|
| MD5 |
44b150dfebb4170aa27d671293fca78e
|
|
| BLAKE2b-256 |
1fd62a33b8088534294fe66132d17e63dca8a8108d41de7cdee3b131880ead40
|
File details
Details for the file nanodsp-0.1.3-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 715.3 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78d187cc1e6b8b0c8c8564ca8a3018f14cdc40ae2536a9fc841c5472f77d5070
|
|
| MD5 |
887245f0914f9a36688f2e9064491dcc
|
|
| BLAKE2b-256 |
9fdfe2477baa95c10360658aba6b1f38b78424992b784ff34953e28dec3f0994
|
File details
Details for the file nanodsp-0.1.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 819.8 kB
- Tags: CPython 3.11, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2dbc6859be5fa2a8053b3c8fb84353e5bcc6969183eb29d517de8dda51f824eb
|
|
| MD5 |
8ccadd786963b39649b997b63602e7c0
|
|
| BLAKE2b-256 |
179f91f0b1fc254b0e7602351d887ba20d7fef4957b6fb585bc881ec572a76a2
|
File details
Details for the file nanodsp-0.1.3-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 692.1 kB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f182aaaa2142cae9762723ae091ae09f1f1589684412dd3928a678d544ecba04
|
|
| MD5 |
ebafb8d0bf3712658f80454cfb0e47c2
|
|
| BLAKE2b-256 |
4d41b9cd855f7d66f62e8ca37ca6e947343b0aa49725f59c888506a924f87593
|
File details
Details for the file nanodsp-0.1.3-cp311-cp311-macosx_10_15_x86_64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp311-cp311-macosx_10_15_x86_64.whl
- Upload date:
- Size: 753.9 kB
- Tags: CPython 3.11, macOS 10.15+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c0a008dead1196418e72b6d20f29db1763b531d4bdbe896776e21a40cbd6dc6b
|
|
| MD5 |
ee6bd883315342ff3fb7ad430123c669
|
|
| BLAKE2b-256 |
680111530569fe3c8d38f991a64f3eec72de62889a25bb3429afade14965a983
|
File details
Details for the file nanodsp-0.1.3-cp310-cp310-win_amd64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp310-cp310-win_amd64.whl
- Upload date:
- Size: 715.1 kB
- Tags: CPython 3.10, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86f31db8aedb4c445c70da23d39635ba9ab6c95cd11a67f41e43e0ad8e4b4632
|
|
| MD5 |
7be41c7f084e81a54bd0dc08639568f7
|
|
| BLAKE2b-256 |
69e00c11e8285f7c4e4da578cc4c7b55b2995615ff8acab09c56b5791a55ea00
|
File details
Details for the file nanodsp-0.1.3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 819.4 kB
- Tags: CPython 3.10, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97b89d9dd1b8880d1a50db66ce5831274ab9d0ab625a8e266241273fe5d0378e
|
|
| MD5 |
a591bcbf6bb99f6706cb09031b3034c0
|
|
| BLAKE2b-256 |
7047ee99a6c9b91fdaf796723d556971436bb6942f30c23390ec15c1f61e1124
|
File details
Details for the file nanodsp-0.1.3-cp310-cp310-macosx_11_0_arm64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp310-cp310-macosx_11_0_arm64.whl
- Upload date:
- Size: 691.9 kB
- Tags: CPython 3.10, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c44042c6e59128ded06e190a6b61a743493532489fe6eb19138aaf5bb1e00fc5
|
|
| MD5 |
e1dc86c2bcf8253301ed61d6923a1267
|
|
| BLAKE2b-256 |
479b7a8bacd7c96fc1af01d12463455e31b049bc77c48ef99e8cbce2dd06d9a4
|
File details
Details for the file nanodsp-0.1.3-cp310-cp310-macosx_10_15_x86_64.whl.
File metadata
- Download URL: nanodsp-0.1.3-cp310-cp310-macosx_10_15_x86_64.whl
- Upload date:
- Size: 753.5 kB
- Tags: CPython 3.10, macOS 10.15+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a32530fd70b6191a0923bfedc0c35343d73d210e66207dc6f9bdb2f477608d3
|
|
| MD5 |
98f960aa307ef29b047b4a5fa986f3cc
|
|
| BLAKE2b-256 |
b1c031b330798596aa2218a1641f7a025a8f2a8dc0cdbefdbb05b7e7833ee7d9
|