├── dsp ├── include │ └── signalsmith-dsp │ │ ├── fft.h │ │ ├── mix.h │ │ ├── perf.h │ │ ├── curves.h │ │ ├── delay.h │ │ ├── filters.h │ │ ├── rates.h │ │ ├── windows.h │ │ ├── envelopes.h │ │ └── spectral.h ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── common.h ├── perf.h ├── rates.h └── mix.h ├── .gitignore ├── Doxyfile ├── tests ├── common.h ├── envelopes │ ├── peak-hold.py │ ├── plain-plots.py │ ├── 04-peak-decay.cpp │ ├── cubic-lfo.py │ ├── box-stack.py │ ├── 01-box-sum-average.cpp │ ├── 00-cubic-lfo.cpp │ ├── 02-box-stack.cpp │ └── 03-peak-hold.cpp ├── common │ └── version.cpp ├── perf │ ├── perf-lagrange.py │ ├── 00-utils.cpp │ └── 01-lagrange-methods.cpp ├── delay │ ├── 03-multi-delay.cpp │ ├── 00-buffer.cpp │ ├── 02-multi-buffer.cpp │ └── fractional-delay.py ├── windows │ ├── kaiser-plots.py │ ├── window-stats.h │ └── 01-approx-confined-gaussian.cpp ├── fft │ ├── 00-fft.py │ └── fft-errors-numpy.py ├── mix │ ├── cheap-fade.cpp │ ├── stereo-multi.cpp │ └── mixing-matrix.cpp ├── curves │ ├── 00-linear.cpp │ ├── 03-reciprocal-bark.cpp │ ├── 02-reciprocal.cpp │ └── 01-cubic-segments.cpp ├── filters │ ├── 03-gain.cpp │ ├── 04-allpass.cpp │ ├── 01-bandpass.cpp │ ├── 02-responses.cpp │ ├── 06-spec-equivalence.cpp │ ├── 05-shelves.cpp │ ├── filter-tests.h │ ├── plots.cpp │ ├── 07-accuracy.cpp │ └── 00-highpass-lowpass.cpp ├── spectral │ ├── 03-stft-processor.cpp │ └── 01-windowed-fft.cpp └── rates │ └── 00-kaiser-sinc.cpp ├── LICENSE.txt ├── benchmarks ├── fft │ ├── plots.py │ └── complex.cpp └── envelopes-peak-hold │ ├── plots.py │ ├── peak-hold.cpp │ ├── _previous │ ├── signalsmith-run-length-amortised.h │ └── signalsmith-constant-v1.h │ └── _others │ └── kvr-vadim-zavalishin.h ├── manual ├── filters │ └── responses │ │ ├── README.md │ │ ├── Makefile │ │ ├── wasm-api.h │ │ ├── index.html │ │ ├── main.cpp │ │ └── wasm-api.js └── fractional-delay.html ├── historical-docs.sh ├── util ├── console-colours.h ├── csv-writer.h ├── stopwatch.h └── test │ ├── benchmarks.h │ └── main.cpp ├── git-sub-branch ├── README.md ├── extra-style.js ├── version.py ├── index.html └── Makefile /dsp/include/signalsmith-dsp/fft.h: -------------------------------------------------------------------------------- 1 | #include "../../fft.h" 2 | -------------------------------------------------------------------------------- /dsp/include/signalsmith-dsp/mix.h: -------------------------------------------------------------------------------- 1 | #include "../../mix.h" 2 | -------------------------------------------------------------------------------- /dsp/include/signalsmith-dsp/perf.h: -------------------------------------------------------------------------------- 1 | #include "../../perf.h" 2 | -------------------------------------------------------------------------------- /dsp/include/signalsmith-dsp/curves.h: -------------------------------------------------------------------------------- 1 | #include "../../curves.h" 2 | -------------------------------------------------------------------------------- /dsp/include/signalsmith-dsp/delay.h: -------------------------------------------------------------------------------- 1 | #include "../../delay.h" 2 | -------------------------------------------------------------------------------- /dsp/include/signalsmith-dsp/filters.h: -------------------------------------------------------------------------------- 1 | #include "../../filters.h" 2 | -------------------------------------------------------------------------------- /dsp/include/signalsmith-dsp/rates.h: -------------------------------------------------------------------------------- 1 | #include "../../rates.h" 2 | -------------------------------------------------------------------------------- /dsp/include/signalsmith-dsp/windows.h: -------------------------------------------------------------------------------- 1 | #include "../../windows.h" 2 | -------------------------------------------------------------------------------- /dsp/include/signalsmith-dsp/envelopes.h: -------------------------------------------------------------------------------- 1 | #include "../../envelopes.h" 2 | -------------------------------------------------------------------------------- /dsp/include/signalsmith-dsp/spectral.h: -------------------------------------------------------------------------------- 1 | #include "../../spectral.h" 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.DS_Store 2 | **/*.pyc 3 | out/ 4 | html/ 5 | v*/ 6 | 7 | # Personal dev setup 8 | util/article 9 | tests/plot.h 10 | Doxyfile-local 11 | version-notes.txt 12 | -------------------------------------------------------------------------------- /dsp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.24) 2 | 3 | add_library(signalsmith-dsp INTERFACE) 4 | target_include_directories(signalsmith-dsp INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) -------------------------------------------------------------------------------- /Doxyfile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = "Signalsmith Audio's DSP Library" 2 | PROJECT_NUMBER = 1.7.0 3 | PROJECT_BRIEF = Useful C++ classes/templates for audio effects 4 | 5 | OUTPUT_DIRECTORY = . 6 | 7 | INPUT = dsp/ 8 | USE_MDFILE_AS_MAINPAGE = dsp/README.md 9 | 10 | IMAGE_PATH = manual/diagrams out/analysis -------------------------------------------------------------------------------- /tests/common.h: -------------------------------------------------------------------------------- 1 | // Custom style if available 2 | #if defined(__has_include) && __has_include("plot-style.h") 3 | # include "plot-style.h" 4 | #else 5 | # include "plot.h" 6 | #endif 7 | 8 | using Figure = signalsmith::plot::Figure; 9 | using Plot2D = signalsmith::plot::Plot2D; 10 | 11 | #include "../util/csv-writer.h" 12 | 13 | -------------------------------------------------------------------------------- /tests/envelopes/peak-hold.py: -------------------------------------------------------------------------------- 1 | import article 2 | import numpy 3 | from numpy import fft 4 | 5 | figure, axes = article.short(); 6 | 7 | columns, data = article.readCsv("peak-hold.csv") 8 | for i in range(1, len(columns)): 9 | axes.plot(data[0], data[i], label=columns[i]); 10 | axes.set(xlabel="time") 11 | figure.save("peak-hold.svg") 12 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021-2022 Geraint Luff / Signalsmith Audio Ltd. 2 | 3 | Unless released elsewhere under another license, or a license/description is included in the file itself, the contents of this directory is licensed for use and redistribution (including modified versions) solely for developing, testing or documenting the Signalsmith Audio DSP Library. -------------------------------------------------------------------------------- /tests/common/version.cpp: -------------------------------------------------------------------------------- 1 | #include "delay.h" // Anything that includes "common.h" should do 2 | 3 | SIGNALSMITH_DSP_VERSION_CHECK(1, 7, 0) 4 | 5 | // Test with some compatible earlier versions 6 | SIGNALSMITH_DSP_VERSION_CHECK( 7 | SIGNALSMITH_DSP_VERSION_MAJOR, 8 | SIGNALSMITH_DSP_VERSION_MINOR, 9 | SIGNALSMITH_DSP_VERSION_PATCH 10 | ) 11 | SIGNALSMITH_DSP_VERSION_CHECK( 12 | SIGNALSMITH_DSP_VERSION_MAJOR, 13 | SIGNALSMITH_DSP_VERSION_MINOR, 14 | 0 15 | ) 16 | SIGNALSMITH_DSP_VERSION_CHECK( 17 | SIGNALSMITH_DSP_VERSION_MAJOR, 18 | 0, 19 | 0 20 | ) 21 | -------------------------------------------------------------------------------- /tests/perf/perf-lagrange.py: -------------------------------------------------------------------------------- 1 | from numpy import * 2 | from numpy.fft import rfft 3 | 4 | import article 5 | 6 | for type in ["double", "float"]: 7 | columns, data = article.readCsv("performance-lagrange-interpolation-%s.csv"%type) 8 | 9 | figure, axes = article.medium() 10 | for i in range(1, len(columns)): 11 | axes.plot(data[0], data[i], label=columns[i]) 12 | axes.set(xlabel="order", ylabel="computation time", ylim=[0, None], xlim=[min(data[0]), max(data[0])], xticks=range(int(min(data[0])), int(max(data[0])) + 1, 2)); 13 | figure.save("performance-lagrange-interpolation-%s.svg"%type) 14 | -------------------------------------------------------------------------------- /tests/envelopes/plain-plots.py: -------------------------------------------------------------------------------- 1 | import article 2 | import numpy 3 | from numpy import fft 4 | 5 | def plainPlot(name, legend_loc="best", ylim=[None, None]): 6 | figure, axes = article.short(); 7 | columns, data = article.readCsv("%s.csv"%name) 8 | for i in range(1, len(columns)): 9 | axes.plot(data[0], data[i], label=columns[i]); 10 | axes.set(xlabel="time", ylim=ylim) 11 | figure.save("%s.svg"%name, legend_loc=legend_loc) 12 | 13 | plainPlot("box-filter-example") 14 | plainPlot("peak-decay-linear", legend_loc="upper center", ylim=[0,10]) 15 | plainPlot("peak-decay-linear-cascade", legend_loc="upper center", ylim=[0,10]) 16 | -------------------------------------------------------------------------------- /benchmarks/fft/plots.py: -------------------------------------------------------------------------------- 1 | import article 2 | 3 | def plainPlot(name): 4 | columns, data = article.readCsv("%s.csv"%name) 5 | 6 | figure, axes = article.medium(); 7 | def display(x): 8 | if x == int(x): 9 | return str(int(x)) 10 | return str(x) 11 | xlabels = [display(x) for x in data[0]]; 12 | xticks = range(len(data[0])); 13 | 14 | divisor = int(len(xlabels)*0.2); 15 | for i in range(len(xlabels)): 16 | if i%divisor != 0: 17 | xlabels[i] = "" 18 | 19 | for i in range(1, len(columns)): 20 | axes.plot(xticks, 1/data[i], label=columns[i]); 21 | axes.set(ylabel="speed (higher is better)", xticks=xticks, xticklabels=xlabels); 22 | figure.save("%s.svg"%name, legend_loc="upper center") 23 | 24 | plainPlot("complex_fft_double") 25 | -------------------------------------------------------------------------------- /benchmarks/envelopes-peak-hold/plots.py: -------------------------------------------------------------------------------- 1 | import article 2 | 3 | def plainPlot(name, legend_loc="best"): 4 | columns, data = article.readCsv("%s.csv"%name) 5 | 6 | figure, axes = article.medium(); 7 | def display(x): 8 | if x == int(x): 9 | return str(int(x)) 10 | return str(x) 11 | xlabels = [display(x) for x in data[0]]; 12 | xticks = range(len(data[0])); 13 | 14 | divisor = int(len(xlabels)*0.2); 15 | for i in range(len(xlabels)): 16 | if i%divisor != 0: 17 | xlabels[i] = "" 18 | 19 | for i in range(1, len(columns)): 20 | axes.plot(xticks, 1/data[i], label=columns[i]); 21 | axes.set(ylabel="speed (higher is better)", xticks=xticks, xticklabels=xlabels); 22 | figure.save("%s.svg"%name, legend_loc=legend_loc) 23 | 24 | plainPlot("envelopes_peak_hold_double") 25 | plainPlot("envelopes_peak_hold_float") 26 | plainPlot("envelopes_peak_hold_int") 27 | -------------------------------------------------------------------------------- /manual/filters/responses/README.md: -------------------------------------------------------------------------------- 1 | # Emscripten build 2 | 3 | C++ should include [`wasm-api.h`](wasm-api.h). This provides some helper methods for passing back arrays and strings, by stashing them in a property on the module. 4 | 5 | This can be run from `WasmApi().run(Main, callback) in `wasm-api.js`, which wraps all the exposed functions so that array results and callbacks work. 6 | 7 | The `EXPORT_NAME` argument in the `Makefile` should match the `#define` in `main.cpp`. 8 | 9 | ### Setting up 10 | 11 | If you don't already have the Emscripten SDK installed: 12 | 13 | ``` 14 | EMSDK_DIR=