├── Makefile ├── readme.rst ├── requirements.txt └── source ├── Analysis ├── 107-tone-detection-with-goertzel.rst ├── 108-magnitude-and-phase-plot-of-arbitrary-iir-function-up-to-5th-order.rst ├── 136-envelope-follower-with-different-attack-and-release.rst ├── 137-lpc-analysis-autocorrelation-levinson-durbin-recursion.rst ├── 146-qft-and-dqft-double-precision-classes.rst ├── 156-java-fft.rst ├── 172-tone-detection-with-goertzel-x86-asm.rst ├── 18-fast-in-place-walsh-hadamard-transform.rst ├── 186-frequency-response-from-biquad-coefficients.rst ├── 19-simple-peak-follower.rst ├── 20-coefficients-for-daubechies-wavelets-1-38.rst ├── 200-beat-detector-class.rst ├── 21-dft.rst ├── 22-measuring-interpollation-noise.rst ├── 264-vintage-vu-meters-tutorial.rst ├── 53-look-ahead-limiting.rst ├── 79-fft.rst ├── 82-fft-classes-in-c-and-object-pascal.rst ├── 97-envelope-detector.rst └── index.rst ├── Effects ├── 101-parallel-combs-delay-calculation.rst ├── 102-ece320-project-reverberation-w-parameter-control-from-pc.rst ├── 104-variable-hardness-clipping-function.rst ├── 114-waveshaper-simple-description.rst ├── 124-decimator.rst ├── 126-time-compression-expansion-using-standard-phase-vocoder.rst ├── 139-lo-fi-crusher.rst ├── 150-reverberation-algorithms-in-matlab.rst ├── 153-most-simple-static-delay.rst ├── 154-most-simple-and-smooth-feedback-delay.rst ├── 169-compressor.rst ├── 173-stereo-enhancer.rst ├── 177-transistor-differential-amplifier-simulation.rst ├── 203-fold-back-distortion.rst ├── 204-simple-compressor-class-c.rst ├── 207-dynamic-convolution.rst ├── 221-band-limited-pwm-generator.rst ├── 230-polynominal-waveshaper.rst ├── 255-stereo-field-rotation-via-transformation-matrix.rst ├── 256-stereo-width-control-obtained-via-transfromation-matrix.rst ├── 274-lookahead-limiter.rst ├── 277-univox-univibe-emulator.rst ├── 41-waveshaper.rst ├── 42-soft-saturation.rst ├── 43-waveshaper.rst ├── 44-delay-time-calculation-for-reverberation.rst ├── 45-reverberation-techniques.rst ├── 46-waveshaper.rst ├── 47-guitar-feedback.rst ├── 70-alien-wah.rst ├── 74-early-echo-s-with-image-mirror-technique.rst ├── 78-phaser-code.rst ├── 86-waveshaper-gloubi-boulga.rst ├── 89-2-wave-shaping-things.rst ├── 96-bit-quantization-reduction-effect.rst ├── 98-class-for-waveguide-delay-effects.rst └── index.rst ├── Filters ├── 110-formant-filter.rst ├── 116-one-pole-lp-and-hp.rst ├── 117-one-pole-one-zero-lp-hp.rst ├── 118-one-zero-lp-hp.rst ├── 122-digital-riaa-equalization-filter-coefficients.rst ├── 128-c-class-implementation-of-rbj-filters.rst ├── 130-peak-notch-filter.rst ├── 131-cascaded-resonant-lp-hp-filter.rst ├── 135-dc-filter.rst ├── 141-karlsen.rst ├── 142-state-variable-filter-chamberlin-version.rst ├── 145-stilson-s-moog-filter-code.rst ├── 174-direct-form-ii.rst ├── 176-reverb-filter-generator.rst ├── 179-frequency-warped-fir-lattice.rst ├── 180-cool-sounding-lowpass-with-decibel-measured-resonance.rst ├── 181-another-4-pole-lowpass.rst ├── 185-1-rc-and-c-filter.rst ├── 194-windowed-sinc-fir-generator.rst ├── 195-hilbert-filter-coefficient-calculation.rst ├── 196-moog-filter.rst ├── 197-rbj-audio-eq-cookbook.rst ├── 198-rbj-audio-eq-cookbook.rst ├── 208-remez-remez-parks-mcclellan.rst ├── 209-remez-exchange-algorithm-parks-mcclellan.rst ├── 214-fast-downsampling-with-antialiasing.rst ├── 218-plotting-r-b-j-equalisers-in-excel.rst ├── 223-polyphase-filters-delphi.rst ├── 225-delphi-class-implementation-of-the-rbj-filters.rst ├── 226-c-weighed-filter.rst ├── 229-lpf-24db-oct.rst ├── 23-state-variable.rst ├── 231-hiqh-quality-2-decimators.rst ├── 232-type-lpf-24db-oct.rst ├── 235-bass-booster.rst ├── 236-3-band-equaliser.rst ├── 237-one-pole-filter-lp-and-hp.rst ├── 24-moog-vcf.rst ├── 240-karlsen-fast-ladder.rst ├── 243-butterworth-optimized-c-class.rst ├── 247-poor-man-s-fiwiz.rst ├── 25-moog-vcf-variation-1.rst ├── 251-plot-filter-analyze-filter-characteristics.rst ├── 253-perfect-lp4-filter.rst ├── 257-1-pole-lpf-for-smooth-parameter-changes.rst ├── 258-spuc-s-open-source-filters.rst ├── 259-simple-biquad-filter-from-apple-com.rst ├── 26-moog-vcf-variation-2.rst ├── 263-one-liner-iir-filters-1st-order.rst ├── 265-output-limiter-using-envelope-follower-in-c.rst ├── 266-4th-order-linkwitz-riley-filters.rst ├── 267-simple-tilt-equalizer.rst ├── 27-resonant-iir-lowpass-12db-oct.rst ├── 270-mdct-and-imdct-based-on-fftw3.rst ├── 275-direct-form-ii-biquad.rst ├── 276-biquad-butterworth-chebyshev-n-order-m-channel-optimized-filters.rst ├── 28-lowpass-filter-for-parameter-edge-filtering.rst ├── 29-resonant-filter.rst ├── 30-303-type-filter-with-saturation.rst ├── 31-all-pass-filters-a-good-explanation.rst ├── 32-various-biquad-filters.rst ├── 33-resonant-low-pass-filter.rst ├── 34-prewarping.rst ├── 35-notch-filter.rst ├── 37-zoelzer-biquad-filters.rst ├── 38-lp-and-hp-filter.rst ├── 39-polyphase-filters.rst ├── 64-biquad-c-code.rst ├── 65-time-domain-convolution-with-o-n-log2-3.rst ├── 66-time-domain-convolution-with-o-n-log2-3.rst ├── 72-18db-oct-resonant-3-pole-lpf-with-tanh-dist.rst ├── 76-pink-noise-filter.rst ├── 85-1st-and-2nd-order-pink-noise-filters.rst ├── 92-state-variable-filter-double-sampled-stable.rst └── index.rst ├── Other ├── 103-calculate-notes-java.rst ├── 106-fast-exp2-approximation.rst ├── 115-sin-cos-tan-approximation.rst ├── 119-lock-free-fifo.rst ├── 120-saturation.rst ├── 121-gaussian-dithering.rst ├── 125-midi-note-frequency-conversion.rst ├── 129-gaussian-random-numbers.rst ├── 132-fast-abs-neg-sign-for-32bit-floats.rst ├── 133-fast-power-and-root-estimates-for-32bit-floats.rst ├── 138-envelope-follower.rst ├── 148-nonblocking-multiprocessor-multithread-algorithms-in-c.rst ├── 149-block-loop-benchmarking.rst ├── 157-hermite-interpolator-x86-asm.rst ├── 158-really-fast-x86-floating-point-sin-cos.rst ├── 162-antialiased-lines.rst ├── 163-center-separation-in-a-stereo-mixdown.rst ├── 164-resampling.rst ├── 165-center-separation-in-a-stereo-mixdown.rst ├── 166-cheap-pseudo-sinusoidal-lfo.rst ├── 170-float-to-int-more-intel-asm.rst ├── 171-bit-reversed-counting.rst ├── 175-sin-x-aproximation-with-sse-code.rst ├── 178-reasonably-accurate-fastish-tanh-approximation.rst ├── 182-vst-sdk-gui-switch-without.rst ├── 188-matlab-time-domain-impulse-response-inverter-divider.rst ├── 191-cure-for-malicious-samples.rst ├── 193-denormalization-preventer.rst ├── 202-motorola-56300-disassembler.rst ├── 206-fast-cube-root-square-root-and-reciprocal-for-x86-sse-cpus.rst ├── 210-branchless-clipping.rst ├── 212-16-point-fast-integer-sinc-interpolator.rst ├── 222-fast-exp-approximations.rst ├── 228-automatic-pdc-system.rst ├── 233-denormalization-preventer.rst ├── 238-rational-tanh-approximation.rst ├── 245-linear-interpolation.rst ├── 246-float-to-integer-conversion.rst ├── 248-conversion-and-normalization-of-16-bit-sample-to-a-floating-point-number.rst ├── 249-fast-sign-for-32-bit-floats.rst ├── 250-piecewise-quadratic-approximate-exponential-function.rst ├── 252-fast-rounding-functions-in-pascal.rst ├── 260-exponential-curve-for.rst ├── 273-fast-float-random-numbers.rst ├── 48-double-to-int.rst ├── 49-cubic-interpollation.rst ├── 50-base-2-exp.rst ├── 51-denormal-numbers.rst ├── 52-conversions-on-a-powerpc.rst ├── 54-allocating-aligned-memory.rst ├── 55-pow-x-4-approximation.rst ├── 56-float-to-int.rst ├── 57-float-to-int-coverting-an-array-of-floats.rst ├── 58-matlab-tools-for-sndan.rst ├── 60-5-point-spline-interpollation.rst ├── 61-dither-code.rst ├── 62-3rd-order-spline-interpollation.rst ├── 63-fast-log2.rst ├── 71-constant-time-exponent-of-2-detector.rst ├── 77-dithering.rst ├── 81-clipping-without-branching.rst ├── 83-denormal-numbers-the-meta-text.rst ├── 84-reading-the-compressed-wa-parts-in-gigasampler-files.rst ├── 87-exponential-parameter-mapping.rst ├── 88-denormal-double-variables-macro.rst ├── 91-fast-binary-log-approximations.rst ├── 93-hermite-interpollation.rst ├── 94-millimeter-to-db-faders.rst ├── 95-16-to-8-bit-first-order-dither.rst ├── 99-noise-shaping-class.rst └── index.rst ├── Synthesis ├── 1-alias-free-waveform-generation-with-analog-filtering.rst ├── 10-fast-sine-and-cosine-calculation.rst ├── 109-gaussian-white-noise.rst ├── 11-weird-synthesis.rst ├── 111-phase-modulation-vs-frequency-modulation.rst ├── 112-waveform-generator-using-minbleps.rst ├── 113-gaussian-white-noise.rst ├── 12-bandlimited-waveforms.rst ├── 123-audiable-alias-free-waveform-gen-using-width-sine.rst ├── 13-sine-calculation.rst ├── 134-arbitary-shaped-band-limited-waveform-generation-using-oversampling-and-low-pass-filtering.rst ├── 14-inverted-parabolic-envelope.rst ├── 140-dsf-super-set-of-blit.rst ├── 15-cubic-polynomial-envelopes.rst ├── 151-fast-lfo-in-delphi.rst ├── 152-another-lfo-class.rst ├── 16-allmost-ready-to-use-oscillators.rst ├── 160-phase-modulation-vs-frequency-modulation-ii.rst ├── 161-quick-and-dirty-sine-generator.rst ├── 167-another-cheap-sinusoidal-lfo.rst ├── 168-c-gaussian-noise-generation.rst ├── 17-bandlimited-waveform-generation.rst ├── 183-drift-generator.rst ├── 184-rossler-and-lorenz-oscillators.rst ├── 187-chebyshev-waveshaper-using-their-recursive-definition.rst ├── 189-fast-exponential-envelope-generator.rst ├── 199-rbj-wavetable-101.rst ├── 2-square-waves.rst ├── 211-matlab-octave-code-for-minblep-table-generation.rst ├── 213-padsynth-synthesys-method.rst ├── 215-generator.rst ├── 216-fast-whitenoise-generator.rst ├── 217-easy-noise-generation.rst ├── 219-antialiased-square-generator.rst ├── 220-trammell-pink-noise-c-class.rst ├── 224-am-formantic-synthesis.rst ├── 227-butterworth.rst ├── 239-c-oscilator-class.rst ├── 241-quick-dirty-sine.rst ├── 242-pulsequad.rst ├── 244-direct-pink-noise-synthesis-with-auto-correlated-generator.rst ├── 254-parabolic-shaper.rst ├── 261-fast-sin-approximation-for-usage-in-e-g-additive-synthesizers.rst ├── 262-simple-time-stretching-granular-synthesizer.rst ├── 268-band-limited-waveforms-my-way.rst ├── 269-smooth-random-lfo-generator.rst ├── 271-prng-for-non-uniformly-distributed-values-from-trigonometric-identity.rst ├── 272-randja-compressor.rst ├── 59-pseudo-random-generator.rst ├── 67-sawsin.rst ├── 68-discrete-summation-formula-dsf.rst ├── 69-fast-square-wave-generator.rst ├── 75-bandlimited-waveforms-synopsis.rst ├── 8-pulsewidth-modulation.rst ├── 80-wavetable-synthesis.rst ├── 9-fast-sine-wave-calculation.rst ├── 90-bandlimited-sawtooth-synthesis.rst └── index.rst ├── conf.py ├── files ├── 56kmidi.gif ├── ATOMIC.H ├── Audio-EQ-Cookbook.txt ├── BandLimit.cpp ├── BandLimit.h ├── CFxRbjFilter.h ├── Disassemble56k.zip ├── EQ-Coefficients.pdf ├── FFTReal.zip ├── FIJI.ZIP ├── Frequency.java ├── LFO.zip ├── LFOGenerator.zip ├── LockFreeFifo.h ├── MATLABReverb.zip ├── MFX2181.zip ├── MadShifta.sit ├── MadShifta.zip ├── MinBLEPS.zip ├── NS9dither16.h ├── SimpleOscillator.h ├── Sounds.asm ├── THRU.ASM ├── Units.asm ├── VowelSynth.zip ├── Wavetable-101.pdf ├── Wavetable.sit ├── alienwah.c ├── approx.h ├── bandlimited.cpp ├── bandlimited.pdf ├── biquad.c ├── daub.h ├── denormal.pdf ├── early_echo.c ├── early_echo_eng.c ├── filter001.gif ├── filters001.txt ├── filters002.txt ├── filters003.txt ├── filters004.txt ├── filters005.txt ├── flash.asm ├── gigxpand.zip ├── index.php ├── interp.zip ├── laurent.gif ├── lpf18.sme ├── lpf18.zip ├── madshifta_readme.txt ├── midinative.zip ├── mmflash.txt ├── moog.txt.deleted ├── nsdither.txt ├── other001.gif ├── other001.txt ├── other001.zip ├── pdc.pdf ├── phaser.cpp ├── pink.txt ├── qft.tar_1.gz ├── rbj_eq.xls ├── rev.txt ├── rvfft.cpp ├── rvfft.ps ├── simpleSource.zip ├── sincos.zip ├── sines.asm ├── synthesis001.txt ├── synthesis002.txt ├── vocoder.m ├── waveforms.txt ├── wavetabl.zip └── wsfir.h └── index.rst /Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = source 8 | BUILDDIR = build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 20 | -------------------------------------------------------------------------------- /readme.rst: -------------------------------------------------------------------------------- 1 | Welcome to Musicdsp.org website source 2 | ====================================== 3 | 4 | |build-status| 5 | 6 | Pull requests welcome! 7 | 8 | In order to build the HTML locally with python3: 9 | 10 | .. code-block:: bash 11 | 12 | python -m venv .env 13 | pip install -r requirements.txt 14 | make html 15 | 16 | 17 | .. |build-status| image:: https://readthedocs.org/projects/musicdsp/badge/?version=latest 18 | :alt: build status 19 | :scale: 100% 20 | :target: https://readthedocs.org/projects/musicdsp -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinx_rtd_theme -------------------------------------------------------------------------------- /source/Analysis/136-envelope-follower-with-different-attack-and-release.rst: -------------------------------------------------------------------------------- 1 | Envelope follower with different attack and release 2 | =================================================== 3 | 4 | - **Author or source:** Bram 5 | - **Created:** 2003-01-15 00:21:39 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | xxxx_in_ms is xxxx in milliseconds ;-) 12 | 13 | 14 | .. code-block:: c++ 15 | :linenos: 16 | :caption: code 17 | 18 | init:: 19 | 20 | attack_coef = exp(log(0.01)/( attack_in_ms * samplerate * 0.001)); 21 | release_coef = exp(log(0.01)/( release_in_ms * samplerate * 0.001)); 22 | envelope = 0.0; 23 | 24 | loop:: 25 | 26 | tmp = fabs(in); 27 | if(tmp > envelope) 28 | envelope = attack_coef * (envelope - tmp) + tmp; 29 | else 30 | envelope = release_coef * (envelope - tmp) + tmp; 31 | 32 | Comments 33 | -------- 34 | 35 | - **Date**: 2003-01-18 20:56:46 36 | - **By**: kd.utd.xaspmak@mj 37 | 38 | .. code-block:: c++ 39 | 40 | // the expressions of the form: 41 | 42 | xxxx_coef = exp(log(0.01)/( xxxx_in_ms * samplerate * 0.001)); 43 | 44 | // can be simplified a little bit to: 45 | 46 | xxxx_coef = pow(0.01, 1.0/( xxxx_in_ms * samplerate * 0.001)); 47 | 48 | 49 | - **Date**: 2007-07-01 19:05:26 50 | - **By**: uh.etle.fni@yfoocs 51 | 52 | .. code-block:: text 53 | 54 | Here the definition of the attack/release time is the time for the envelope to fall from 100% to 1%. 55 | In the other version, the definition is for the envelope to fall from 100% to 36.7%. So in this one 56 | the envelope is about 4.6 times faster. 57 | -------------------------------------------------------------------------------- /source/Analysis/18-fast-in-place-walsh-hadamard-transform.rst: -------------------------------------------------------------------------------- 1 | Fast in-place Walsh-Hadamard Transform 2 | ====================================== 3 | 4 | - **Author or source:** Timo H Tossavainen 5 | - **Type:** wavelet transform 6 | - **Created:** 2002-01-17 01:54:52 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | IIRC, They're also called walsh-hadamard transforms. 13 | Basically like Fourier, but the basis functions are squarewaves with different sequencies. 14 | I did this for a transform data compression study a while back. 15 | Here's some code to do a walsh hadamard transform on long ints in-place (you need to 16 | divide by n to get transform) the order is bit-reversed at output, IIRC. 17 | The inverse transform is the same as the forward transform (expects bit-reversed input). 18 | i.e. x = 1/n * FWHT(FWHT(x)) (x is a vector) 19 | 20 | 21 | .. code-block:: c++ 22 | :linenos: 23 | :caption: code 24 | 25 | void inline wht_bfly (long& a, long& b) 26 | { 27 | long tmp = a; 28 | a += b; 29 | b = tmp - b; 30 | } 31 | 32 | // just a integer log2 33 | int inline l2 (long x) 34 | { 35 | int l2; 36 | for (l2 = 0; x > 0; x >>=1) 37 | { 38 | ++ l2; 39 | } 40 | 41 | return (l2); 42 | } 43 | 44 | //////////////////////////////////////////// 45 | // Fast in-place Walsh-Hadamard Transform // 46 | //////////////////////////////////////////// 47 | 48 | void FWHT (std::vector& data) 49 | { 50 | const int log2 = l2 (data.size()) - 1; 51 | for (int i = 0; i < log2; ++i) 52 | { 53 | for (int j = 0; j < (1 << log2); j += 1 << (i+1)) 54 | { 55 | for (int k = 0; k < (1<= output ) 31 | { 32 | /* When we hit a peak, ride the peak to the top. */ 33 | output = input; 34 | } 35 | else 36 | { 37 | /* Exponential decay of output when signal is low. */ 38 | output = output * scalar; 39 | /* 40 | ** When current gets close to 0.0, set current to 0.0 to prevent FP underflow 41 | ** which can cause a severe performance degradation due to a flood 42 | ** of interrupts. 43 | */ 44 | if( output < VERY_SMALL_FLOAT ) output = 0.0; 45 | } 46 | 47 | Comments 48 | -------- 49 | 50 | - **Date**: 2013-01-26 09:48:15 51 | - **By**: moc.liamg@osoromaerfac 52 | 53 | .. code-block:: c++ 54 | 55 | #ifndef VERY_SMALL_FLOAT 56 | #define VERY_SMALL_FLOAT 1.0e-30F 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /source/Analysis/20-coefficients-for-daubechies-wavelets-1-38.rst: -------------------------------------------------------------------------------- 1 | Coefficients for Daubechies wavelets 1-38 2 | ========================================= 3 | 4 | - **Author or source:** Computed by Kazuo Hatano, Compiled and verified by Olli Niemitalo 5 | - **Type:** wavelet transform 6 | - **Created:** 2002-01-17 02:00:43 7 | 8 | - **Linked files:** :download:`daub.h <../files/daub.h>`. 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /source/Analysis/21-dft.rst: -------------------------------------------------------------------------------- 1 | DFT 2 | === 3 | 4 | - **Author or source:** Andy Mucho 5 | - **Type:** fourier transform 6 | - **Created:** 2002-01-17 01:59:38 7 | 8 | 9 | 10 | .. code-block:: c++ 11 | :linenos: 12 | :caption: code 13 | 14 | AnalyseWaveform(float *waveform, int framesize) 15 | { 16 | float aa[MaxPartials]; 17 | float bb[MaxPartials]; 18 | for(int i=0;i>= 1; 32 | if (value>section) 33 | { 34 | lookup[section]++; 35 | lookup_add(section+size,size,value); 36 | } 37 | else 38 | lookup_add(section-size,size,value); 39 | } 40 | } 41 | 42 | void lookup_remove(unsigned section, unsigned size, unsigned value) 43 | { 44 | if (section==value) 45 | lookup[section]--; 46 | else 47 | { 48 | size >>= 1; 49 | if (value>section) 50 | { 51 | lookup[section]--; 52 | lookup_remove(section+size,size,value); 53 | } 54 | else 55 | lookup_remove(section-size,size,value); 56 | } 57 | } 58 | 59 | unsigned lookup_getmax(unsigned section, unsigned size) 60 | { 61 | unsigned max = lookup[section] ? section : 0; 62 | size >>= 1; 63 | if (size) 64 | if (max) 65 | { 66 | max = lookup_getmax((section+size),size); 67 | if (!max) max=section; 68 | } 69 | else 70 | max = lookup_getmax((section-size),size); 71 | return max; 72 | } 73 | 74 | void add_value(unsigned value) 75 | { 76 | lookup_add(LOOKUP_VALUES>>1, LOOKUP_VALUES>>1, value); 77 | } 78 | 79 | void remove_value(unsigned value) 80 | { 81 | lookup_remove(LOOKUP_VALUES>>1, LOOKUP_VALUES>>1, value); 82 | } 83 | 84 | unsigned get_max_value() 85 | { 86 | return lookup_getmax(LOOKUP_VALUES>>1, LOOKUP_VALUES>>1); 87 | } 88 | 89 | -------------------------------------------------------------------------------- /source/Analysis/79-fft.rst: -------------------------------------------------------------------------------- 1 | FFT 2 | === 3 | 4 | - **Author or source:** Toth Laszlo 5 | - **Created:** 2002-02-11 17:43:15 6 | 7 | - **Linked files:** :download:`rvfft.ps <../files/rvfft.ps>`. 8 | - **Linked files:** :download:`rvfft.cpp <../files/rvfft.cpp>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | A paper (postscript) and some C++ source for 4 different fft algorithms, compiled by Toth 14 | Laszlo from the Hungarian Academy of Sciences Research Group on Artificial Intelligence. 15 | Toth says: "I've found that Sorensen's split-radix algorithm was the fastest, so I use 16 | this since then (this means that you may as well delete the other routines in my source - 17 | if you believe my results)." 18 | 19 | 20 | 21 | Comments 22 | -------- 23 | 24 | - **Date**: 2011-01-22 20:56:46 25 | - **By**: moc.oohay@ygobatem 26 | 27 | .. code-block:: text 28 | 29 | Thank you very much, this was useful, and it worked right out of the box, 30 | so to speak. It's very efficient, and the algorithm is readable. It also includes some 31 | very useful functions. 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /source/Analysis/82-fft-classes-in-c-and-object-pascal.rst: -------------------------------------------------------------------------------- 1 | FFT classes in C++ and Object Pascal 2 | ==================================== 3 | 4 | - **Author or source:** Laurent de Soras (Object Pascal translation by Frederic Vanmol) 5 | - **Type:** Real-to-Complex FFT and Complex-to-Real IFFT 6 | - **Created:** 2002-02-14 02:09:26 7 | 8 | - **Linked files:** :download:`FFTReal.zip <../files/FFTReal.zip>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | (see linkfile) 14 | -------------------------------------------------------------------------------- /source/Analysis/97-envelope-detector.rst: -------------------------------------------------------------------------------- 1 | Envelope detector 2 | ================= 3 | 4 | - **Author or source:** Bram 5 | - **Created:** 2002-04-12 21:37:18 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | Basicaly a one-pole LP filter with different coefficients for attack and release fed by 12 | the abs() of the signal. If you don't need different attack and decay settings, just use 13 | in->abs()->LP 14 | 15 | 16 | .. code-block:: c++ 17 | :linenos: 18 | :caption: code 19 | 20 | //attack and release in seconds 21 | float ga = (float) exp(-1/(SampleRate*attack)); 22 | float gr = (float) exp(-1/(SampleRate*release)); 23 | 24 | float envelope=0; 25 | 26 | for(...) 27 | { 28 | //get your data into 'input' 29 | EnvIn = std::abs(input); 30 | 31 | if(envelope < EnvIn) 32 | { 33 | envelope *= ga; 34 | envelope += (1-ga)*EnvIn; 35 | } 36 | else 37 | { 38 | envelope *= gr; 39 | envelope += (1-gr)*EnvIn; 40 | } 41 | //envelope now contains.........the envelope ;) 42 | } 43 | 44 | Comments 45 | -------- 46 | 47 | - **Date**: 2005-05-17 13:58:11 48 | - **By**: moc.liamg@sisehtnysorpitna 49 | 50 | .. code-block:: c++ 51 | 52 | // Slightly faster version of the envelope follower using one multiply form. 53 | 54 | // attTime and relTime is in seconds 55 | 56 | float ga = exp(-1.0f/(sampleRate*attTime)); 57 | float gr = exp(-1.0f/(sampleRate*relTime)); 58 | 59 | float envOut = 0.0f; 60 | 61 | for( ... ) 62 | { 63 | // get your data into 'input' 64 | 65 | envIn = fabs(input); 66 | 67 | if( envOut < envIn ) 68 | envOut = envIn + ga * (envOut - envIn); 69 | else 70 | envOut = envIn + gr * (envOut - envIn); 71 | 72 | // envOut now contains the envelope 73 | } 74 | -------------------------------------------------------------------------------- /source/Analysis/index.rst: -------------------------------------------------------------------------------- 1 | Analysis 2 | ======== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :caption: Contents: 7 | 8 | 200-beat-detector-class 9 | 20-coefficients-for-daubechies-wavelets-1-38 10 | 21-dft 11 | 97-envelope-detector 12 | 136-envelope-follower-with-different-attack-and-release 13 | 79-fft 14 | 82-fft-classes-in-c-and-object-pascal 15 | 18-fast-in-place-walsh-hadamard-transform 16 | 186-frequency-response-from-biquad-coefficients 17 | 156-java-fft 18 | 137-lpc-analysis-autocorrelation-levinson-durbin-recursion 19 | 53-look-ahead-limiting 20 | 108-magnitude-and-phase-plot-of-arbitrary-iir-function-up-to-5th-order 21 | 22-measuring-interpollation-noise 22 | 146-qft-and-dqft-double-precision-classes 23 | 19-simple-peak-follower 24 | 107-tone-detection-with-goertzel 25 | 172-tone-detection-with-goertzel-x86-asm 26 | 264-vintage-vu-meters-tutorial 27 | -------------------------------------------------------------------------------- /source/Effects/101-parallel-combs-delay-calculation.rst: -------------------------------------------------------------------------------- 1 | Parallel combs delay calculation 2 | ================================ 3 | 4 | - **Author or source:** Juhana Sadeharju ( if.tenuf.cin@aihuok ) 5 | - **Created:** 2002-05-23 19:49:40 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | This formula can be found from a patent related to parallel combs structure. The 12 | formula places the first echoes coming out of parallel combs to uniformly distributed 13 | sequence. If T_ ,...,T_n are the delay lines in increasing order, the formula can be 14 | derived by setting T_(k-1)/T_k = Constant and T_n/(2*T_1) = Constant, where 2*T_1 is the 15 | echo coming just after the echo T_n. 16 | I figured this out myself as it is not told in the patent. The formula is not the best 17 | which one can come up. I use a search method to find echo sequences which are uniform 18 | enough for long enough time. The formula is uniform for a short time only. 19 | The formula doesn't work good for series allpass and FDN structures, for which a 20 | similar formula can be derived with the same idea. The search method works for these 21 | structures as well. 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /source/Effects/102-ece320-project-reverberation-w-parameter-control-from-pc.rst: -------------------------------------------------------------------------------- 1 | ECE320 project: Reverberation w/ parameter control from PC 2 | ========================================================== 3 | 4 | - **Author or source:** Brahim Hamadicharef (project by Hua Zheng and Shobhit Jain) 5 | - **Created:** 2002-05-24 13:34:45 6 | 7 | - **Linked files:** :download:`rev.txt <../files/rev.txt>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | rev.asm 13 | ECE320 project: Reverberation w/ parameter control from PC 14 | Hua Zheng and Shobhit Jain 15 | 12/02/98 ~ 12/11/98 16 | (se linked file) 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /source/Effects/114-waveshaper-simple-description.rst: -------------------------------------------------------------------------------- 1 | Waveshaper (simple description) 2 | =============================== 3 | 4 | - **Author or source:** Jon Watte 5 | - **Type:** Polynomial; Distortion 6 | - **Created:** 2002-08-15 00:45:22 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | > The other question; what's a 'waveshaper' algorithm. Is it simply another 13 | > word for distortion? 14 | 15 | A typical "waveshaper" is some function which takes an input sample value 16 | X and transforms it to an output sample X'. A typical implementation would 17 | be a look-up table of some number of points, and some level of interpolation 18 | between those points (say, cubic). When people talk about a wave shaper, 19 | this is most often what they mean. Note that a wave shaper, as opposed to a 20 | filter, does not have any state. The mapping from X -> X' is stateless. 21 | 22 | Some wave shapers are implemented as polynomials, or using other math 23 | functions. Hard clipping is a wave shaper implemented using the min() and 24 | max() functions (or the three-argument clamp() function, which is the same 25 | thing). A very mellow and musical-sounding distortion is implemented using 26 | a third-degree polynomial; something like X' = (3/2)X - (1/2)X^3. The nice 27 | thing with polynomial wave shapers is that you know that the maximum they 28 | will expand bandwidth is their order. Thus, you need to oversample 3x to 29 | make sure that a third-degree polynomial is aliasing free. With a lookup 30 | table based wave shaper, you don't know this (unless you treat an N-point 31 | table as an N-point polynomial :-) 32 | 33 | 34 | 35 | .. code-block:: c++ 36 | :linenos: 37 | :caption: code 38 | 39 | float waveshape_distort( float in ) { 40 | return 1.5f * in - 0.5f * in *in * in; 41 | } 42 | 43 | 44 | Comments 45 | -------- 46 | 47 | - **Date**: 2005-06-30 09:41:07 48 | - **By**: ed.luosfosruoivas@naitsirhC 49 | 50 | .. code-block:: text 51 | 52 | Yes! It's one of the most simple waveshaper and you know the amount of oversampling! 53 | Works very nice (and fast). -------------------------------------------------------------------------------- /source/Effects/126-time-compression-expansion-using-standard-phase-vocoder.rst: -------------------------------------------------------------------------------- 1 | Time compression-expansion using standard phase vocoder 2 | ======================================================= 3 | 4 | - **Author or source:** Cournape 5 | - **Type:** vocoder phase time stretching 6 | - **Created:** 2002-12-01 21:15:54 7 | 8 | - **Linked files:** :download:`vocoder.m <../files/vocoder.m>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | Standard phase vocoder. For imporved techniques ( faster ), see paper of Laroche : 14 | "Improved phase vocoder time-scale modification of audio" 15 | Laroche, J.; Dolson, M. 16 | Speech and Audio Processing, IEEE Transactions on , Volume: 7 Issue: 3 , May 1999 17 | Page(s): 323 -332 18 | -------------------------------------------------------------------------------- /source/Effects/139-lo-fi-crusher.rst: -------------------------------------------------------------------------------- 1 | Lo-Fi Crusher 2 | ============= 3 | 4 | - **Author or source:** David Lowenfels 5 | - **Type:** Quantizer / Decimator with smooth control 6 | - **Created:** 2003-04-01 15:34:40 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Yet another bitcrusher algorithm. But this one has smooth parameter control. 13 | 14 | Normfreq goes from 0 to 1.0; (freq/samplerate) 15 | Input is assumed to be between 0 and 1. 16 | Output gain is greater than unity when bits < 1.0; 17 | 18 | 19 | .. code-block:: matlab 20 | :linenos: 21 | :caption: code 22 | 23 | function output = crusher( input, normfreq, bits ); 24 | step = 1/2^(bits); 25 | phasor = 0; 26 | last = 0; 27 | 28 | for i = 1:length(input) 29 | phasor = phasor + normfreq; 30 | if (phasor >= 1.0) 31 | phasor = phasor - 1.0; 32 | last = step * floor( input(i)/step + 0.5 ); %quantize 33 | end 34 | output(i) = last; %sample and hold 35 | end 36 | end 37 | 38 | Comments 39 | -------- 40 | 41 | - **Date**: 2004-06-16 21:10:39 42 | - **By**: moc.liamtoh@132197kk 43 | 44 | .. code-block:: text 45 | 46 | what's the "bits" here? I tried to run the code, it seems it's a dead loop here, can not 47 | figure out why 48 | 49 | - **Date**: 2005-10-26 23:25:13 50 | - **By**: dfl 51 | 52 | .. code-block:: text 53 | 54 | bits goes from 1 to 16 55 | 56 | - **Date**: 2016-03-19 02:47:47 57 | - **By**: moc.liamg@tnemniatretnEesneS2 58 | 59 | .. code-block:: text 60 | 61 | I'm having trouble with the code as well. Is there something I'm missing? 62 | 63 | -------------------------------------------------------------------------------- /source/Effects/150-reverberation-algorithms-in-matlab.rst: -------------------------------------------------------------------------------- 1 | Reverberation Algorithms in Matlab 2 | ================================== 3 | 4 | - **Author or source:** Gautham J. Mysore (moc.oohay@mjmahtuag) 5 | - **Created:** 2003-07-15 08:58:05 6 | 7 | - **Linked files:** :download:`MATLABReverb.zip <../files/MATLABReverb.zip>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | These M-files implement a few reverberation algorithms (based on Schroeder's and Moorer's 13 | algorithms). Each of the M-files include a short description. 14 | 15 | There are 5 M-files that implement reverberation. They are: 16 | 17 | - schroeder1.m 18 | - schroeder2.m 19 | - schroeder3.m 20 | - moorer.m 21 | - stereoverb.m 22 | 23 | The remaining 8 M-files implement filters, delay lines etc. Most of these are used in the 24 | above M-files. They can also be used as building blocks for other reverberation 25 | algorithms. 26 | 27 | 28 | 29 | Comments 30 | -------- 31 | 32 | - **Date**: 2003-08-15 04:04:56 33 | - **By**: moc.loa@mnijwerb 34 | 35 | .. code-block:: text 36 | 37 | StereoVerb is the name of an old car stereo "enhancer" from way back. I was just trying to find 38 | it's roots. 39 | 40 | - **Date**: 2004-04-02 04:44:46 41 | - **By**: moc.oohay@y_sunave 42 | 43 | .. code-block:: text 44 | 45 | There is another allpass filter transfer function. 46 | -g+Z^(-m) 47 | H(z)=------------ 48 | 1-gZ^(-m) 49 | 50 | g is the attenuation 51 | m is the number of delay (in sampel) 52 | 53 | This allpass will give exponential decay impulse response, compare to your allpass that give 54 | half sinc decay impulse response. 55 | 56 | -------------------------------------------------------------------------------- /source/Effects/154-most-simple-and-smooth-feedback-delay.rst: -------------------------------------------------------------------------------- 1 | Most simple and smooth feedback delay 2 | ===================================== 3 | 4 | - **Author or source:** moc.liamtoh@sisehtnysorpitna 5 | - **Type:** Feedback delay 6 | - **Created:** 2003-09-03 12:58:52 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | fDlyTime = delay time parameter (0-1) 13 | 14 | i = input index 15 | j = delay index 16 | 17 | 18 | .. code-block:: c++ 19 | :linenos: 20 | :caption: code 21 | 22 | if( i >= SampleRate ) 23 | i = 0; 24 | 25 | j = i - (fDlyTime * SampleRate); 26 | 27 | if( j < 0 ) 28 | j += SampleRate; 29 | 30 | Output = DlyBuffer[ i++ ] = Input + (DlyBuffer[ j ] * fFeedback); 31 | 32 | Comments 33 | -------- 34 | 35 | - **Date**: 2003-09-03 13:25:47 36 | - **By**: moc.liamtoh@sisehtnysorpitna 37 | 38 | .. code-block:: c++ 39 | 40 | // This algo didn't seem to work on testing again, just change: 41 | // ------------------------------------------------------------------- 42 | Output = DlyBuffer[ i++ ] = Input + (DlyBuffer[ j ] * fFeedback); 43 | // ------------------------------------------------------------------- 44 | // to 45 | // --------------------------------------------------------------- 46 | Output = DlyBuffer[ i ] = Input + (DlyBuffer[ j ] * fFeedback); 47 | 48 | i++; 49 | // --------------------------------------------------------------- 50 | // and it will work fine. 51 | 52 | - **Date**: 2003-09-08 12:07:22 53 | - **By**: moc.liamtoh@sisehtnysorpitna 54 | 55 | .. code-block:: c++ 56 | 57 | // Here's a more clear source. both BufferSize and MaxDlyTime are amounts of samples. BufferSize 58 | // should best be 2*MaxDlyTime to have proper sound. 59 | // - 60 | if( i >= BufferSize ) 61 | i = 0; 62 | 63 | j = i - (fDlyTime * MaxDlyTime); 64 | 65 | if( j < 0 ) 66 | j += BufferSize; 67 | 68 | Output = DlyBuffer[ i ] = Input + (DlyBuffer[ j ] * fFeedback); 69 | 70 | i++; 71 | -------------------------------------------------------------------------------- /source/Effects/177-transistor-differential-amplifier-simulation.rst: -------------------------------------------------------------------------------- 1 | Transistor differential amplifier simulation 2 | ============================================ 3 | 4 | - **Author or source:** ed.luosfosruoivas@naitsirhC 5 | - **Type:** Waveshaper 6 | - **Created:** 2004-08-09 07:46:11 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Writting an exam about electronic components, i learned several equations about simulating 13 | that stuff. One simplified equation was the tanh(x) formula for the differential 14 | amplifier. It is not exact, but since the amplifiers are driven with only small amplitudes 15 | the behaviour is most often even advanced linear. 16 | The fact, that the amp is differential, means, that the 2n order is eliminated, so the 17 | sound is also similar to a tube. 18 | For a very fast use, this code is in pure assembly language (not optimized with SSE-Code 19 | yet) and performs in VST-Plugins very fast. 20 | The code was written in delphi and if you want to translate the assembly code, you should 21 | know, the the parameters passing is done via registers. So pinp=EAX pout=EDX sf=ECX. 22 | 23 | 24 | .. code-block:: delphi 25 | :linenos: 26 | :caption: code 27 | 28 | procedure Transistor(pinp,pout : PSingle; sf:Integer; Faktor: Single); 29 | asm 30 | fld Faktor 31 | @Start: 32 | fld [eax].single 33 | fmul st(0),st(1) 34 | 35 | fldl2e 36 | fmul 37 | fld st(0) 38 | frndint 39 | fsub st(1),st 40 | fxch st(1) 41 | f2xm1 42 | fld1 43 | fadd 44 | fscale { result := z * 2**i } 45 | fstp st(1) 46 | 47 | fld st(0) 48 | fmulp 49 | 50 | fld st(0) 51 | fld1 52 | faddp 53 | fld1 54 | fsubp st(2),st(0) 55 | fdivp 56 | 57 | fstp [edx].single 58 | 59 | add eax,4 60 | add edx,4 61 | loop @Start 62 | fstp st(0) 63 | end; 64 | 65 | -------------------------------------------------------------------------------- /source/Effects/203-fold-back-distortion.rst: -------------------------------------------------------------------------------- 1 | Fold back distortion 2 | ==================== 3 | 4 | - **Author or source:** ed.bpu@eriflleh 5 | - **Type:** distortion 6 | - **Created:** 2005-05-28 19:11:06 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | a simple fold-back distortion filter. 13 | if the signal exceeds the given threshold-level, it mirrors at the positive/negative 14 | threshold-border as long as the singal lies in the legal range (-threshold..+threshold). 15 | there is no range limit, so inputs doesn't need to be in -1..+1 scale. 16 | threshold should be >0 17 | depending on use (low thresholds) it makes sense to rescale the input to full amplitude 18 | 19 | performs approximately the following code 20 | (just without the loop) 21 | 22 | while (in>threshold || in<-threshold) 23 | { 24 | // mirror at positive threshold 25 | if (in>threshold) in= threshold - (in-threshold); 26 | // mirror at negative threshold 27 | if (in<-threshold) in= -threshold + (-threshold-in); 28 | } 29 | 30 | 31 | 32 | .. code-block:: c++ 33 | :linenos: 34 | :caption: code 35 | 36 | float foldback(float in, float threshold) 37 | { 38 | if (in>threshold || in<-threshold) 39 | { 40 | in= fabs(fabs(fmod(in - threshold, threshold*4)) - threshold*2) - threshold; 41 | } 42 | return in; 43 | } 44 | 45 | 46 | -------------------------------------------------------------------------------- /source/Effects/204-simple-compressor-class-c.rst: -------------------------------------------------------------------------------- 1 | Simple Compressor class (C++) 2 | ============================= 3 | 4 | - **Author or source:** Citizen Chunk 5 | - **Type:** stereo, feed-forward, peak compressor 6 | - **Created:** 2005-05-28 19:11:42 7 | 8 | - **Linked files:** :download:`simpleSource.zip <../files/simpleSource.zip>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | Everyone seems to want to make their own compressor plugin these days, but very few know 14 | where to start. After replying to so many questions on the KVR Dev Forum, I figured I 15 | might as well just post some ready-to-use C++ source code. 16 | 17 | This is a C++ implementation of a simple, stereo, peak compressor. It uses a feed-forward 18 | topology, detecting the sidechain level pre-gain reduction. The sidechain detects the 19 | rectified peak level, with stereo linking to preserve imaging. The attack/release uses the 20 | EnvelopeDetector class (posted in the Analysis section). 21 | 22 | Notes: 23 | - Make sure to call initRuntime() before processing starts (i.e. call it in resume()). 24 | - The process function takes a stereo input. 25 | - VST params must be mapped to a practical range when setting compressor parameters. (i.e. 26 | don't try setAttack( 0.f ).) 27 | 28 | (see linked files) 29 | 30 | 31 | 32 | Comments 33 | -------- 34 | 35 | - **Date**: 2005-11-26 01:56:48 36 | - **By**: moc.liamtoh@361_lt 37 | 38 | .. code-block:: text 39 | 40 | This code works perfectly, and I have tried a number of sound and each worked correctly. The 41 | conversion is linear in logarithm domain. 42 | 43 | The code has been written in such a professional style, can not believe it is FREE!! 44 | 45 | Keep it up. Two super huge thumbs up. 46 | 47 | Ting -------------------------------------------------------------------------------- /source/Effects/41-waveshaper.rst: -------------------------------------------------------------------------------- 1 | WaveShaper 2 | ========== 3 | 4 | - **Author or source:** Bram de Jong 5 | - **Type:** waveshaper 6 | - **Created:** 2002-01-17 02:17:49 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | where x (in [-1..1] will be distorted and a is a distortion parameter that goes from 1 to 13 | infinity 14 | The equation is valid for positive and negativ values. 15 | If a is 1, it results in a slight distortion and with bigger a's the signal get's more 16 | funky. 17 | 18 | A good thing about the shaper is that feeding it with bigger-than-one 19 | values, doesn't create strange fx. The maximum this function will reach is 20 | 1.2 for a=1. 21 | 22 | 23 | .. code-block:: c++ 24 | :linenos: 25 | :caption: code 26 | 27 | f(x,a) = x*(abs(x) + a)/(x^2 + (a-1)*abs(x) + 1) -------------------------------------------------------------------------------- /source/Effects/42-soft-saturation.rst: -------------------------------------------------------------------------------- 1 | Soft saturation 2 | =============== 3 | 4 | - **Author or source:** Bram de Jong 5 | - **Type:** waveshaper 6 | - **Created:** 2002-01-17 02:18:37 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This only works for positive values of x. a should be in the range 0..1 13 | 14 | 15 | .. code-block:: c++ 16 | :linenos: 17 | :caption: code 18 | 19 | x < a: 20 | f(x) = x 21 | x > a: 22 | f(x) = a + (x-a)/(1+((x-a)/(1-a))^2) 23 | x > 1: 24 | f(x) = (a+1)/2 25 | 26 | Comments 27 | -------- 28 | 29 | - **Date**: 2005-09-09 21:17:55 30 | - **By**: gro.esabnaeco@euarg 31 | 32 | .. code-block:: text 33 | 34 | This is a most excellent waveshaper. 35 | 36 | I have implemented it as an effect for the music tracker Psycle, and so far I am very pleased with the 37 | results. Thanks for sharing this knowledge, Bram! 38 | 39 | - **Date**: 2006-03-12 02:35:16 40 | - **By**: moc.erawtfosnetpot@nosniborb 41 | 42 | .. code-block:: text 43 | 44 | I'm wondering about the >1 condition here. If a is 0.8, values <1 approach 0.85 but values >1 45 | are clamped to 0.9 (there's a gap) 46 | 47 | If you substitute x=1 to the equation for x>a you get: a+((1-a)/4) not (a+1)/2 48 | 49 | Have I missed something or is there a reason for this? 50 | 51 | (Go easy I'm new to all of this) 52 | 53 | - **Date**: 2006-08-23 06:19:05 54 | - **By**: moc.liamg@ubibik 55 | 56 | .. code-block:: text 57 | 58 | Substituting x=1 into equation 2 (taking many steps) 59 | 60 | f(x) = a + (x-a)/(1+ ((x-a)/(1-a))^2) 61 | = a + (1-a)/(1+ ((1-a)/(1-a))^2) 62 | = a + (1-a)/(1+ 1^2) 63 | = a + (1-a)/2 64 | = 2a/2 + (1-a)/2 65 | = (2a + 1 - a) /2 66 | = (a+1) / 2 67 | 68 | - **Date**: 2006-08-24 11:03:04 69 | - **By**: musicdsp@Nospam dsparsons.co.uk 70 | 71 | .. code-block:: text 72 | 73 | You can normalise the output: 74 | f(x)'=f(x)*(1/((a+1)/2)) 75 | 76 | This gives a nice variable shaper with smooth curve upto clipping at 0dBFS 77 | 78 | -------------------------------------------------------------------------------- /source/Effects/43-waveshaper.rst: -------------------------------------------------------------------------------- 1 | Waveshaper 2 | ========== 3 | 4 | - **Author or source:** Jon Watte 5 | - **Type:** waveshaper 6 | - **Created:** 2002-01-17 02:19:17 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | A favourite of mine is using a sin() function instead. 13 | This will have the "unfortunate" side effect of removing 14 | odd harmonics if you take it to the extreme: a triangle 15 | wave gets mapped to a pure sine wave. 16 | This will work with a going from .1 or so to a= 5 and bigger! 17 | The mathematical limits for a = 0 actually turns it into a linear 18 | function at that point, but unfortunately FPUs aren't that good 19 | with calculus :-) Once a goes above 1, you start getting clipping 20 | in addition to the "soft" wave shaping. It starts getting into 21 | more of an effect and less of a mastering tool, though :-) 22 | 23 | Seeing as this is just various forms of wave shaping, you 24 | could do it all with a look-up table, too. In my version, that would 25 | get rid of the somewhat-expensive sin() function. 26 | 27 | 28 | .. code-block:: c++ 29 | :linenos: 30 | :caption: code 31 | 32 | (input: a == "overdrive amount") 33 | 34 | z = M_PI * a; 35 | s = 1/sin(z) 36 | b = 1/a 37 | 38 | if (x > b) 39 | f(x) = 1 40 | else 41 | f(x) = sin(z*x)*s 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /source/Effects/44-delay-time-calculation-for-reverberation.rst: -------------------------------------------------------------------------------- 1 | Delay time calculation for reverberation 2 | ======================================== 3 | 4 | - **Author or source:** Andy Mucho 5 | - **Created:** 2002-01-17 02:19:54 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | This is from some notes I had scribbled down from a while back on 12 | automatically calculating diffuse delays. Given an intial delay line gain 13 | and time, calculate the times and feedback gain for numlines delay lines.. 14 | 15 | 16 | .. code-block:: c++ 17 | :linenos: 18 | :caption: code 19 | 20 | int numlines = 8; 21 | float t1 = 50.0; // d0 time 22 | float g1 = 0.75; // d0 gain 23 | float rev = -3*t1 / log10 (g1); 24 | 25 | for (int n = 0; n < numlines; ++n) 26 | { 27 | float dt = t1 / pow (2, (float (n) / numlines)); 28 | float g = pow (10, -((3*dt) / rev)); 29 | printf ("d%d t=%.3f g=%.3f\n", n, dt, g); 30 | } 31 | 32 | /* 33 | The above with t1=50.0 and g1=0.75 yields: 34 | 35 | d0 t=50.000 g=0.750 36 | d1 t=45.850 g=0.768 37 | d2 t=42.045 g=0.785 38 | d3 t=38.555 g=0.801 39 | d4 t=35.355 g=0.816 40 | d5 t=32.421 g=0.830 41 | d6 t=29.730 g=0.843 42 | d7 t=27.263 g=0.855 43 | 44 | To go more diffuse, chuck in dual feedback paths with a one cycle delay 45 | effectively creating a phase-shifter in the feedback path, then things get 46 | more exciting.. Though what the optimum phase shifts would be I couldn't 47 | tell you right now.. 48 | */ -------------------------------------------------------------------------------- /source/Effects/45-reverberation-techniques.rst: -------------------------------------------------------------------------------- 1 | Reverberation techniques 2 | ======================== 3 | 4 | - **Author or source:** Sean Costello 5 | - **Created:** 2002-02-10 20:00:11 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | * Parallel comb filters, followed by series allpass filters. This was the original design 12 | by Schroeder, and was extended by Moorer. Has a VERY metallic sound for sharp transients. 13 | 14 | * Several allpass filters in serie (also proposed by Schroeder). Also suffers from 15 | metallic sound. 16 | 17 | * 2nd-order comb and allpass filters (described by Moorer). Not supposed to give much of 18 | an advantage over first order sections. 19 | 20 | * Nested allpass filters, where an allpass filter will replace the delay line in another 21 | allpass filter. Pioneered by Gardner. Haven't heard the results. 22 | 23 | * Strange allpass amp delay line based structure in Jon Dattorro article (JAES). Four 24 | allpass filters are used as an input to a cool "figure-8" feedback loop, where four 25 | allpass reverberators are used in series with 26 | a few delay lines. Outputs derived from various taps in structure. Supposedly based on a 27 | Lexicon reverb design. Modulating delay lines are used in some of the allpass structures 28 | to "spread out" the eigentones. 29 | 30 | * Feedback Delay Networks. Pioneered by Puckette/Stautner, with Jot conducting extensive 31 | recent research. Sound VERY good, based on initial experiments. Modulating delay lines and 32 | feedback matrixes used to spread out eigentones. 33 | 34 | * Waveguide-based reverbs, where the reverb structure is based upon the junction of many 35 | waveguides. Julius Smith developed these. Recently, these have been shown to be 36 | essentially equivalent to the feedback delay network reverbs. Also sound very nice. 37 | Modulating delay lines and scattering values used to spread out eigentones. 38 | 39 | * Convolution-based reverbs, where the sound to be reverbed is convolved with the impulse 40 | response of a room, or with exponentially-decaying white noise. Supposedly the best sound, 41 | but very computationally expensive, and not very flexible. 42 | 43 | * FIR-based reverbs. Essentially the same as convolution. Probably not used, but shorter 44 | FIR filters are probably used in combination with many of the above techniques, to provide 45 | early reflections. 46 | -------------------------------------------------------------------------------- /source/Effects/46-waveshaper.rst: -------------------------------------------------------------------------------- 1 | Waveshaper 2 | ========== 3 | 4 | - **Author or source:** Partice Tarrabia and Bram de Jong 5 | - **Created:** 2002-01-17 02:21:49 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | amount should be in [-1..1[ Plot it and stand back in astonishment! ;) 12 | 13 | 14 | .. code-block:: text 15 | :linenos: 16 | :caption: code 17 | 18 | x = input in [-1..1] 19 | y = output 20 | k = 2*amount/(1-amount); 21 | 22 | f(x) = (1+k)*x/(1+k*abs(x)) 23 | 24 | Comments 25 | -------- 26 | 27 | - **Date**: 2002-06-27 07:15:59 28 | - **By**: moc.noicratse@ajelak 29 | 30 | .. code-block:: text 31 | 32 | I haven't compared this to the other waveshapers, but its behavior with input outside the [-1..1] 33 | range is interesting. With a relatively moderate shaping amounts which don't distort in-range 34 | signals severely, it damps extremely out-of-range signals fairly hard, e.g. x = 100, 35 | k = 0.1 yields y = 5.26; as x goes to infinity, y approaches 5.5. This might come in handy 36 | to control nonlinear processes which would otherwise be prone to computational blowup. -------------------------------------------------------------------------------- /source/Effects/70-alien-wah.rst: -------------------------------------------------------------------------------- 1 | Alien Wah 2 | ========= 3 | 4 | - **Author or source:** Nasca Octavian Paul (or.liame@acsanluap) 5 | - **Created:** 2002-02-10 12:51:57 6 | 7 | - **Linked files:** :download:`alienwah.c <../files/alienwah.c>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | I found this algoritm by "playing around" with complex numbers. Please email me your 13 | opinions about it. 14 | 15 | Paul. -------------------------------------------------------------------------------- /source/Effects/74-early-echo-s-with-image-mirror-technique.rst: -------------------------------------------------------------------------------- 1 | Early echo's with image-mirror technique 2 | ======================================== 3 | 4 | - **Author or source:** Donald Schulz 5 | - **Created:** 2002-02-11 17:35:48 6 | 7 | - **Linked files:** :download:`early_echo.c <../files/early_echo.c>`. 8 | - **Linked files:** :download:`early_echo_eng.c <../files/early_echo_eng.c>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | (see linked files) 14 | Donald Schulz's code for computing early echoes using the image-mirror method. There's an 15 | english and a german version. 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/Effects/89-2-wave-shaping-things.rst: -------------------------------------------------------------------------------- 1 | 2 Wave shaping things 2 | ===================== 3 | 4 | - **Author or source:** Frederic Petrot 5 | - **Created:** 2002-03-20 01:12:01 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | Makes nice saturations effects that can be easilly computed using cordic 12 | First using a atan function: 13 | y1 using k=16 14 | max is the max value you can reach (32767 would be a good guess) 15 | Harmonics scale down linealy and not that fast 16 | 17 | Second using the hyperbolic tangent function: 18 | y2 using k=2 19 | Harmonics scale down linealy very fast 20 | 21 | 22 | .. code-block:: c++ 23 | :linenos: 24 | :caption: code 25 | 26 | y1 = (max>>1) * atan(k * x/max) 27 | 28 | y2 = max * th(x/max) 29 | 30 | Comments 31 | -------- 32 | 33 | - **Date**: 2006-06-26 01:12:05 34 | - **By**: ten.labolgcbs@rohtlabi 35 | 36 | .. code-block:: text 37 | 38 | Why are you calling decompiled script code?BALTHOR 39 | 40 | - **Date**: 2013-01-18 02:20:59 41 | - **By**: moc.liamtoh@niffumtohrepus 42 | 43 | .. code-block:: text 44 | 45 | Yeah, atan & tanh, and really any sigmoid function, can create decent overdrive sound if 46 | oversampled and eq'ed properly. I've used them in some of my modelers w/ good results. For 47 | a more realistic sound, two half-wave soft clippers in series will add duty-cycle modulation 48 | and a transfer curve similar to 3/2 tube power curve. Something like: 49 | if(x < 0) y = -A * tanh(B * x); followed immediately by: if(y >= 0) y = -A * tanh(B * y); 50 | Don't forget to invert each output (-A * tanh). Coefficients A & B are left to the designer. 51 | I got this technique after reading a paper discussing a hardware implementation of this type 52 | of circuit used in Carvin amps, here: http://www.trueaudio.com/at_eetjlm.htm (original link at 53 | www.simulanalog.org) 54 | 55 | -------------------------------------------------------------------------------- /source/Effects/96-bit-quantization-reduction-effect.rst: -------------------------------------------------------------------------------- 1 | Bit quantization/reduction effect 2 | ================================= 3 | 4 | - **Author or source:** Jon Watte 5 | - **Type:** Bit-level noise-generating effect 6 | - **Created:** 2002-04-12 13:53:03 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This function, run on each sample, will emulate half the effect of running your signal 13 | through a Speak-N-Spell or similar low-bit-depth circuitry. 14 | 15 | The other half would come from downsampling with no aliasing control, i e replicating 16 | every N-th sample N times in the output signal. 17 | 18 | 19 | .. code-block:: c++ 20 | :linenos: 21 | :caption: code 22 | 23 | short keep_bits_from_16( short input, int keepBits ) { 24 | return (input & (-1 << (16-keepBits))); 25 | } 26 | 27 | 28 | 29 | Comments 30 | -------- 31 | 32 | - **Date**: 2005-05-30 23:01:56 33 | - **By**: moc.liamg@codlli 34 | 35 | .. code-block:: c++ 36 | 37 | //I add some code to prevent offset. 38 | 39 | // Code : 40 | short keep_bits_from_16( short input, int keepBits ) { 41 | short prevent_offset = static_cast(-1) >> keepBits+1; 42 | input &= (-1 << (16-keepBits))); 43 | return input + prevent_offset 44 | } -------------------------------------------------------------------------------- /source/Effects/98-class-for-waveguide-delay-effects.rst: -------------------------------------------------------------------------------- 1 | Class for waveguide/delay effects 2 | ================================= 3 | 4 | - **Author or source:** moc.xinortceletrams@urugra 5 | - **Type:** IIR filter 6 | - **Created:** 2002-04-23 06:46:34 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Flexible-time, non-sample quantized delay , can be used for stuff like waveguide synthesis 13 | or time-based (chorus/flanger) fx. 14 | 15 | MAX_WG_DELAY is a constant determining MAX buffer size (in samples) 16 | 17 | 18 | .. code-block:: c++ 19 | :linenos: 20 | :caption: code 21 | 22 | class cwaveguide 23 | { 24 | public: 25 | cwaveguide(){clear();} 26 | virtual ~cwaveguide(){}; 27 | 28 | void clear() 29 | { 30 | counter=0; 31 | for(int s=0;s=MAX_WG_DELAY)index1=0; 55 | if(index2>=MAX_WG_DELAY)index2=0; 56 | 57 | // get neighbourgh samples 58 | float const y_1= buffer [index_1]; 59 | float const y0 = buffer [index0]; 60 | float const y1 = buffer [index1]; 61 | float const y2 = buffer [index2]; 62 | 63 | // compute interpolation x 64 | float const x=(float)back-(float)index0; 65 | 66 | // calculate 67 | float const c0 = y0; 68 | float const c1 = 0.5f*(y1-y_1); 69 | float const c2 = y_1 - 2.5f*y0 + 2.0f*y1 - 0.5f*y2; 70 | float const c3 = 0.5f*(y2-y_1) + 1.5f*(y0-y1); 71 | 72 | float const output=((c3*x+c2)*x+c1)*x+c0; 73 | 74 | // add to delay buffer 75 | buffer[counter]=in+output*feedback; 76 | 77 | // increment delay counter 78 | counter++; 79 | 80 | // clip delay counter 81 | if(counter>=MAX_WG_DELAY) 82 | counter=0; 83 | 84 | // return output 85 | return output; 86 | } 87 | 88 | float buffer[MAX_WG_DELAY]; 89 | int counter; 90 | }; 91 | 92 | 93 | -------------------------------------------------------------------------------- /source/Effects/index.rst: -------------------------------------------------------------------------------- 1 | Effects 2 | ======= 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :caption: Contents: 7 | 8 | 89-2-wave-shaping-things 9 | 70-alien-wah 10 | 221-band-limited-pwm-generator 11 | 96-bit-quantization-reduction-effect 12 | 98-class-for-waveguide-delay-effects 13 | 169-compressor 14 | 124-decimator 15 | 44-delay-time-calculation-for-reverberation 16 | 207-dynamic-convolution 17 | 102-ece320-project-reverberation-w-parameter-control-from-pc 18 | 74-early-echo-s-with-image-mirror-technique 19 | 203-fold-back-distortion 20 | 47-guitar-feedback 21 | 139-lo-fi-crusher 22 | 274-lookahead-limiter 23 | 154-most-simple-and-smooth-feedback-delay 24 | 153-most-simple-static-delay 25 | 101-parallel-combs-delay-calculation 26 | 78-phaser-code 27 | 230-polynominal-waveshaper 28 | 150-reverberation-algorithms-in-matlab 29 | 45-reverberation-techniques 30 | 204-simple-compressor-class-c 31 | 42-soft-saturation 32 | 173-stereo-enhancer 33 | 255-stereo-field-rotation-via-transformation-matrix 34 | 256-stereo-width-control-obtained-via-transfromation-matrix 35 | 126-time-compression-expansion-using-standard-phase-vocoder 36 | 177-transistor-differential-amplifier-simulation 37 | 277-univox-univibe-emulator 38 | 104-variable-hardness-clipping-function 39 | 41-waveshaper 40 | 43-waveshaper 41 | 46-waveshaper 42 | 114-waveshaper-simple-description 43 | 86-waveshaper-gloubi-boulga 44 | -------------------------------------------------------------------------------- /source/Filters/116-one-pole-lp-and-hp.rst: -------------------------------------------------------------------------------- 1 | One pole LP and HP 2 | ================== 3 | 4 | - **Author or source:** Bram 5 | - **Created:** 2002-08-26 23:33:27 6 | 7 | 8 | 9 | .. code-block:: c++ 10 | :linenos: 11 | :caption: code 12 | 13 | LP: 14 | recursion: tmp = (1-p)*in + p*tmp with output = tmp 15 | coefficient: p = (2-cos(x)) - sqrt((2-cos(x))^2 - 1) with x = 2*pi*cutoff/samplerate 16 | coeficient approximation: p = (1 - 2*cutoff/samplerate)^2 17 | 18 | HP: 19 | recursion: tmp = (p-1)*in - p*tmp with output = tmp 20 | coefficient: p = (2+cos(x)) - sqrt((2+cos(x))^2 - 1) with x = 2*pi*cutoff/samplerate 21 | coeficient approximation: p = (2*cutoff/samplerate)^2 22 | 23 | Comments 24 | -------- 25 | 26 | - **Date**: 2006-03-23 15:39:07 27 | - **By**: moc.liamtoh@wta_sohpyks 28 | 29 | .. code-block:: text 30 | 31 | coefficient: p = (2-cos(x)) - sqrt((2-cos(x))^2 - 1) with x = 2*pi*cutoff/samplerate 32 | 33 | p is always -1 using the formula above. The square eliminates the squareroot and (2-cos(x)) - (2-cos(x)) is 0. 34 | 35 | - **Date**: 2006-03-24 09:37:19 36 | - **By**: q@q 37 | 38 | .. code-block:: text 39 | 40 | Look again. The -1 is inside the sqrt. 41 | 42 | - **Date**: 2008-08-11 09:34:07 43 | - **By**: batlord[.A.T.]o2[.D.O.T.]pl 44 | 45 | .. code-block:: text 46 | 47 | skyphos: 48 | sqrt((2-cos(x))^2 - 1) doesn't equal 49 | sqrt((2-cos(x))^2) + sqrt(- 1) 50 | 51 | so 52 | 53 | -1 can be inside the sqrt, because (2-cos(x))^2 will be always >= one. 54 | 55 | 56 | - **Date**: 2009-07-13 01:22:43 57 | - **By**: No 58 | 59 | .. code-block:: text 60 | 61 | HP is wrong! 62 | Or at least it does not work here. It acts like a lofi low-shelf. However this works: 63 | 64 | HP: 65 | recursion: tmp = (1-p)*in + p*tmp with output = in-tmp 66 | coefficient: p = (2-cos(x)) - sqrt((2-cos(x))^2 - 1) with x = 2*pi*cutoff/samplerate 67 | coeficient approximation: p = (1 - 2*cutoff/samplerate)^2 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /source/Filters/118-one-zero-lp-hp.rst: -------------------------------------------------------------------------------- 1 | One zero, LP/HP 2 | =============== 3 | 4 | - **Author or source:** Bram 5 | - **Created:** 2002-08-29 23:18:43 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | LP is only 'valid' for cutoffs > samplerate/4 12 | HP is only 'valid' for cutoffs < samplerate/4 13 | 14 | 15 | 16 | .. code-block:: c++ 17 | :linenos: 18 | :caption: code 19 | 20 | theta = cutoff*2*pi / samplerate 21 | 22 | LP: 23 | H(z) = (1+p*z^(-1)) / (1+p) 24 | out[i] = 1/(1+p) * in[i] + p/(1+p) * in[i-1]; 25 | p = (1-2*cos(theta)) - sqrt((1-2*cos(theta))^2 - 1) 26 | Pi/2 < theta < Pi 27 | 28 | HP: 29 | H(z) = (1-p*z^(-1)) / (1+p) 30 | out[i] = 1/(1+p) * in[i] - p/(1+p) * in[i-1]; 31 | p = (1+2*cos(theta)) - sqrt((1+2*cos(theta))^2 - 1) 32 | 0 < theta < Pi/2 33 | 34 | -------------------------------------------------------------------------------- /source/Filters/128-c-class-implementation-of-rbj-filters.rst: -------------------------------------------------------------------------------- 1 | C++ class implementation of RBJ Filters 2 | ======================================= 3 | 4 | - **Author or source:** moc.xinortceletrams@urugra 5 | - **Created:** 2002-12-13 01:37:52 6 | 7 | - **Linked files:** :download:`CFxRbjFilter.h <../files/CFxRbjFilter.h>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | [WARNING: This code is not FPU undernormalization safe!] 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /source/Filters/135-dc-filter.rst: -------------------------------------------------------------------------------- 1 | DC filter 2 | ========= 3 | 4 | - **Author or source:** hc.niweulb@lossor.ydna 5 | - **Type:** 1-pole/1-zero DC filter 6 | - **Created:** 2003-01-04 01:18:23 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This is based on code found in the document: 13 | "Introduction to Digital Filters (DRAFT)" 14 | Julius O. Smith III (jos@ccrma.stanford.edu) 15 | (http://www-ccrma.stanford.edu/~jos/filters/) 16 | --- 17 | 18 | Some audio algorithms (asymmetric waveshaping, cascaded filters, ...) can produce DC 19 | offset. This offset can accumulate and reduce the signal/noise ratio. 20 | 21 | So, how to fix it? The example code from Julius O. Smith's document is: 22 | ... 23 | y(n) = x(n) - x(n-1) + R * y(n-1) 24 | // "R" between 0.9 .. 1 25 | // n=current (n-1)=previous in/out value 26 | ... 27 | "R" depends on sampling rate and the low frequency point. Do not set "R" to a fixed value 28 | (e.g. 0.99) if you don't know the sample rate. Instead set R to: 29 | (-3dB @ 40Hz): R = 1-(250/samplerate) 30 | (-3dB @ 30Hz): R = 1-(190/samplerate) 31 | (-3dB @ 20Hz): R = 1-(126/samplerate) 32 | 33 | 34 | 35 | 36 | Comments 37 | -------- 38 | 39 | - **Date**: 2003-01-04 01:58:04 40 | - **By**: hc.niweulb@lossor.ydna 41 | 42 | .. code-block:: text 43 | 44 | I just received a mail from a musicdsp reader: 45 | 46 | 'How to calculate "R" for a given (-3dB) low frequency point?' 47 | 48 | R = 1 - (pi*2 * frequency /samplerate) 49 | 50 | (pi=3.14159265358979) 51 | 52 | - **Date**: 2003-05-10 09:11:42 53 | - **By**: ten.labolgfrus@jbr 54 | 55 | .. code-block:: text 56 | 57 | particularly if fixed-point arithmetic is used, this simple high-pass filter can create it's own DC offset because of limit-cycles. to cure that look at 58 | 59 | http://www.dspguru.com/comp.dsp/tricks/alg/dc_block.htm 60 | 61 | this trick uses the concept of "noise-shaping" to prevent DC in any limit-cycles. 62 | 63 | r b-j 64 | 65 | 66 | -------------------------------------------------------------------------------- /source/Filters/185-1-rc-and-c-filter.rst: -------------------------------------------------------------------------------- 1 | 1-RC and C filter 2 | ================= 3 | 4 | - **Author or source:** ac.nortoediv@niarbdam 5 | - **Type:** Simple 2-pole LP 6 | - **Created:** 2004-11-14 22:42:18 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This filter is called 1-RC and C since it uses these two parameters. C and R correspond to 13 | raw cutoff and inverted resonance, and have a range from 0 to 1. 14 | 15 | 16 | 17 | .. code-block:: c++ 18 | :linenos: 19 | :caption: code 20 | 21 | //Parameter calculation 22 | //cutoff and resonance are from 0 to 127 23 | 24 | c = pow(0.5, (128-cutoff) / 16.0); 25 | r = pow(0.5, (resonance+24) / 16.0); 26 | 27 | //Loop: 28 | 29 | v0 = (1-r*c)*v0 - (c)*v1 + (c)*input; 30 | v1 = (1-r*c)*v1 + (c)*v0; 31 | 32 | output = v1; 33 | 34 | 35 | Comments 36 | -------- 37 | 38 | - **Date**: 2005-01-13 18:25:57 39 | - **By**: yes 40 | 41 | .. code-block:: text 42 | 43 | input is not in 0 - 1 range. 44 | 45 | for cutoff i guess 128. 46 | 47 | for reso the same ? 48 | 49 | - **Date**: 2006-08-31 14:28:33 50 | - **By**: uh.etle.fni@yfoocs 51 | 52 | .. code-block:: text 53 | 54 | Nice. This is very similar to a state variable filter in many ways. Relationship between c and frequency: 55 | 56 | c = 2*sin(pi*freq/samplerate) 57 | 58 | You can approximate this (tuning error towards nyquist): 59 | 60 | c = 2*pi*freq/samplerate 61 | 62 | Relationship between r and q factor: 63 | 64 | r = 1/q 65 | 66 | This filter has stability issues for high r values. State variable filter stability limits seem to work fine here. It can also be oversampled for better stability and wider frequency range (use 0.5*original frequency): 67 | 68 | //Loop: 69 | 70 | v0 = (1-r*c)*v0 - c*v1 + c*input; 71 | v1 = (1-r*c)*v1 + c*v0; 72 | tmp = v1; 73 | 74 | v0 = (1-r*c)*v0 - c*v1 + c*input; 75 | v1 = (1-r*c)*v1 + c*v0; 76 | output = (tmp+v1)*0.5; 77 | 78 | -- peter schoffhauzer 79 | 80 | 81 | -------------------------------------------------------------------------------- /source/Filters/195-hilbert-filter-coefficient-calculation.rst: -------------------------------------------------------------------------------- 1 | Hilbert Filter Coefficient Calculation 2 | ====================================== 3 | 4 | - **Author or source:** ed.luosfosruoivas@naitsirhC 5 | - **Type:** Uncle Hilbert 6 | - **Created:** 2005-04-17 19:05:37 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This is the delphi code to create the filter coefficients, which are needed to phaseshift 13 | a signal by 90° 14 | This may be useful for an evelope detector... 15 | 16 | By windowing the filter coefficients you can trade phase response flatness with magnitude 17 | response flatness. 18 | 19 | I had problems checking its response by using a dirac impulse. White noise works fine. 20 | 21 | Also this introduces a latency of N/2! 22 | 23 | 24 | .. code-block:: c++ 25 | :linenos: 26 | :caption: code 27 | 28 | type TSingleArray = Array of Single; 29 | 30 | procedure UncleHilbert(var FilterCoefficients: TSingleArray; N : Integer); 31 | var i,j : Integer; 32 | begin 33 | SetLength(FilterCoefficients,N); 34 | for i:=0 to (N div 4) do 35 | begin 36 | FilterCoefficients[(N div 2)+(2*i-1)]:=+2/(PI*(2*i-1)); 37 | FilterCoefficients[(N div 2)-(2*i-1)]:=-2/(PI*(2*i-1)); 38 | end; 39 | end; 40 | 41 | -------------------------------------------------------------------------------- /source/Filters/198-rbj-audio-eq-cookbook.rst: -------------------------------------------------------------------------------- 1 | RBJ Audio-EQ-Cookbook 2 | ===================== 3 | 4 | - **Author or source:** Robert Bristow-Johnson 5 | - **Created:** 2005-05-04 20:33:31 6 | 7 | - **Linked files:** :download:`EQ-Coefficients.pdf <../files/EQ-Coefficients.pdf>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | see attached file 13 | 14 | 15 | 16 | Comments 17 | -------- 18 | 19 | - **Date**: 2005-05-14 06:35:17 20 | - **By**: eb.tenyks@didid 21 | 22 | .. code-block:: text 23 | 24 | Hi 25 | 26 | In your most recent version, you write: 27 | 28 | -- 29 | alpha = sin(w0)/(2*Q) (case: Q) 30 | = sin(w0)*sinh( ln(2)/2 * BW * w0/sin(w0) ) (case: BW) 31 | = sin(w0)/2 * sqrt( (A + 1/A)*(1/S - 1) + 2 ) (case: S) 32 | -- 33 | 34 | 35 | But the 'slope' case doesn't seem to work for me. It results in some kind of bad resonance at higher samplerates. 36 | 37 | Now I found this 'beta' in an older version of your paper (I think), describing: 38 | 39 | -- 40 | beta = sqrt(A)/Q (for shelving EQ filters only) 41 | = sqrt(A)*sqrt[ (A + 1/A)*(1/S - 1) + 2 ] (if shelf slope is specified) 42 | = sqrt[ (A^2 + 1)/S - (A-1)^2 ] 43 | -- 44 | 45 | ..and here the 46 | sqrt(A)*sqrt[ (A + 1/A)*(1/S - 1) + 2 ] 47 | formula works perfectly for me. 48 | 49 | I must say I don't understand half of the theory, so it's probably my fault somewhere. But why the change in the newer version? 50 | 51 | 52 | - **Date**: 2005-05-20 20:56:45 53 | - **By**: moc.noitanigamioidua@jbr 54 | 55 | .. code-block:: text 56 | 57 | >But why the change in the newer version? 58 | ---------------------------------------------------------- 59 | 60 | i wanted to get rid of an extraneous intermediate variable and there was enough similarity between alpha and beta that i changed the lowShelf and highShelf coefficient equations to be in terms of alpha rather than beta. 61 | 62 | i believe if you use the new version as shown, in terms of alpha (but remember the coef equations are changed accordingly from the old version), it will come up with the same coefficients given the same boost gain, Q (or S), and shelf frequency (and same Fs). lemme know if you still have trouble. 63 | 64 | r b-j 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /source/Filters/208-remez-remez-parks-mcclellan.rst: -------------------------------------------------------------------------------- 1 | Remez Remez (Parks/McClellan) 2 | ============================= 3 | 4 | - **Author or source:** ed.luosfosruoivas@naitsirhC 5 | - **Type:** FIR Remez (Parks/McClellan) 6 | - **Created:** 2005-06-28 21:06:53 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Below you can find a Object Pascal / Delphi Translation of the Remez (Parks/McClellan) FIR 13 | Filter Design algorithm. 14 | It behaves slightly different from the c++ version, but the results work very well. 15 | 16 | 17 | .. code-block:: c++ 18 | :linenos: 19 | :caption: code 20 | 21 | http://www.savioursofsoul.de/Christian/remez.zip 22 | 23 | -------------------------------------------------------------------------------- /source/Filters/209-remez-exchange-algorithm-parks-mcclellan.rst: -------------------------------------------------------------------------------- 1 | Remez Exchange Algorithm (Parks/McClellan) 2 | ========================================== 3 | 4 | - **Author or source:** ed.luosfosruoivas@naitsirhC 5 | - **Type:** Linear Phase FIR Filter 6 | - **Created:** 2006-05-06 08:40:18 7 | 8 | - **Linked files:** :download:`http://www.savioursofsoul.de/Christian/Remez.zip <../files/http://www.savioursofsoul.de/Christian/Remez.zip>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | Here is an object pascal / delphi translation of the Remez Exchange Algorithm by 14 | Parks/McClellan 15 | There is at least one small bug in it (compared to the C++ version), which causes the 16 | result to be slightly different to the C version. 17 | 18 | 19 | .. code-block:: c++ 20 | :linenos: 21 | :caption: code 22 | 23 | http://www.savioursofsoul.de/Christian/Remez.zip 24 | 25 | -------------------------------------------------------------------------------- /source/Filters/226-c-weighed-filter.rst: -------------------------------------------------------------------------------- 1 | C-Weighed Filter 2 | ================ 3 | 4 | - **Author or source:** ed.luosfosruoivas@naitsirhC 5 | - **Type:** digital implementation (after bilinear transform) 6 | - **Created:** 2006-07-12 19:12:16 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | unoptimized version! 13 | 14 | 15 | .. code-block:: c++ 16 | :linenos: 17 | :caption: code 18 | 19 | First prewarp the frequency of both poles: 20 | 21 | K1 = tan(0.5*Pi*20.6 / SampleRate) // for 20.6Hz 22 | K2 = tan(0.5*Pi*12200 / SampleRate) // for 12200Hz 23 | 24 | Then calculate the both biquads: 25 | 26 | b0 = 1 27 | b1 = 0 28 | b2 =-1 29 | a0 = ((K1+1)*(K1+1)*(K2+1)*(K2+1)); 30 | a1 =-4*(K1*K1*K2*K2+K1*K1*K2+K1*K2*K2-K1-K2-1)*t; 31 | a2 =- ((K1-1)*(K1-1)*(K2-1)*(K2-1))*t; 32 | 33 | and: 34 | 35 | b3 = 1 36 | b4 = 0 37 | b5 =-1 38 | a3 = ((K1+1)*(K1+1)*(K2+1)*(K2+1)); 39 | a4 =-4*(K1*K1*K2*K2+K1*K1*K2+K1*K2*K2-K1-K2-1)*t; 40 | a5 =- ((K1-1)*(K1-1)*(K2-1)*(K2-1))*t; 41 | 42 | Now use an equation for calculating the biquads like this: 43 | 44 | Stage1 = b0*Input + State0; 45 | State0 = + a1/a0*Stage1 + State1; 46 | State1 = b2*Input + a2/a0*Stage1; 47 | 48 | Output = b3*Stage1 + State2; 49 | State2 = + a4/a3*Output + State2; 50 | State3 = b5*Stage1 + a5/a3*Output; 51 | 52 | Comments 53 | -------- 54 | 55 | - **Date**: 2006-07-12 21:07:28 56 | - **By**: ed.luosfosruoivas@naitsirhC 57 | 58 | .. code-block:: text 59 | 60 | You might still need to normalize the filter output. You can do this easily by multipliing either the b0 and b2 or the b3 and b5 with a constant. 61 | Typically the filter is normalized to have a gain of 0dB at 1kHz 62 | 63 | Also oversampling of this filter might be useful. 64 | 65 | -------------------------------------------------------------------------------- /source/Filters/235-bass-booster.rst: -------------------------------------------------------------------------------- 1 | Bass Booster 2 | ============ 3 | 4 | - **Author or source:** Johny Dupej 5 | - **Type:** LP and SUM 6 | - **Created:** 2006-08-11 12:47:34 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This function adds a low-passed signal to the original signal. The low-pass has a quite 13 | wide response. 14 | 15 | Params: 16 | selectivity - frequency response of the LP (higher value gives a steeper one) [70.0 to 17 | 140.0 sounds good] 18 | ratio - how much of the filtered signal is mixed to the original 19 | gain2 - adjusts the final volume to handle cut-offs (might be good to set dynamically) 20 | 21 | 22 | .. code-block:: c++ 23 | :linenos: 24 | :caption: code 25 | 26 | #define saturate(x) __min(__max(-1.0,x),1.0) 27 | 28 | float BassBoosta(float sample) 29 | { 30 | static float selectivity, gain1, gain2, ratio, cap; 31 | gain1 = 1.0/(selectivity + 1.0); 32 | 33 | cap= (sample + cap*selectivity )*gain1; 34 | sample = saturate((sample + cap*ratio)*gain2); 35 | 36 | return sample; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /source/Filters/253-perfect-lp4-filter.rst: -------------------------------------------------------------------------------- 1 | Perfect LP4 filter 2 | ================== 3 | 4 | - **Author or source:** rf.eerf@aipotreza 5 | - **Type:** LP 6 | - **Created:** 2008-03-13 10:40:46 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | hacked from the exemple of user script in FL Edison 13 | 14 | 15 | .. code-block:: c++ 16 | :linenos: 17 | :caption: code 18 | 19 | TLP24DB = class 20 | constructor create; 21 | procedure process(inp,Frq,Res:single;SR:integer); 22 | private 23 | t, t2, x, f, k, p, r, y1, y2, y3, y4, oldx, oldy1, oldy2, oldy3: Single; 24 | public outlp:single; 25 | end; 26 | ---------------------------------------- 27 | implementation 28 | 29 | constructor TLP24DB.create; 30 | begin 31 | y1:=0; 32 | y2:=0; 33 | y3:=0; 34 | y4:=0; 35 | oldx:=0; 36 | oldy1:=0; 37 | oldy2:=0; 38 | oldy3:=0; 39 | end; 40 | procedure TLP24DB.process(inp: Single; Frq: Single; Res: Single; SR: Integer); 41 | begin 42 | f := (Frq+Frq) / SR; 43 | p:=f*(1.8-0.8*f); 44 | k:=p+p-1.0; 45 | t:=(1.0-p)*1.386249; 46 | t2:=12.0+t*t; 47 | r := res*(t2+6.0*t)/(t2-6.0*t); 48 | x := inp - r*y4; 49 | y1:=x*p + oldx*p - k*y1; 50 | y2:=y1*p+oldy1*p - k*y2; 51 | y3:=y2*p+oldy2*p - k*y3; 52 | y4:=y3*p+oldy3*p - k*y4; 53 | y4 := y4 - ((y4*y4*y4)/6.0); 54 | oldx := x; 55 | oldy1 := y1+_kd; 56 | oldy2 := y2+_kd;; 57 | oldy3 := y3+_kd;; 58 | outlp := y4; 59 | end; 60 | 61 | // the result is in outlp 62 | // 1/ call MyTLP24DB.Process 63 | // 2/then get the result from outlp. 64 | // this filter have a fantastic sound w/a very special res 65 | // _kd is the denormal killer value. 66 | 67 | Comments 68 | -------- 69 | 70 | - **Date**: 2008-10-20 07:44:35 71 | - **By**: moc.liamg@321tiloen 72 | 73 | .. code-block:: text 74 | 75 | This is basically a Moog filter. 76 | 77 | 78 | 79 | - **Date**: 2010-09-16 23:07:30 80 | - **By**: moc.liamG@0356orbratiug 81 | 82 | .. code-block:: text 83 | 84 | Same as http://www.musicdsp.org/showArchiveComment.php?ArchiveID=24 85 | but seems to be in pascal. 86 | 87 | -------------------------------------------------------------------------------- /source/Filters/258-spuc-s-open-source-filters.rst: -------------------------------------------------------------------------------- 1 | Spuc's open source filters 2 | ========================== 3 | 4 | - **Author or source:** moc.liamg@321tiloen 5 | - **Type:** Elliptic, Butterworth, Chebyshev 6 | - **Created:** 2008-10-27 10:14:41 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | http://www.koders.com/info.aspx?c=ProjectInfo&pid=FQLFTV9LA27MF421YKXV224VWH 13 | 14 | Spuc has good C++ versions of some classic filter models. 15 | 16 | Download full package from: 17 | http://spuc.sourceforge.net 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /source/Filters/267-simple-tilt-equalizer.rst: -------------------------------------------------------------------------------- 1 | Simple Tilt equalizer 2 | ===================== 3 | 4 | - **Author or source:** moc.liamg@321tiloen 5 | - **Type:** Tilt 6 | - **Created:** 2009-05-29 15:13:21 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | There are a few ways to implement this. (crossover, shelves, morphing shelves [hs->lp, 13 | ls->hp] ...etc) 14 | This particular one tries to mimic the behavior of the "Niveau" filter from the "Elysia: 15 | mPressor" compressor. 16 | 17 | [The 'Tilt' filter]: 18 | It uses a center frequency (F0) and then boosts one of the ranges above or below F0, while 19 | doing the opposite with the other range. 20 | 21 | In the case of the "mPressor" - more extreme settings turn the filter into first order 22 | low-pass or high-pass. This is achieved with the gain factor for one band going close to 23 | -1. (ex: +6db -> lp; -6db -> hp) 24 | 25 | Lubomir I. Ivanov 26 | 27 | 28 | .. code-block:: c++ 29 | :linenos: 30 | :caption: code 31 | 32 | //======================= 33 | // tilt eq settings 34 | // 35 | // srate -> sample rate 36 | // f0 -> 20-20khz 37 | // gain -> -6 / +6 db 38 | //======================= 39 | amp = 6/log(2); 40 | denorm = 10^-30; 41 | pi = 22/7; 42 | sr3 = 3*srate; 43 | 44 | // conditition: 45 | // gfactor is the proportional gain 46 | // 47 | gfactor = 5; 48 | if (gain > 0) { 49 | g1 = -gfactor*gain; 50 | g2 = gain; 51 | } else { 52 | g1 = -gain; 53 | g2 = gfactor*gain; 54 | }; 55 | 56 | //two separate gains 57 | lgain = exp(g1/amp)-1; 58 | hgain = exp(g2/amp)-1; 59 | 60 | //filter 61 | omega = 2*pi*f0; 62 | n = 1/(sr3 + omega); 63 | a0 = 2*omega*n; 64 | b1 = (sr3 - omega)*n; 65 | 66 | //================================== 67 | // sample loop 68 | // in -> input sample 69 | // out -> output sample 70 | //================================== 71 | lp_out = a0*in + b1*lp_out; 72 | out = in + lgain*lp_out + hgain*(in - lp_out); 73 | 74 | 75 | 76 | Comments 77 | -------- 78 | 79 | - **Date**: 2009-05-29 19:16:18 80 | - **By**: moc.liamg@321tiloen 81 | 82 | .. code-block:: text 83 | 84 | correction: 85 | 86 | (ex: +6db -> hp; -6db -> lp) 87 | 88 | - **Date**: 2017-04-01 09:05:48 89 | - **By**: moc.liamg@59hsielgladsemaj 90 | 91 | .. code-block:: text 92 | 93 | Where is the denorm value meant to be used in the code? The code works regardless by noise is created when the gain control being used, it may be a result of the denorm value not being used? 94 | 95 | -------------------------------------------------------------------------------- /source/Filters/27-resonant-iir-lowpass-12db-oct.rst: -------------------------------------------------------------------------------- 1 | Resonant IIR lowpass (12dB/oct) 2 | =============================== 3 | 4 | - **Author or source:** Olli Niemitalo 5 | - **Type:** Resonant IIR lowpass (12dB/oct) 6 | - **Created:** 2002-01-17 02:05:38 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Hard to calculate coefficients, easy to process algorithm 13 | 14 | 15 | .. code-block:: c++ 16 | :linenos: 17 | :caption: code 18 | 19 | resofreq = pole frequency 20 | amp = magnitude at pole frequency (approx) 21 | 22 | double pi = 3.141592654; 23 | 24 | /* Parameters. Change these! */ 25 | double resofreq = 5000; 26 | double amp = 1.0; 27 | 28 | DOUBLEWORD streamofs; 29 | double w = 2.0*pi*resofreq/samplerate; // Pole angle 30 | double q = 1.0-w/(2.0*(amp+0.5/(1.0+w))+w-2.0); // Pole magnitude 31 | double r = q*q; 32 | double c = r+1.0-2.0*cos(w)*q; 33 | double vibrapos = 0; 34 | double vibraspeed = 0; 35 | 36 | /* Main loop */ 37 | for (streamofs = 0; streamofs < streamsize; streamofs++) { 38 | 39 | /* Accelerate vibra by signal-vibra, multiplied by lowpasscutoff */ 40 | vibraspeed += (fromstream[streamofs] - vibrapos) * c; 41 | 42 | /* Add velocity to vibra's position */ 43 | vibrapos += vibraspeed; 44 | 45 | /* Attenuate/amplify vibra's velocity by resonance */ 46 | vibraspeed *= r; 47 | 48 | /* Check clipping */ 49 | temp = vibrapos; 50 | if (temp > 32767) { 51 | temp = 32767; 52 | } else if (temp < -32768) temp = -32768; 53 | 54 | /* Store new value */ 55 | tostream[streamofs] = temp; 56 | } 57 | 58 | Comments 59 | -------- 60 | 61 | - **Date**: 2002-05-05 08:59:19 62 | - **By**: moc.ibtta@suocuar 63 | 64 | .. code-block:: text 65 | 66 | This looks similar to the low-pass filter I used in FilterKing (http://home.attbi.com/~spaztek4/) Can you cruft up a high-pass example for me? 67 | 68 | Thanks, 69 | __e 70 | 71 | - **Date**: 2006-05-18 17:01:21 72 | - **By**: faster init 73 | 74 | .. code-block:: text 75 | 76 | thank you! works nicely... 77 | here a simplified init version for faster changes of the filter properties for amps = 1.0 78 | 79 | void init( double resofreq ) 80 | { 81 | static const double FAC = pi * 2.0 /samplerate; 82 | double q, w; 83 | 84 | w = FAC * resofreq; 85 | q = 1.0f - w /( ( 3.0 /( 1.0+w ) ) + w - 2.0 ); 86 | 87 | _r = q * q; 88 | _c = r + 1.0f - 2.0f * cos(w) * q; 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /source/Filters/275-direct-form-ii-biquad.rst: -------------------------------------------------------------------------------- 1 | Direct Form II biquad 2 | ===================== 3 | 4 | - **Author or source:** es.tuanopx@kileib.trebor 5 | - **Created:** 2009-11-16 08:46:12 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | The nominal implementation for biquads is the Direct Form I variant. But the Direct Form 12 | II is actually more suited for calculating the biquad since it needs only 2 memory 13 | locations, and the multiplications can be pipelined better by the compiler. In release 14 | build, I've noted a considerable speedup when compared to DF I. When processing stereo, 15 | the code below was ~ 2X faster. Until I develop a SIMD biquad that is faster, this will 16 | do. 17 | 18 | 19 | .. code-block:: c++ 20 | :linenos: 21 | :caption: code 22 | 23 | // b0, b1, b2, a1, a2 calculated via r.b-j's cookbook 24 | // formulae. 25 | // m1, m2 are the memory locations 26 | // dn is the de-denormal coeff (=1.0e-20f) 27 | 28 | void processBiquad(const float* in, float* out, unsigned length) 29 | { 30 | for(unsigned i = 0; i < length; ++i) 31 | { 32 | register float w = in[i] - a1*m1 - a2*m2 + dn; 33 | out[i] = b1*m1 + b2*m2 + b0*w; 34 | m2 = m1; m1 = w; 35 | } 36 | dn = -dn; 37 | } 38 | 39 | void processBiquadStereo(const float* inL, 40 | const float* inR, 41 | float* outL, 42 | float* outR, 43 | unsigned length) 44 | { 45 | for(unsigned i = 0; i < length; ++i) 46 | { 47 | register float wL = inL[i] - a1*m1L - a2*m2L + dn; 48 | register float wR = inR[i] - a1*m1R - a2*m2R + dn; 49 | outL[i] = b1*m1L + b2*m2L + b0*wL; 50 | m2L = m1L; m1L = wL; 51 | outR[i] = b1*m1R + b2*m2R + b0*wR; 52 | m2R = m1R; m1R = wR; 53 | } 54 | dn = -dn; 55 | } 56 | 57 | Comments 58 | -------- 59 | 60 | - **Date**: 2010-01-13 13:44:09 61 | - **By**: moc.suomyn@ona 62 | 63 | .. code-block:: text 64 | 65 | true, this structure is faster. but it is also (even) more sensitive to coefficients changes, so it becomes unstable quite fast compaerd to the DF I form. I'd really like to know if there's a way to change coefficients and at the same time time changing the history of the filter for avoiding unstability. 66 | 67 | - **Date**: 2012-01-31 20:43:12 68 | - **By**: earlevel 69 | 70 | .. code-block:: text 71 | 72 | Use direct form I (single accumulation point) when using fixed-point processors. For floating point, use direct form II transposed, which has superior numerical characteristics to direct form II (non-transposed). 73 | 74 | -------------------------------------------------------------------------------- /source/Filters/29-resonant-filter.rst: -------------------------------------------------------------------------------- 1 | Resonant filter 2 | =============== 3 | 4 | - **Author or source:** Paul Kellett 5 | - **Created:** 2002-01-17 02:07:02 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | This filter consists of two first order low-pass filters in 12 | series, with some of the difference between the two filter 13 | outputs fed back to give a resonant peak. 14 | 15 | You can use more filter stages for a steeper cutoff but the 16 | stability criteria get more complicated if the extra stages 17 | are within the feedback loop. 18 | 19 | 20 | .. code-block:: c++ 21 | :linenos: 22 | :caption: code 23 | 24 | //set feedback amount given f and q between 0 and 1 25 | fb = q + q/(1.0 - f); 26 | 27 | //for each sample... 28 | buf0 = buf0 + f * (in - buf0 + fb * (buf0 - buf1)); 29 | buf1 = buf1 + f * (buf0 - buf1); 30 | out = buf1; 31 | 32 | Comments 33 | -------- 34 | 35 | - **Date**: 2006-01-18 10:59:55 36 | - **By**: mr.just starting 37 | 38 | .. code-block:: text 39 | 40 | very nice! how could i turn that into a HPF? 41 | 42 | - **Date**: 2006-01-23 10:53:41 43 | - **By**: ku.oc.mapson.snosrapsd@psd 44 | 45 | .. code-block:: text 46 | 47 | The cheats way is to use HPF = sample - out; 48 | If you do a plot, you'll find that it isn't as good as designing an HPF from scratch, but it's good enuff for most ears. 49 | This would also mean that you have a quick method for splitting a signal and operating on the (in)discreet parts separately. :) DSP 50 | 51 | - **Date**: 2006-09-12 14:42:25 52 | - **By**: uh.etle.fni@yfoocs 53 | 54 | .. code-block:: text 55 | 56 | This filter calculates bandpass and highpass outputs too during calculation, namely bandpass is buf0 - buf1 and highpass is in - buf0. So, we can rewrite the algorithm: 57 | 58 | // f and fb calculation 59 | f = 2.0*sin(pi*freq/samplerate); 60 | /* you can approximate this with f = 2.0*pi*freq/samplerate with tuning error towards nyquist */ 61 | fb = q + q/(1.0 - f); 62 | 63 | // loop 64 | hp = in - buf0; 65 | bp = buf0 - buf1; 66 | buf0 = buf0 + f * (hp + fb * bp); 67 | buf1 = buf1 + f * (buf0 - buf1); 68 | 69 | out = buf1; // lowpass 70 | out = bp; // bandpass 71 | out = hp; // highpass 72 | 73 | The slope of the highpass out is not constant, it varies between 6 and 12 dB/Octave with different f and q settings. I'd be interested if anyone derived a proper highpass output from this algorithm. 74 | 75 | -- peter schoffhauzer 76 | 77 | -------------------------------------------------------------------------------- /source/Filters/30-303-type-filter-with-saturation.rst: -------------------------------------------------------------------------------- 1 | 303 type filter with saturation 2 | =============================== 3 | 4 | - **Author or source:** Hans Mikelson 5 | - **Type:** Runge-Kutta Filters 6 | - **Created:** 2002-01-17 02:07:37 7 | 8 | - **Linked files:** :download:`filters001.txt <../files/filters001.txt>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | I posted a filter to the Csound mailing list a couple of weeks ago that has a 303 flavor 14 | to it. It basically does wacky distortions to the sound. I used Runge-Kutta for the diff 15 | eq. simulation though which makes it somewhat sluggish. 16 | 17 | This is a CSound score!! 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /source/Filters/31-all-pass-filters-a-good-explanation.rst: -------------------------------------------------------------------------------- 1 | All-Pass Filters, a good explanation 2 | ==================================== 3 | 4 | - **Author or source:** Olli Niemitalo 5 | - **Type:** information 6 | - **Created:** 2002-01-17 02:08:11 7 | 8 | - **Linked files:** :download:`filters002.txt <../files/filters002.txt>`. 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /source/Filters/32-various-biquad-filters.rst: -------------------------------------------------------------------------------- 1 | Various Biquad filters 2 | ====================== 3 | 4 | - **Author or source:** JAES, Vol. 31, No. 11, 1983 November 5 | - **Created:** 2002-01-17 02:08:47 6 | 7 | - **Linked files:** :download:`filters003.txt <../files/filters003.txt>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | (see linkfile) 13 | Filters included are: 14 | presence 15 | shelvelowpass 16 | 2polebp 17 | peaknotch 18 | peaknotch2 19 | 20 | 21 | 22 | Comments 23 | -------- 24 | 25 | - **Date**: 2008-10-19 23:02:44 26 | - **By**: moc.liamg@321tiloen 27 | 28 | .. code-block:: text 29 | 30 | I'm kinda stuck trying to figure out the 'pointer' 'structure pointer' loop in the presence EQ. 31 | 32 | Can someone explain: 33 | 34 | ... 35 | 36 | *a0 = a2plus1 + alphan*ma2plus1; 37 | *a1 = 4.0*a; 38 | *a2 = a2plus1 - alphan*ma2plus1; 39 | 40 | b0 = a2plus1 + alphad*ma2plus1; 41 | *b2 = a2plus1 - alphad*ma2plus1; 42 | 43 | recipb0 = 1.0/b0; 44 | *a0 *= recipb0; 45 | *a1 *= recipb0; 46 | *a2 *= recipb0; 47 | *b1 = *a1; 48 | *b2 *= recipb0; 49 | 50 | .... 51 | 52 | void setfilter_presence(f,freq,boost,bw) 53 | filter *f; 54 | double freq,boost,bw; 55 | { 56 | presence(freq/(double)SR,boost,bw/(double)SR, 57 | &f->cx,&f->cx1,&f->cx2,&f->cy1,&f->cy2); 58 | f->cy1 = -f->cy1; 59 | f->cy2 = -f->cy2; 60 | } 61 | 62 | 63 | How can this be translated into something more easy to understand. 64 | 65 | Input = ... 66 | Output = ... 67 | 68 | - **Date**: 2008-10-28 12:15:21 69 | - **By**: moc.liamg@321tiloen 70 | 71 | .. code-block:: text 72 | 73 | Managed to port the presence eq properly. And its sounds great! 74 | 75 | Altho I did some changes to some of the code. 76 | 77 | changed "d /= mag" to "d = mag" 78 | "bw/srate" to "bw" 79 | 80 | There results I got are stable within there parameters: 81 | 82 | freq: 3100-18500hz 83 | boost: 0-15db 84 | bw: 0.07-0.40 85 | 86 | Really good sound from this filter! 87 | 88 | -------------------------------------------------------------------------------- /source/Filters/33-resonant-low-pass-filter.rst: -------------------------------------------------------------------------------- 1 | Resonant low pass filter 2 | ======================== 3 | 4 | - **Author or source:** "Zxform" 5 | - **Type:** 24dB lowpass 6 | - **Created:** 2002-01-17 02:09:31 7 | 8 | - **Linked files:** :download:`filters004.txt <../files/filters004.txt>`. 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /source/Filters/34-prewarping.rst: -------------------------------------------------------------------------------- 1 | Prewarping 2 | ========== 3 | 4 | - **Author or source:** robert bristow-johnson (better known as "rbj" ) 5 | - **Type:** explanation 6 | - **Created:** 2002-01-17 02:10:26 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | prewarping is simply recognizing the warping that the BLT introduces. 13 | to determine frequency response, we evaluate the digital H(z) at 14 | z=exp(j*w*T) and we evaluate the analog Ha(s) at s=j*W . the following 15 | will confirm the jw to unit circle mapping and will show exactly what the 16 | mapping is (this is the same stuff in the textbooks): 17 | 18 | the BLT says: s = (2/T) * (z-1)/(z+1) 19 | 20 | substituting: s = j*W = (2/T) * (exp(j*w*T) - 1) / (exp(j*w*T) + 1) 21 | 22 | j*W = (2/T) * (exp(j*w*T/2) - exp(-j*w*T/2)) / (exp(j*w*T/2) + exp(-j*w*T/2)) 23 | 24 | = (2/T) * (j*2*sin(w*T/2)) / (2*cos(w*T/2)) 25 | 26 | = j * (2/T) * tan(w*T/2) 27 | 28 | or 29 | 30 | analog W = (2/T) * tan(w*T/2) 31 | 32 | so when the real input frequency is w, the digital filter will behave with 33 | the same amplitude gain and phase shift as the analog filter will have at a 34 | hypothetical frequency of W. as w*T approaches pi (Nyquist) the digital 35 | filter behaves as the analog filter does as W -> inf. for each degree of 36 | freedom that you have in your design equations, you can adjust the analog 37 | design frequency to be just right so that when the deterministic BLT 38 | warping does its thing, the resultant warped frequency comes out just 39 | right. for a simple LPF, you have only one degree of freedom, the cutoff 40 | frequency. you can precompensate it so that the true cutoff comes out 41 | right but that is it, above the cutoff, you will see that the LPF dives 42 | down to -inf dB faster than an equivalent analog at the same frequencies. 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /source/Filters/64-biquad-c-code.rst: -------------------------------------------------------------------------------- 1 | Biquad C code 2 | ============= 3 | 4 | - **Author or source:** Tom St Denis 5 | - **Created:** 2002-02-10 12:33:52 6 | 7 | - **Linked files:** :download:`biquad.c <../files/biquad.c>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Implementation of the RBJ cookbook, in C. 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /source/Filters/66-time-domain-convolution-with-o-n-log2-3.rst: -------------------------------------------------------------------------------- 1 | Time domain convolution with O(n^log2(3)) 2 | ========================================= 3 | 4 | - **Author or source:** Magnus Jonsson 5 | - **Created:** 2002-09-07 23:23:50 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | [see other code by Wilfried Welti too!] 12 | 13 | 14 | .. code-block:: c++ 15 | :linenos: 16 | :caption: code 17 | 18 | void mul_brute(float *r, float *a, float *b, int w) 19 | { 20 | for (int i = 0; i < w+w; i++) 21 | r[i] = 0; 22 | for (int i = 0; i < w; i++) 23 | { 24 | float *rr = r+i; 25 | float ai = a[i]; 26 | for (int j = 0; j < w; j++) 27 | rr[j] += ai*b[j]; 28 | } 29 | } 30 | 31 | // tmp must be of length 2*w 32 | void mul_knuth(float *r, float *a, float *b, int w, float *tmp) 33 | { 34 | if (w < 30) 35 | { 36 | mul_brute(r, a, b, w); 37 | } 38 | else 39 | { 40 | int m = w>>1; 41 | 42 | for (int i = 0; i < m; i++) 43 | { 44 | r[i ] = a[m+i]-a[i ]; 45 | r[i+m] = b[i ]-b[m+i]; 46 | } 47 | 48 | mul_knuth(tmp, r , r+m, m, tmp+w); 49 | mul_knuth(r , a , b , m, tmp+w); 50 | mul_knuth(r+w, a+m, b+m, m, tmp+w); 51 | 52 | for (int i = 0; i < m; i++) 53 | { 54 | float bla = r[m+i]+r[w+i]; 55 | r[m+i] = bla+r[i ]+tmp[i ]; 56 | r[w+i] = bla+r[w+m+i]+tmp[i+m]; 57 | } 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /source/Filters/72-18db-oct-resonant-3-pole-lpf-with-tanh-dist.rst: -------------------------------------------------------------------------------- 1 | 18dB/oct resonant 3 pole LPF with tanh() dist 2 | ============================================= 3 | 4 | - **Author or source:** Josep M Comajuncosas 5 | - **Created:** 2002-02-10 13:17:10 6 | 7 | - **Linked files:** :download:`lpf18.zip <../files/lpf18.zip>`. 8 | - **Linked files:** :download:`lpf18.sme <../files/lpf18.sme>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | Implementation in CSound and Sync Modular... 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /source/Filters/85-1st-and-2nd-order-pink-noise-filters.rst: -------------------------------------------------------------------------------- 1 | 1st and 2nd order pink noise filters 2 | ==================================== 3 | 4 | - **Author or source:** moc.regnimmu@regnimmu 5 | - **Type:** Pink noise 6 | - **Created:** 2004-04-07 09:36:23 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Here are some new lower-order pink noise filter coefficients. 13 | 14 | These have approximately equiripple error in decibels from 20hz to 20khz at a 44.1khz 15 | sampling rate. 16 | 17 | 1st order, ~ +/- 3 dB error (not recommended!) 18 | num = [0.05338071119116 -0.03752455712906] 19 | den = [1.00000000000000 -0.97712493947102] 20 | 21 | 2nd order, ~ +/- 0.9 dB error 22 | num = [ 0.04957526213389 -0.06305581334498 0.01483220320740 ] 23 | den = [ 1.00000000000000 -1.80116083982126 0.80257737639225 ] 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /source/Other/103-calculate-notes-java.rst: -------------------------------------------------------------------------------- 1 | Calculate notes (java) 2 | ====================== 3 | 4 | - **Author or source:** gro.kale@ybsral 5 | - **Type:** Java class for calculating notes with different in params 6 | - **Created:** 2002-06-21 02:33:13 7 | 8 | - **Linked files:** :download:`Frequency.java <../files/Frequency.java>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | Converts between string notes and frequencies and back. I vaguely remember writing bits of 14 | it, and I got it off the net somwhere so dont ask me 15 | 16 | - Larsby 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /source/Other/106-fast-exp2-approximation.rst: -------------------------------------------------------------------------------- 1 | Fast exp2 approximation 2 | ======================= 3 | 4 | - **Author or source:** Laurent de Soras (moc.ecrofmho@tnerual) 5 | - **Created:** 2002-07-29 18:42:23 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | Partial approximation of exp2 in fixed-point arithmetic. It is exactly : 12 | [0 ; 1[ -> [0.5 ; 1[ 13 | f : x |-> 2^(x-1) 14 | To get the full exp2 function, you have to separate the integer and fractionnal part of 15 | the number. The integer part may be processed by bitshifting. Process the fractionnal part 16 | with the function, and multiply the two results. 17 | Maximum error is only 0.3 % which is pretty good for two mul ! You get also the continuity 18 | of the first derivate. 19 | 20 | -- Laurent 21 | 22 | 23 | .. code-block:: c++ 24 | :linenos: 25 | :caption: code 26 | 27 | // val is a 16-bit fixed-point value in 0x0 - 0xFFFF ([0 ; 1[) 28 | // Returns a 32-bit fixed-point value in 0x80000000 - 0xFFFFFFFF ([0.5 ; 1[) 29 | unsigned int fast_partial_exp2 (int val) 30 | { 31 | unsigned int result; 32 | 33 | __asm 34 | { 35 | mov eax, val 36 | shl eax, 15 ; eax = input [31/31 bits] 37 | or eax, 080000000h ; eax = input + 1 [32/31 bits] 38 | mul eax 39 | mov eax, edx ; eax = (input + 1) ^ 2 [32/30 bits] 40 | mov edx, 2863311531 ; 2/3 [32/32 bits], rounded to +oo 41 | mul edx ; eax = 2/3 (input + 1) ^ 2 [32/30 bits] 42 | add edx, 1431655766 ; + 4/3 [32/30 bits] + 1 43 | mov result, edx 44 | } 45 | 46 | return (result); 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /source/Other/115-sin-cos-tan-approximation.rst: -------------------------------------------------------------------------------- 1 | Sin, Cos, Tan approximation 2 | =========================== 3 | 4 | - **Author or source:** http://www.wild-magic.com 5 | - **Created:** 2003-04-26 00:17:56 6 | 7 | - **Linked files:** :download:`approx.h <../files/approx.h>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Code for approximation of cos, sin, tan and inv sin, etc. 13 | Surprisingly accurate and very usable. 14 | 15 | [edit by bram] 16 | this code is taken literaly from 17 | http://www.wild-magic.com/SourceCode.html 18 | Go have a look at the MgcMath.h and MgcMath.cpp files in their library... 19 | [/edit] 20 | 21 | 22 | 23 | 24 | Comments 25 | -------- 26 | 27 | - **Date**: 2002-09-01 00:06:40 28 | - **By**: moc.oi@htnysa 29 | 30 | .. code-block:: text 31 | 32 | It'd be nice to have a note on the domain of these functions. I assume Sin0 is meant to be used about zero and Sin1 about 1. But a note to that effect would be good. 33 | Thanks, 34 | 35 | james mccartney 36 | 37 | 38 | - **Date**: 2003-05-31 18:39:50 39 | - **By**: ten.xmg@mapsedocm 40 | 41 | .. code-block:: text 42 | 43 | Sin0 is faster but less accurate than Sin1, same for the other pairs. The domains are: 44 | 45 | Sin/Cos [0, pi/2] 46 | Tan [0,pi/4] 47 | InvSin/Cos [0, 1] 48 | InvTan [-1, 1] 49 | 50 | This comes from the original header file. 51 | 52 | -------------------------------------------------------------------------------- /source/Other/119-lock-free-fifo.rst: -------------------------------------------------------------------------------- 1 | Lock free fifo 2 | ============== 3 | 4 | - **Author or source:** Timo 5 | - **Created:** 2002-09-13 16:21:59 6 | 7 | - **Linked files:** :download:`LockFreeFifo.h <../files/LockFreeFifo.h>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Simple implementation of a lock free FIFO. 13 | 14 | 15 | 16 | Comments 17 | -------- 18 | 19 | - **Date**: 2003-04-15 11:17:31 20 | - **By**: moc.oohay@SIHTEVOMER_ralohcshsoj 21 | 22 | .. code-block:: text 23 | 24 | There is a good algorithm for a lock free (but multiprocessor safe) FIFO. But the given implimentation is flawed in a number of ways. This code is not reliable. Two problems on the surface of it: 25 | 1. I can easily see that it's possible for two threads/processors to return the same item from the head if the timing is right. 26 | 2. there's no interlocked instructions to make sure that changes to the shared variables are globally visible 27 | 3. there's not attempt in the code to make sure that data is read in an atomic way, let alone changed in one... 28 | 29 | The code is VERY naive 30 | 31 | I do have code that works, but it's not so short that will post it in a comment. If anyone needs it they can email me 32 | 33 | - **Date**: 2003-05-15 19:16:24 34 | - **By**: Timo 35 | 36 | .. code-block:: text 37 | 38 | This is only supposed to work on uniprocessor machines with _one_ reading and _one_ writing thread 39 | assuming that the assignments to read and write idx are simple mov instructions (i.e. atomic). To be sure you'd need to write the update parts in hand-coded asm; never know what the compiler comes up with. The context of this code was omitted (i.e. Bram posted my written in 1 min sketch in a discussion on IRC on a lock-free fifo, not production code). 40 | 41 | -------------------------------------------------------------------------------- /source/Other/121-gaussian-dithering.rst: -------------------------------------------------------------------------------- 1 | Gaussian dithering 2 | ================== 3 | 4 | - **Author or source:** Aleksey Vaneev (ur.liam@redocip) 5 | - **Type:** Dithering 6 | - **Created:** 2002-09-29 23:02:52 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | It is a more sophisticated dithering than simple RND. It gives the most low noise floor 13 | for the whole spectrum even without noise-shaping. You can use as big N as you can afford 14 | (it will not hurt), but 4 or 5 is generally enough. 15 | 16 | 17 | .. code-block:: c++ 18 | :linenos: 19 | :caption: code 20 | 21 | Basically, next value is calculated this way (for RND going from -0.5 to 0.5): 22 | 23 | dither = (RND+RND+...+RND) / N. 24 | \ / 25 | \_________/ 26 | N times 27 | 28 | If your RND goes from 0 to 1, then this code is applicable: 29 | 30 | dither = (RND+RND+...+RND - 0.5*N) / N. 31 | 32 | 33 | -------------------------------------------------------------------------------- /source/Other/129-gaussian-random-numbers.rst: -------------------------------------------------------------------------------- 1 | Gaussian random numbers 2 | ======================= 3 | 4 | - **Author or source:** ed.bew@raebybot 5 | - **Type:** random number generation 6 | - **Created:** 2002-12-16 19:01:01 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | // Gaussian random numbers 13 | // This algorithm (adapted from "Natur als fraktale Grafik" by 14 | // Reinhard Scholl) implements a generation method for gaussian 15 | // distributed random numbers with mean=0 and variance=1 16 | // (standard gaussian distribution) mapped to the range of 17 | // -1 to +1 with the maximum at 0. 18 | // For only positive results you might abs() the return value. 19 | // The q variable defines the precision, with q=15 the smallest 20 | // distance between two numbers will be 1/(2^q div 3)=1/10922 21 | // which usually gives good results. 22 | 23 | // Note: the random() function used is the standard random 24 | // function from Delphi/Pascal that produces *linear* 25 | // distributed numbers from 0 to parameter-1, the equivalent 26 | // C function is probably rand(). 27 | 28 | 29 | .. code-block:: c++ 30 | :linenos: 31 | :caption: code 32 | 33 | const q=15; 34 | c1=(1 shl q)-1; 35 | c2=(c1 div 3)+1; 36 | c3=1/c1; 37 | 38 | function GRandom:single; 39 | begin 40 | result:=(2*(random(c2)+random(c2)+random(c2))-3*(c2-1))*c3; 41 | end; 42 | 43 | 44 | -------------------------------------------------------------------------------- /source/Other/133-fast-power-and-root-estimates-for-32bit-floats.rst: -------------------------------------------------------------------------------- 1 | Fast power and root estimates for 32bit floats 2 | ============================================== 3 | 4 | - **Author or source:** ed.bew@raebybot 5 | - **Type:** floating point functions 6 | - **Created:** 2002-12-18 21:07:27 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Original code by Stefan Stenzel (also in this archive, see "pow(x,4) approximation") - 13 | extended for more flexibility. 14 | 15 | fastpow(f,n) gives a rather *rough* estimate of a float number f to the power of an 16 | integer number n (y=f^n). It is fast but result can be quite a bit off, since we directly 17 | mess with the floating point exponent.-> use it only for getting rough estimates of the 18 | values and where precision is not that important. 19 | 20 | fastroot(f,n) gives the n-th root of f. Same thing concerning precision applies here. 21 | 22 | Cheers 23 | 24 | Toby (www.tobybear.de) 25 | 26 | 27 | .. code-block:: c++ 28 | :linenos: 29 | :caption: code 30 | 31 | //C/C++ source code: 32 | float fastpower(float f,int n) 33 | { 34 | long *lp,l; 35 | lp=(long*)(&f); 36 | l=*lp;l-=0x3F800000l;l<<=(n-1);l+=0x3F800000l; 37 | *lp=l; 38 | return f; 39 | } 40 | 41 | float fastroot(float f,int n) 42 | { 43 | long *lp,l; 44 | lp=(long*)(&f); 45 | l=*lp;l-=0x3F800000l;l>>=(n-1);l+=0x3F800000l; 46 | *lp=l; 47 | return f; 48 | } 49 | 50 | //Delphi/Pascal source code: 51 | function fastpower(i:single;n:integer):single; 52 | var l:longint; 53 | begin 54 | l:=longint((@i)^); 55 | l:=l-$3F800000;l:=l shl (n-1);l:=l+$3F800000; 56 | result:=single((@l)^); 57 | end; 58 | 59 | function fastroot(i:single;n:integer):single; 60 | var l:longint; 61 | begin 62 | l:=longint((@i)^); 63 | l:=l-$3F800000;l:=l shr (n-1);l:=l+$3F800000; 64 | result:=single((@l)^); 65 | end; 66 | 67 | 68 | -------------------------------------------------------------------------------- /source/Other/138-envelope-follower.rst: -------------------------------------------------------------------------------- 1 | Envelope Follower 2 | ================= 3 | 4 | - **Author or source:** ers 5 | - **Created:** 2003-03-12 04:08:16 6 | 7 | 8 | 9 | .. code-block:: c++ 10 | :linenos: 11 | :caption: code 12 | 13 | #define V_ENVELOPE_FOLLOWER_NUM_POINTS 2000 14 | class vEnvelopeFollower : 15 | { 16 | public: 17 | vEnvelopeFollower(); 18 | virtual ~vEnvelopeFollower(); 19 | inline void Calculate(float *b) 20 | { 21 | envelopeVal -= *buff; 22 | if (*b < 0) 23 | envelopeVal += *buff = -*b; 24 | else 25 | envelopeVal += *buff = *b; 26 | if (buff++ == bufferEnd) 27 | buff = buffer; 28 | } 29 | void SetBufferSize(float value); 30 | void GetControlValue(){return envelopeVal / (float)bufferSize;} 31 | 32 | private: 33 | float buffer[V_ENVELOPE_FOLLOWER_NUM_POINTS]; 34 | float *bufferEnd, *buff, envelopeVal; 35 | int bufferSize; 36 | float val; 37 | }; 38 | 39 | vEnvelopeFollower::vEnvelopeFollower() 40 | { 41 | bufferEnd = buffer + V_ENVELOPE_FOLLOWER_NUM_POINTS-1; 42 | buff = buffer; 43 | val = 0; 44 | float *b = buffer; 45 | do 46 | { 47 | *b++ = 0; 48 | }while (b <= bufferEnd); 49 | bufferSize = V_ENVELOPE_FOLLOWER_NUM_POINTS; 50 | envelopeVal= 0; 51 | } 52 | 53 | vEnvelopeFollower::~vEnvelopeFollower() 54 | { 55 | 56 | } 57 | 58 | void vEnvelopeFollower::SetBufferSize(float value) 59 | { 60 | 61 | bufferEnd = buffer + (bufferSize = 100 + (int)(value * ((float)V_ENVELOPE_FOLLOWER_NUM_POINTS-102))); 62 | buff = buffer; 63 | float val = envelopeVal / bufferSize; 64 | do 65 | { 66 | *buff++ = val; 67 | }while (buff <= bufferEnd); 68 | buff = buffer; 69 | } 70 | 71 | 72 | Comments 73 | -------- 74 | 75 | - **Date**: 2007-01-17 13:46:04 76 | - **By**: gro.akeeb@evets 77 | 78 | .. code-block:: text 79 | 80 | Nice contribution, but I have a couple of questions... 81 | 82 | Looks like there is a typo on GetControlValue... should return a float. Also, I am not clear on the reason for it taking a pointer to a float. 83 | 84 | Is there any noticeable speed improvement with the "if (*b < 0)" code, as opposed to using fabs? I would hope that a decent compiler library would inline this (but haven't cracked open the disassembler to find out). 85 | 86 | 87 | -------------------------------------------------------------------------------- /source/Other/148-nonblocking-multiprocessor-multithread-algorithms-in-c.rst: -------------------------------------------------------------------------------- 1 | Nonblocking multiprocessor/multithread algorithms in C++ 2 | ======================================================== 3 | 4 | - **Author or source:** moc.oohay@ralohcshsoj 5 | - **Type:** queue, stack, garbage collection, memory allocation, templates for atomic algorithms and types 6 | - **Created:** 2004-04-07 09:38:12 7 | 8 | - **Linked files:** :download:`ATOMIC.H <../files/ATOMIC.H>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | see linked file... 14 | 15 | 16 | 17 | Comments 18 | -------- 19 | 20 | - **Date**: 2008-01-10 17:01:39 21 | - **By**: ten.xliamnahx@xmagie 22 | 23 | .. code-block:: text 24 | 25 | This code has a problem with operation exceeding 4G times. If you do more then 4G of Put and Get with the MPQueue, "AtomicUInt & Index(int i) { return data[i & (len-1)];} will cause BUG. 26 | Modular operation with length of 2^n is OK, but not for other numbers. 27 | My email does not have any "x" letters. 28 | 29 | 30 | - **Date**: 2011-05-23 22:22:21 31 | - **By**: ude.fcu.sc@awajuk 32 | 33 | .. code-block:: text 34 | 35 | In MPCountStack::PopElement, what's to prevent another thread from deleting was.Value().ptr between assigning was and reading was.Value().ptr->next? 36 | 37 | -------------------------------------------------------------------------------- /source/Other/149-block-loop-benchmarking.rst: -------------------------------------------------------------------------------- 1 | Block/Loop Benchmarking 2 | ======================= 3 | 4 | - **Author or source:** moc.xinortceletrams@urugra 5 | - **Type:** Benchmarking Tool 6 | - **Created:** 2003-06-24 07:30:43 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Requires CPU with RDTSC support 13 | 14 | 15 | .. code-block:: c++ 16 | :linenos: 17 | :caption: code 18 | 19 | // Block-Process Benchmarking Code using rdtsc 20 | // useful for measure DSP block stuff 21 | // (based on Intel papers) 22 | // 64-bit precission 23 | // VeryUglyCode(tm) by Arguru 24 | 25 | // globals 26 | UINT time,time_low,time_high; 27 | 28 | // call this just before enter your loop or whatever 29 | void bpb_start() 30 | { 31 | // read time stamp to EAX 32 | __asm rdtsc; 33 | __asm mov time_low,eax; 34 | __asm mov time_high,edx; 35 | } 36 | 37 | // call the following function just after your loop 38 | // returns average cycles wasted per sample 39 | UINT bpb_finish(UINT const num_samples) 40 | { 41 | __asm rdtsc 42 | __asm sub eax,time_low; 43 | __asm sub edx,time_high; 44 | __asm div num_samples; 45 | __asm mov time,eax; 46 | return time; 47 | } 48 | 49 | Comments 50 | -------- 51 | 52 | - **Date**: 2004-05-16 18:20:13 53 | - **By**: moc.sulp.52retsinnab@etep 54 | 55 | .. code-block:: text 56 | 57 | If running windows on a mutliprocessor system, apparently it is worth calling: 58 | 59 | SetThreadAffinityMask(GetCurrentThread(), 1); 60 | 61 | to reduce artefacts. 62 | 63 | (see http://msdn.microsoft.com/visualc/vctoolkit2003/default.aspx?pull=/library/en-us/dv_vstechart/html/optimization.asp) 64 | 65 | - **Date**: 2004-08-26 00:33:18 66 | - **By**: rf.eerf@uerum.emualliug 67 | 68 | .. code-block:: text 69 | 70 | __asm sub eax,time_low; 71 | __asm sub edx,time_high; 72 | 73 | should be 74 | 75 | __asm sub eax,time_low 76 | __asm SBB edx,time_high // substract with borrow 77 | 78 | -------------------------------------------------------------------------------- /source/Other/158-really-fast-x86-floating-point-sin-cos.rst: -------------------------------------------------------------------------------- 1 | Really fast x86 floating point sin/cos 2 | ====================================== 3 | 4 | - **Author or source:** moc.nsm@seivadrer 5 | - **Created:** 2003-11-25 17:43:28 6 | 7 | - **Linked files:** :download:`sincos.zip <../files/sincos.zip>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Frightful code from the Intel Performance optimization front. Not for the squeamish. 13 | 14 | The following code calculates sin and cos of a floating point value on x86 platforms to 20 15 | bits precision with 2 multiplies and two adds. The basic principle is to use sin(x+y) and 16 | cos(x+y) identities to generate the result from lookup tables. Each lookup table takes 17 | care of 10 bits of precision in the input. The same principle can be used to generate 18 | sin/cos to full (! Really. Full!) 24-bit float precision using two 8-bit tables, and one 19 | 10 bit table (to provide guard bits), for a net speed gain of about 4x over fsin/fcos, and 20 | 8x if you want both sin and cos. Note that microsoft compilers have trouble keeping 21 | doubles aligned properly on the stack (they must be 8-byte aligned in order not to incur 22 | a massive alignment penalty). As a result, this class should NOT be allocated on the 23 | stack. Add it as a member variable to any class that uses it. 24 | 25 | e.g. 26 | class CSomeClass { 27 | CQuickTrig m_QuickTrig; 28 | ... 29 | mQuickTrig.QuickSinCos(dAngle,fSin,fCos); 30 | ... 31 | } 32 | 33 | 34 | 35 | .. code-block:: c++ 36 | :linenos: 37 | :caption: code 38 | 39 | (see attached file) 40 | 41 | -------------------------------------------------------------------------------- /source/Other/164-resampling.rst: -------------------------------------------------------------------------------- 1 | Resampling 2 | ========== 3 | 4 | - **Author or source:** ed.corm@liam 5 | - **Type:** linear interpolated aliased resampling of a wave file 6 | - **Created:** 2004-04-07 09:39:12 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | som resampling stuff. the code is heavily used in MSynth, but do not lough about ;-) 13 | 14 | perhaps, prefiltering would reduce aliasing. 15 | 16 | 17 | .. code-block:: c++ 18 | :linenos: 19 | :caption: code 20 | 21 | signed short* pSample = ...; 22 | unsigned int sampleLength = ...; 23 | 24 | // stretch sample to length of one bar... 25 | float playPosDelta = sampleLength / ( ( 240.0f / bpm ) * samplingRate ); 26 | 27 | // requires for position calculation... 28 | float playpos1 = 0.0f; 29 | unsigned int iter = 0; 30 | 31 | // required for interpolation... 32 | unsigned int i1, i2; 33 | 34 | float* pDest = ....; 35 | float* pDestStop = pDest + len; 36 | for( float *pt=pDest;pt`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | This code contains functions to disassemble Motorola 56k opcodes. The code was originally 14 | created by Stephen Davis at Stanford. I made minor modifications to support many 56300 15 | opcodes, although it would nice to add them all at some point. Specifically, I added 16 | support for CLB, NORMF, immediate AND, immediate OR, multi-bit ASR/ASL, multi-bit LSL/LSR, 17 | MAX, MAXM, BRA, Bcc, BSR, BScc, DMAC, MACsu, MACuu, and conditional ALU instructions. 18 | 19 | 20 | 21 | Comments 22 | -------- 23 | 24 | - **Date**: 2005-05-24 20:33:25 25 | - **By**: jawoll 26 | 27 | .. code-block:: text 28 | 29 | nice! let's disassemble virus c, nord lead 3, ... 30 | 31 | - **Date**: 2005-09-29 19:51:55 32 | - **By**: moc.liamg@rhajile 33 | 34 | .. code-block:: text 35 | 36 | Very nice. How would one get ahold of the OS for one of these synths, to disassemble it? I've got a Nord Micro, with a single 56303... question is.... how to get the OS from the flash? 37 | 38 | - **Date**: 2011-07-11 08:58:10 39 | - **By**: ach nö 40 | 41 | .. code-block:: text 42 | 43 | After a first look inside the c file i found out that the header file "Utility56k.h" is missing which is included in the code file... 44 | 45 | -------------------------------------------------------------------------------- /source/Other/228-automatic-pdc-system.rst: -------------------------------------------------------------------------------- 1 | Automatic PDC system 2 | ==================== 3 | 4 | - **Author or source:** Tebello Thejane 5 | - **Type:** the type that actually works, completely 6 | - **Created:** 2006-07-16 11:39:56 7 | 8 | - **Linked files:** :download:`pdc.pdf <../files/pdc.pdf>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | No, people, implementing PDC is actually not as difficult as you might think it is. 14 | 15 | This paper presents a solution to the problem of latency inherent in audio effects 16 | processors, and the two appendices give examples of the method being applied on Cubase SX 17 | (with an example which its native half-baked PDC fails to solve properly) as well as a 18 | convoluted example in FL Studio (taking advantage of the flexible routing capabilities 19 | introduced in version 6 of the software). All that's necessary to understand it is a grasp 20 | of basic algebra and an intermediate understanding of how music production software works 21 | (no need to understand the Laplace transform, linear processes, sigma and integral 22 | notation... YAY!). 23 | 24 | Please do send me any feedback (kudos, errata, flames, job offers, questions, comments) 25 | you might have - my email address is included in the paper - or simply use musicdsp.org's 26 | own commenting system. 27 | 28 | Tebello Thejane. 29 | 30 | 31 | .. code-block:: c++ 32 | :linenos: 33 | :caption: code 34 | 35 | (I have sent the PDF to Bram as he suggested) 36 | 37 | Comments 38 | -------- 39 | 40 | - **Date**: 2006-07-18 08:12:00 41 | - **By**: moc.liamg@saoxyz 42 | 43 | .. code-block:: text 44 | 45 | Oops! RBJ's first name is Robert, not Richard! Man, that's a bad one... 46 | 47 | - **Date**: 2006-07-21 10:24:53 48 | - **By**: moc.liamg@saoxyz 49 | 50 | .. code-block:: text 51 | 52 | Okay, I've sent a fixed version to Bram. It should be uploaded shortly. Bigger diagrams, too, so there's less aliasing in Adode Acrobat Reader. Hopefully no more embarisingly bad errors (like misspelling my own name, or something...). 53 | 54 | - **Date**: 2006-10-09 15:27:24 55 | - **By**: moc.liamg@saoxyz 56 | 57 | .. code-block:: text 58 | 59 | The revised version may be found here: 60 | http(:)//www.vormdicht.nl /misc/PDC_paper-rev.pdf 61 | Naturally, you need to remove the brackets from the address. 62 | 63 | -------------------------------------------------------------------------------- /source/Other/238-rational-tanh-approximation.rst: -------------------------------------------------------------------------------- 1 | Rational tanh approximation 2 | =========================== 3 | 4 | - **Author or source:** cschueler 5 | - **Type:** saturation 6 | - **Created:** 2006-11-15 17:29:12 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This is a rational function to approximate a tanh-like soft clipper. It is based on the 13 | pade-approximation of the tanh function with tweaked coefficients. 14 | 15 | The function is in the range x=-3..3 and outputs the range y=-1..1. Beyond this range the 16 | output must be clamped to -1..1. 17 | 18 | The first to derivatives of the function vanish at -3 and 3, so the transition to the hard 19 | clipped region is C2-continuous. 20 | 21 | 22 | 23 | 24 | .. code-block:: c++ 25 | :linenos: 26 | :caption: code 27 | 28 | float rational_tanh(x) 29 | { 30 | if( x < -3 ) 31 | return -1; 32 | else if( x > 3 ) 33 | return 1; 34 | else 35 | return x * ( 27 + x * x ) / ( 27 + 9 * x * x ); 36 | } 37 | 38 | 39 | Comments 40 | -------- 41 | 42 | - **Date**: 2006-11-24 16:24:54 43 | - **By**: uh.etle.fni@yfoocs 44 | 45 | .. code-block:: text 46 | 47 | Works fine. If you want only a little overdrive, you don't even need the clipping, just the last line for faster processing. 48 | 49 | float rational_tanh_noclip(x) 50 | { 51 | return x * ( 27 + x * x ) / ( 27 + 9 * x * x ); 52 | } 53 | 54 | The maximum error of this function in the -4.5 .. 4.5 range is about 2.6%. 55 | 56 | 57 | - **Date**: 2006-11-30 15:59:33 58 | - **By**: uh.etle.fni@yfoocs 59 | 60 | .. code-block:: text 61 | 62 | By the way this is the fastest tanh() approximation in the archive so far. 63 | 64 | - **Date**: 2006-12-08 21:21:02 65 | - **By**: cschueler 66 | 67 | .. code-block:: text 68 | 69 | Yep, I thought so. 70 | That's why I thought it would be worth sharing. 71 | 72 | Especially fast when using SSE you can do a 4-way parallel implementation, with MIN/MAX and the RCP instruction. 73 | 74 | 75 | - **Date**: 2007-01-26 12:13:50 76 | - **By**: mdsp 77 | 78 | .. code-block:: text 79 | 80 | nice one 81 | 82 | BTW if you google about "pade-approximation" you'll find a nice page with many solutions for common functions. 83 | 84 | there's exp, log, sin, cos, tan, gaussian... 85 | 86 | - **Date**: 2007-02-18 03:35:13 87 | - **By**: uh.etle.fni@yfoocs 88 | 89 | .. code-block:: text 90 | 91 | Yep, but the RCP increases the noise floor somewhat, giving a quantized sound, so I'd refrain from using it for high quality audio. 92 | 93 | -------------------------------------------------------------------------------- /source/Other/248-conversion-and-normalization-of-16-bit-sample-to-a-floating-point-number.rst: -------------------------------------------------------------------------------- 1 | Conversion and normalization of 16-bit sample to a floating point number 2 | ======================================================================== 3 | 4 | - **Author or source:** George Yohng 5 | - **Created:** 2007-05-02 13:34:21 6 | 7 | 8 | 9 | .. code-block:: c++ 10 | :linenos: 11 | :caption: code 12 | 13 | float out; 14 | signed short in; 15 | 16 | // This code does the same as 17 | // out = ((float)in)*(1.0f/32768.0f); 18 | // 19 | // Depending on the architecture and conversion settings, 20 | // it might be more optimal, though it is always 21 | // advisable to check its speed against genuine 22 | // algorithms. 23 | 24 | ((unsigned &)out)=0x43818000^in; 25 | out-=259.0f; 26 | 27 | Comments 28 | -------- 29 | 30 | - **Date**: 2007-05-15 06:09:54 31 | - **By**: moc.mot@lx_iruy 32 | 33 | .. code-block:: text 34 | 35 | Hi George Yohng 36 | 37 | I tried it... but it's create the heavy noise!! 38 | 39 | 40 | - **Date**: 2007-09-20 17:51:12 41 | - **By**: George Yohng 42 | 43 | .. code-block:: text 44 | 45 | Correction: 46 | ((unsigned &)out)=0x43818000^((unsigned short)in); 47 | out-=259.0f; 48 | 49 | (needs to have a cast to 'unsigned short') 50 | 51 | -------------------------------------------------------------------------------- /source/Other/250-piecewise-quadratic-approximate-exponential-function.rst: -------------------------------------------------------------------------------- 1 | Piecewise quadratic approximate exponential function 2 | ==================================================== 3 | 4 | - **Author or source:** Johannes M.-R. 5 | - **Type:** Approximation of base-2 exponential function 6 | - **Created:** 2007-06-18 08:09:58 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | The code assumes round-to-zero mode, and ieee 754 float. 13 | To achieve other bases, multiply the input by the logarithmus dualis of the base. 14 | 15 | 16 | .. code-block:: c++ 17 | :linenos: 18 | :caption: code 19 | 20 | inline float fpow2(const float y) 21 | { 22 | union 23 | { 24 | float f; 25 | int i; 26 | } c; 27 | 28 | int integer = (int)y; 29 | if(y < 0) 30 | integer = integer-1; 31 | 32 | float frac = y - (float)integer; 33 | 34 | c.i = (integer+127) << 23; 35 | c.f *= 0.33977f*frac*frac + (1.0f-0.33977f)*frac + 1.0f; 36 | 37 | return c.f; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /source/Other/252-fast-rounding-functions-in-pascal.rst: -------------------------------------------------------------------------------- 1 | Fast rounding functions in pascal 2 | ================================= 3 | 4 | - **Author or source:** moc.liamtoh@abuob 5 | - **Type:** round/ceil/floor/trunc 6 | - **Created:** 2008-03-09 13:09:44 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Original documentation with cpp samples: 13 | http://ldesoras.free.fr/prod.html#doc_rounding 14 | 15 | 16 | .. code-block:: c++ 17 | :linenos: 18 | :caption: code 19 | 20 | Pascal translation of the functions (accurates ones) : 21 | 22 | function ffloor(f:double):integer; 23 | var 24 | i:integer; 25 | t : double; 26 | begin 27 | t := -0.5 ; 28 | asm 29 | fld f 30 | fadd st,st(0) 31 | fadd t 32 | fistp i 33 | sar i, 1 34 | end; 35 | result:= i 36 | end; 37 | 38 | function fceil(f:double):integer; 39 | var 40 | i:integer; 41 | t : double; 42 | begin 43 | t := -0.5 ; 44 | asm 45 | fld f 46 | fadd st,st(0) 47 | fsubr t 48 | fistp i 49 | sar i, 1 50 | end; 51 | result:= -i 52 | end; 53 | 54 | function ftrunc(f:double):integer; 55 | var 56 | i:integer; 57 | t : double; 58 | begin 59 | t := -0.5 ; 60 | asm 61 | fld f 62 | fadd st,st(0) 63 | fabs 64 | fadd t 65 | fistp i 66 | sar i, 1 67 | end; 68 | if f<0 then i := -i; 69 | result:= i 70 | end; 71 | 72 | function fround(f:double):integer; 73 | var 74 | i:integer; 75 | t : double; 76 | begin 77 | t := 0.5 ; 78 | asm 79 | fld f 80 | fadd st,st(0) 81 | fadd t 82 | fistp i 83 | sar i, 1 84 | end; 85 | result:= i 86 | end; 87 | 88 | Comments 89 | -------- 90 | 91 | - **Date**: 2008-04-23 11:46:58 92 | - **By**: eb.mapstenykson@didid 93 | 94 | .. code-block:: text 95 | 96 | the fround doesn't make much sense in Pascal, as in Pascal (well, Delphi & I'm pretty sure FreePascal too), the default rounding is already a fast rounding. The default being FPU rounding to nearest mode, the compiler doesn't change it back & forth. & since it's inlined (well, compiler magic), it's very fast. 97 | 98 | -------------------------------------------------------------------------------- /source/Other/260-exponential-curve-for.rst: -------------------------------------------------------------------------------- 1 | Exponential curve for 2 | ===================== 3 | 4 | - **Author or source:** moc.liamg@321tiloen 5 | - **Type:** Exponential curve 6 | - **Created:** 2008-10-29 17:29:03 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | When you design a frequency control for your filters you may need an exponential curve to 13 | give the lower frequencies more resolution. 14 | 15 | F=20-20000hz 16 | x=0-100% 17 | 18 | Case (control middle point): 19 | x=50% 20 | F=1135hz 21 | 22 | Ploted diagram with 5 points: 23 | http://img151.imageshack.us/img151/9938/expplotur3.jpg 24 | 25 | 26 | 27 | .. code-block:: c++ 28 | :linenos: 29 | :caption: code 30 | 31 | //tweak - 14.15005 to change middle point and F(max) 32 | F = 19+floor(pow(4,x/14.15005))+x*20; 33 | 34 | 35 | 36 | Comments 37 | -------- 38 | 39 | - **Date**: 2008-10-30 13:47:16 40 | - **By**: moc.liamg@321tiloen 41 | 42 | .. code-block:: text 43 | 44 | same function with the more friendly exp(x) 45 | 46 | y = 19+floor(exp(x/10.2071))+x*20; 47 | 48 | middle point (x=50) is still at 1135hz 49 | 50 | - **Date**: 2008-10-31 01:14:13 51 | - **By**: moc.liamg@321tiloen 52 | 53 | .. code-block:: text 54 | 55 | Here is another function: 56 | This one is much more expensive but should sound more linear. 57 | 58 | //t - offset 59 | //x - 0-100% 60 | //y - 20-20000hz 61 | 62 | t = 64.925; 63 | y = floor(exp(x*log(1.059))*t - t/1.45); 64 | 65 | Comparison between the two: 66 | [IMG]http://img528.imageshack.us/img528/641/plot1nu1.jpg[/IMG] 67 | 68 | 69 | - **Date**: 2008-11-01 14:58:20 70 | - **By**: moc.liamg@321tiloen 71 | 72 | .. code-block:: text 73 | 74 | Yet another one! :) 75 | This is one should be the most linear one out of the 3. The 50% appears to be exactly the same as Voxengo span midpoint. 76 | 77 | //x - 0-100% 78 | //y - 20-20k 79 | 80 | y = floor(exp((16+x*1.20103)*log(1.059))*8.17742); 81 | 82 | //x=0, y=20 83 | //x=50, y=639 84 | //x=100, y=20000 85 | 86 | -------------------------------------------------------------------------------- /source/Other/48-double-to-int.rst: -------------------------------------------------------------------------------- 1 | Double to Int 2 | ============= 3 | 4 | - **Author or source:** many people, implementation by Andy M00cho 5 | - **Type:** pointer cast (round to zero, or 'trunctate') 6 | - **Created:** 2002-01-17 03:04:41 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | -Platform independant, literally. You have IEEE FP numbers, this will work, as long as 13 | your not expecting a signed integer back larger than 16bits :) 14 | -Will only work correctly for FP numbers within the range of [-32768.0,32767.0] 15 | -The FPU must be in Double-Precision mode 16 | 17 | 18 | .. code-block:: c++ 19 | :linenos: 20 | :caption: code 21 | 22 | typedef double lreal; 23 | typedef float real; 24 | typedef unsigned long uint32; 25 | typedef long int32; 26 | 27 | //2^36 * 1.5, (52-_shiftamt=36) uses limited precision to floor 28 | //16.16 fixed point representation 29 | 30 | const lreal _double2fixmagic = 68719476736.0*1.5; 31 | const int32 _shiftamt = 16; 32 | 33 | #if BigEndian_ 34 | #define iexp_ 0 35 | #define iman_ 1 36 | #else 37 | #define iexp_ 1 38 | #define iman_ 0 39 | #endif //BigEndian_ 40 | 41 | // Real2Int 42 | inline int32 Real2Int(lreal val) 43 | { 44 | val= val + _double2fixmagic; 45 | return ((int32*)&val)[iman_] >> _shiftamt; 46 | } 47 | 48 | // Real2Int 49 | inline int32 Real2Int(real val) 50 | { 51 | return Real2Int ((lreal)val); 52 | } 53 | 54 | For the x86 assembler freaks here's the assembler equivalent: 55 | 56 | __double2fixmagic dd 000000000h,042380000h 57 | 58 | fld AFloatingPoint Number 59 | fadd QWORD PTR __double2fixmagic 60 | fstp TEMP 61 | movsx eax,TEMP+2 62 | 63 | Comments 64 | -------- 65 | 66 | - **Date**: 2007-01-28 20:13:49 67 | - **By**: ude.odu@grebnesie.nitram 68 | 69 | .. code-block:: text 70 | 71 | www.stereopsis.com/FPU.html credits one Sree Kotay for this code. 72 | 73 | - **Date**: 2007-07-11 06:17:12 74 | - **By**: kd.sgnik3@sumsar 75 | 76 | .. code-block:: text 77 | 78 | On PC this may be faster/easier: 79 | 80 | int ftoi(float x) 81 | { 82 | int res; 83 | __asm 84 | { 85 | fld x 86 | fistp res 87 | } 88 | return res; 89 | } 90 | 91 | int dtoi(double x) 92 | { 93 | return ftoi((float)x); 94 | } 95 | 96 | 97 | -------------------------------------------------------------------------------- /source/Other/49-cubic-interpollation.rst: -------------------------------------------------------------------------------- 1 | Cubic interpollation 2 | ==================== 3 | 4 | - **Author or source:** Olli Niemitalo 5 | - **Type:** interpollation 6 | - **Created:** 2002-01-17 03:05:33 7 | 8 | - **Linked files:** :download:`other001.gif <../files/other001.gif>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | (see linkfile) 14 | finpos is the fractional, inpos the integer part. 15 | 16 | 17 | 18 | .. code-block:: c++ 19 | :linenos: 20 | :caption: code 21 | 22 | xm1 = x [inpos - 1]; 23 | x0 = x [inpos + 0]; 24 | x1 = x [inpos + 1]; 25 | x2 = x [inpos + 2]; 26 | a = (3 * (x0-x1) - xm1 + x2) / 2; 27 | b = 2*x1 + xm1 - (5*x0 + x2) / 2; 28 | c = (x1 - xm1) / 2; 29 | y [outpos] = (((a * finpos) + b) * finpos + c) * finpos + x0; 30 | 31 | -------------------------------------------------------------------------------- /source/Other/51-denormal-numbers.rst: -------------------------------------------------------------------------------- 1 | Denormal numbers 2 | ================ 3 | 4 | - **Author or source:** Compiled by Merlijn Blaauw 5 | - **Created:** 2002-01-17 03:06:39 6 | 7 | - **Linked files:** :download:`other001.txt <../files/other001.txt>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | this text describes some ways to avoid denormalisation. Denormalisation happens when 13 | FPU's go mad processing very small numbers 14 | 15 | 16 | 17 | Comments 18 | -------- 19 | 20 | - **Date**: 2004-01-31 05:20:38 21 | - **By**: moc.dh2a@ydna 22 | 23 | .. code-block:: text 24 | 25 | See also the entry about 'branchless min, max and clip' by Laurent Soras in this section, 26 | 27 | Using the following function, 28 | 29 | float clip (float x, float a, float b) 30 | { 31 | x1 = fabs (x-a); 32 | x2 = fabs (x-b); 33 | x = x1 + (a+b); 34 | x -= x2; 35 | x *= 0.5; 36 | return (x); 37 | } 38 | 39 | If you apply clipping from -1.0 to 1.0 will have a side effect of squashing denormal numbers to zero due to loss of precision on the order of ~1.0.e-20. The upside is that it is branchless, but possibly more expensive than adding noise and certainly more so than adding a DC offset. 40 | 41 | 42 | -------------------------------------------------------------------------------- /source/Other/52-conversions-on-a-powerpc.rst: -------------------------------------------------------------------------------- 1 | Conversions on a PowerPC 2 | ======================== 3 | 4 | - **Author or source:** James McCartney 5 | - **Type:** motorola ASM conversions 6 | - **Created:** 2002-01-17 03:07:18 7 | 8 | 9 | 10 | .. code-block:: c++ 11 | :linenos: 12 | :caption: code 13 | 14 | double ftod(float x) { return (double)x; 15 | 00000000: 4E800020 blr 16 | // blr == return from subroutine, i.e. this function is a noop 17 | 18 | float dtof(double x) { return (float)x; 19 | 00000000: FC200818 frsp fp1,fp1 20 | 00000004: 4E800020 blr 21 | 22 | int ftoi(float x) { return (int)x; 23 | 00000000: FC00081E fctiwz fp0,fp1 24 | 00000004: D801FFF0 stfd fp0,-16(SP) 25 | 00000008: 8061FFF4 lwz r3,-12(SP) 26 | 0000000C: 4E800020 blr 27 | 28 | int dtoi(double x) { return (int)x; 29 | 00000000: FC00081E fctiwz fp0,fp1 30 | 00000004: D801FFF0 stfd fp0,-16(SP) 31 | 00000008: 8061FFF4 lwz r3,-12(SP) 32 | 0000000C: 4E800020 blr 33 | 34 | double itod(int x) { return (double)x; 35 | 00000000: C8220000 lfd fp1,@1558(RTOC) 36 | 00000004: 6C608000 xoris r0,r3,$8000 37 | 00000008: 9001FFF4 stw r0,-12(SP) 38 | 0000000C: 3C004330 lis r0,17200 39 | 00000010: 9001FFF0 stw r0,-16(SP) 40 | 00000014: C801FFF0 lfd fp0,-16(SP) 41 | 00000018: FC200828 fsub fp1,fp0,fp1 42 | 0000001C: 4E800020 blr 43 | 44 | float itof(int x) { return (float)x; 45 | 00000000: C8220000 lfd fp1,@1558(RTOC) 46 | 00000004: 6C608000 xoris r0,r3,$8000 47 | 00000008: 9001FFF4 stw r0,-12(SP) 48 | 0000000C: 3C004330 lis r0,17200 49 | 00000010: 9001FFF0 stw r0,-16(SP) 50 | 00000014: C801FFF0 lfd fp0,-16(SP) 51 | 00000018: EC200828 fsubs fp1,fp0,fp1 52 | 0000001C: 4E800020 blr 53 | 54 | -------------------------------------------------------------------------------- /source/Other/54-allocating-aligned-memory.rst: -------------------------------------------------------------------------------- 1 | Allocating aligned memory 2 | ========================= 3 | 4 | - **Author or source:** Benno Senoner 5 | - **Type:** memory allocation 6 | - **Created:** 2002-01-17 03:08:46 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | we waste up to align_size + sizeof(int) bytes when we alloc a memory area. 13 | We store the aligned_ptr - unaligned_ptr delta in an int located before the aligned area. 14 | This is needed for the free() routine since we need to free all the memory not only the 15 | aligned area. 16 | You have to use aligned_free() to free the memory allocated with aligned_malloc() ! 17 | 18 | 19 | .. code-block:: c++ 20 | :linenos: 21 | :caption: code 22 | 23 | /* align_size has to be a power of two !! */ 24 | void *aligned_malloc(size_t size, size_t align_size) { 25 | 26 | char *ptr,*ptr2,*aligned_ptr; 27 | int align_mask = align_size - 1; 28 | 29 | ptr=(char *)malloc(size + align_size + sizeof(int)); 30 | if(ptr==NULL) return(NULL); 31 | 32 | ptr2 = ptr + sizeof(int); 33 | aligned_ptr = ptr2 + (align_size - ((size_t)ptr2 & align_mask)); 34 | 35 | 36 | ptr2 = aligned_ptr - sizeof(int); 37 | *((int *)ptr2)=(int)(aligned_ptr - ptr); 38 | 39 | return(aligned_ptr); 40 | } 41 | 42 | void aligned_free(void *ptr) { 43 | 44 | int *ptr2=(int *)ptr - 1; 45 | ptr -= *ptr2; 46 | free(ptr); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /source/Other/55-pow-x-4-approximation.rst: -------------------------------------------------------------------------------- 1 | Pow(x,4) approximation 2 | ====================== 3 | 4 | - **Author or source:** Stefan Stenzel 5 | - **Created:** 2002-01-17 03:09:20 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | Very hacked, but it gives a rough estimate of x**4 by modifying exponent and mantissa. 12 | 13 | 14 | .. code-block:: c++ 15 | :linenos: 16 | :caption: code 17 | 18 | float p4fast(float in) 19 | { 20 | long *lp,l; 21 | 22 | lp=(long *)(&in); 23 | l=*lp; 24 | 25 | l-=0x3F800000l; /* un-bias */ 26 | l<<=2; /* **4 */ 27 | l+=0x3F800000l; /* bias */ 28 | *lp=l; 29 | 30 | /* compiler will read this from memory since & operator had been used */ 31 | return in; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /source/Other/56-float-to-int.rst: -------------------------------------------------------------------------------- 1 | Float to int 2 | ============ 3 | 4 | - **Author or source:** Ross Bencina 5 | - **Created:** 2002-01-17 03:15:14 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | intel only 12 | 13 | 14 | .. code-block:: c++ 15 | :linenos: 16 | :caption: code 17 | 18 | int truncate(float flt) 19 | { 20 | int i; 21 | static const double half = 0.5f; 22 | _asm 23 | { 24 | fld flt 25 | fsub half 26 | fistp i 27 | } 28 | return i 29 | } 30 | 31 | Comments 32 | -------- 33 | 34 | - **Date**: 2002-06-11 20:12:11 35 | - **By**: moc.xinortceletrams@ahaj 36 | 37 | .. code-block:: text 38 | 39 | Note: Round nearest doesn't work, because the Intel FPU uses Even-Odd rounding in order to conform to the IEEE floating-point standard: when the FPU is set to use the round-nearest rule, values whose fractional part is exactly 0.5 40 | round toward the nearest *even* integer. Thus, 1.5 rounds to 2, 2.5 rounds to 2, 3.5 rounds to 4. This is quite disastrous for the FLOOR/CEIL 41 | functions if you use the strategy you describe. 42 | 43 | 44 | - **Date**: 2003-05-28 21:25:24 45 | - **By**: moc.oohay@tuanogus 46 | 47 | .. code-block:: text 48 | 49 | This version below seems to be more accurate on my Win32/P4. Doesn't deal with the Intel FPU issue. A faster solution than c-style casts though. But you're not always going to get the most accurate conversion. Like the previous comment; 2.5 will convert to 2, but 2.501 will convert to 3. 50 | 51 | int truncate(float flt) 52 | { 53 | int i; 54 | _asm 55 | { 56 | fld flt 57 | fistp i 58 | } 59 | return i 60 | } 61 | 62 | - **Date**: 2004-04-07 01:20:49 63 | - **By**: moc.erehwon@amsuk 64 | 65 | .. code-block:: text 66 | 67 | if you use msvc, just use the /QIfist compile-switch 68 | 69 | -------------------------------------------------------------------------------- /source/Other/58-matlab-tools-for-sndan.rst: -------------------------------------------------------------------------------- 1 | MATLAB-Tools for SNDAN 2 | ====================== 3 | 4 | - **Author or source:** Markus Sapp 5 | - **Created:** 2002-01-17 03:11:05 6 | 7 | - **Linked files:** :download:`other001.zip <../files/other001.zip>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | (see linkfile) 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /source/Other/61-dither-code.rst: -------------------------------------------------------------------------------- 1 | Dither code 2 | =========== 3 | 4 | - **Author or source:** Paul Kellett 5 | - **Type:** Dither with noise-shaping 6 | - **Created:** 2002-01-17 03:13:20 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This is a simple implementation of highpass triangular-PDF dither (a good general-purpose 13 | dither) with optional 2nd-order noise shaping (which lowers the noise floor by 11dB below 14 | 0.1 Fs). 15 | The code assumes input data is in the range +1 to -1 and doesn't check for overloads! 16 | 17 | To save time when generating dither for multiple channels you can re-use lower bits of a 18 | previous random number instead of calling rand() again. e.g. r3=(r1 & 0x7F)<<8; 19 | 20 | 21 | .. code-block:: c++ 22 | :linenos: 23 | :caption: code 24 | 25 | int r1, r2; //rectangular-PDF random numbers 26 | float s1, s2; //error feedback buffers 27 | float s = 0.5f; //set to 0.0f for no noise shaping 28 | float w = pow(2.0,bits-1); //word length (usually bits=16) 29 | float wi= 1.0f/w; 30 | float d = wi / RAND_MAX; //dither amplitude (2 lsb) 31 | float o = wi * 0.5f; //remove dc offset 32 | float in, tmp; 33 | int out; 34 | 35 | //for each sample... 36 | 37 | r2=r1; //can make HP-TRI dither by 38 | r1=rand(); //subtracting previous rand() 39 | 40 | in += s * (s1 + s1 - s2); //error feedback 41 | tmp = in + o + d * (float)(r1 - r2); //dc offset and dither 42 | 43 | out = (int)(w * tmp); //truncate downwards 44 | if(tmp<0.0f) out--; //this is faster than floor() 45 | 46 | s2 = s1; 47 | s1 = in - wi * (float)out; //error 48 | 49 | -------------------------------------------------------------------------------- /source/Other/71-constant-time-exponent-of-2-detector.rst: -------------------------------------------------------------------------------- 1 | Constant-time exponent of 2 detector 2 | ==================================== 3 | 4 | - **Author or source:** Brent Lehman (moc.oohay@ljbliam) 5 | - **Created:** 2002-02-10 12:53:15 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | In your common FFT program, you want to make sure that the frame you're working with has a 12 | size that is a power of 2. This tells you in just a few operations. Granted, you won't 13 | be using this algorithm inside a loop, so the savings aren't that great, but every little 14 | hack helps ;) 15 | 16 | 17 | .. code-block:: c++ 18 | :linenos: 19 | :caption: code 20 | 21 | // Quit if size isn't a power of 2 22 | if ((-size ^ size) & size) return; 23 | 24 | // If size is an unsigned int, the above might not compile. 25 | // You'd want to use this instead: 26 | if (((~size + 1) ^ size) & size) return; 27 | 28 | Comments 29 | -------- 30 | 31 | - **Date**: 2002-02-12 03:20:11 32 | - **By**: moc.oohay@xrotcnuf 33 | 34 | .. code-block:: text 35 | 36 | I think I prefer: 37 | 38 | if (! (size & (size - 1))) return; 39 | 40 | I'm not positive this is fewer instructions than the above, but I think it's easier to see why it works (n and n-1 will share bits unless n is a power of two), and it doesn't require two's-complement. 41 | 42 | - Tom 7 43 | 44 | 45 | -------------------------------------------------------------------------------- /source/Other/77-dithering.rst: -------------------------------------------------------------------------------- 1 | Dithering 2 | ========= 3 | 4 | - **Author or source:** Paul Kellett 5 | - **Created:** 2002-02-11 17:41:21 6 | 7 | - **Linked files:** :download:`nsdither.txt <../files/nsdither.txt>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | (see linked file) 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /source/Other/83-denormal-numbers-the-meta-text.rst: -------------------------------------------------------------------------------- 1 | Denormal numbers, the meta-text 2 | =============================== 3 | 4 | - **Author or source:** Laurent de Soras 5 | - **Created:** 2002-02-15 00:16:30 6 | 7 | - **Linked files:** :download:`denormal.pdf <../files/denormal.pdf>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This very interesting paper, written by Laurent de Soras (www.ohmforce.com) has everything 13 | you ever wanted to know about denormal numbers! And it obviously descibes how you can get 14 | rid of them too! 15 | 16 | (see linked file) 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /source/Other/84-reading-the-compressed-wa-parts-in-gigasampler-files.rst: -------------------------------------------------------------------------------- 1 | Reading the compressed WA! parts in gigasampler files 2 | ===================================================== 3 | 4 | - **Author or source:** Paul Kellett 5 | - **Created:** 2002-02-18 00:51:08 6 | 7 | - **Linked files:** :download:`gigxpand.zip <../files/gigxpand.zip>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | (see linkfile) 13 | Code to read the .WA! (compressed .WAV) parts of GigaSampler .GIG files. 14 | For related info on reading .GIG files see http://www.linuxdj.com/evo 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /source/Other/87-exponential-parameter-mapping.rst: -------------------------------------------------------------------------------- 1 | Exponential parameter mapping 2 | ============================= 3 | 4 | - **Author or source:** Russell Borogove 5 | - **Created:** 2002-03-17 15:42:33 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | Use this if you want to do an exponential map of a parameter (mParam) to a range (mMin - 12 | mMax). 13 | Output is in mData... 14 | 15 | 16 | .. code-block:: c++ 17 | :linenos: 18 | :caption: code 19 | 20 | float logmax = log10f( mMax ); 21 | float logmin = log10f( mMin ); 22 | float logdata = (mParam * (logmax-logmin)) + logmin; 23 | 24 | mData = powf( 10.0f, logdata ); 25 | if (mData < mMin) 26 | { 27 | mData = mMin; 28 | } 29 | if (mData > mMax) 30 | { 31 | mData = mMax; 32 | } 33 | 34 | Comments 35 | -------- 36 | 37 | - **Date**: 2002-03-26 00:28:53 38 | - **By**: moc.nsm@seivadrer 39 | 40 | .. code-block:: text 41 | 42 | No point in using heavy functions when lighter-weight functions work just as well. Use ln instead of log10f, and exp instead of pow(10,x). Log-linear is the same, no matter which base you're using, and base e is way more efficient than base 10. 43 | 44 | - **Date**: 2002-12-06 01:31:55 45 | - **By**: moc.noicratse@ajelak 46 | 47 | .. code-block:: text 48 | 49 | Thanks for the tip. A set of VST param wrapper classes which offers linear float, exponential float, integer selection, and text selection controls, using this technique for the exponential response, can be found in the VST source code archive -- finally. 50 | 51 | - **Date**: 2003-08-21 16:01:01 52 | - **By**: moc.oohay@noi_tca 53 | 54 | .. code-block:: text 55 | 56 | Just made my day! 57 | pretty useful :) cheers Aktion 58 | 59 | - **Date**: 2006-09-08 18:27:33 60 | - **By**: agillesp@gmail 61 | 62 | .. code-block:: text 63 | 64 | You can trade an (expensive) ln for a (cheaper) divide here because of the logarithmic identity: 65 | 66 | ln(x) - ln(y) == ln(x/y) 67 | 68 | 69 | -------------------------------------------------------------------------------- /source/Other/88-denormal-double-variables-macro.rst: -------------------------------------------------------------------------------- 1 | Denormal DOUBLE variables, macro 2 | ================================ 3 | 4 | - **Author or source:** Jon Watte 5 | - **Created:** 2002-03-17 15:44:31 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | Use this macro if you want to find denormal numbers and you're using doubles... 12 | 13 | 14 | .. code-block:: c++ 15 | :linenos: 16 | :caption: code 17 | 18 | #if PLATFORM_IS_BIG_ENDIAN 19 | #define INDEX 0 20 | #else 21 | #define INDEX 1 22 | #endif 23 | inline bool is_denormal( double const & d ) { 24 | assert( sizeof( d ) == 2*sizeof( int ) ); 25 | int l = ((int *)&d)[INDEX]; 26 | return (l&0x7fe00000) != 0; 27 | } 28 | 29 | Comments 30 | -------- 31 | 32 | - **Date**: 2005-05-14 17:19:48 33 | - **By**: dont-email-me 34 | 35 | .. code-block:: text 36 | 37 | put the #if inside the function itself 38 | 39 | -------------------------------------------------------------------------------- /source/Other/95-16-to-8-bit-first-order-dither.rst: -------------------------------------------------------------------------------- 1 | 16-to-8-bit first-order dither 2 | ============================== 3 | 4 | - **Author or source:** Jon Watte 5 | - **Type:** First order error feedforward dithering code 6 | - **Created:** 2002-04-12 13:52:36 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This is about as simple a dithering algorithm as you can implement, but it's likely to 13 | sound better than just truncating to N bits. 14 | 15 | Note that you might not want to carry forward the full difference for infinity. It's 16 | probably likely that the worst performance hit comes from the saturation conditionals, 17 | which can be avoided with appropriate instructions on many DSPs and integer SIMD type 18 | instructions, or CMOV. 19 | 20 | Last, if sound quality is paramount (such as when going from > 16 bits to 16 bits) you 21 | probably want to use a higher-order dither function found elsewhere on this site. 22 | 23 | 24 | 25 | .. code-block:: c++ 26 | :linenos: 27 | :caption: code 28 | 29 | // This code will down-convert and dither a 16-bit signed short 30 | // mono signal into an 8-bit unsigned char signal, using a first 31 | // order forward-feeding error term dither. 32 | 33 | #define uchar unsigned char 34 | 35 | void dither_one_channel_16_to_8( short * input, uchar * output, int count, int * memory ) 36 | { 37 | int m = *memory; 38 | while( count-- > 0 ) { 39 | int i = *input++; 40 | i += m; 41 | int j = i + 32768 - 128; 42 | uchar o; 43 | if( j < 0 ) { 44 | o = 0; 45 | } 46 | else if( j > 65535 ) { 47 | o = 255; 48 | } 49 | else { 50 | o = (uchar)((j>>8)&0xff); 51 | } 52 | m = ((j-32768+128)-i); 53 | *output++ = o; 54 | } 55 | *memory = m; 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /source/Other/99-noise-shaping-class.rst: -------------------------------------------------------------------------------- 1 | Noise Shaping Class 2 | =================== 3 | 4 | - **Author or source:** ude.anaidni@iehsc 5 | - **Type:** Dithering with 9th order noise shaping 6 | - **Created:** 2002-04-23 06:49:06 7 | 8 | - **Linked files:** :download:`NS9dither16.h <../files/NS9dither16.h>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | This is an implemetation of a 9th order noise shaping & dithering class, that runs quite 14 | fast (it has one function that uses Intel x86 assembly, but you can replace it with a 15 | different rounding function if you are running on a non-Intel platform). _aligned_malloc 16 | and _aligned_free require the MSVC++ Processor Pack, available from www.microsoft.com. 17 | You can replace them with "new" and "delete," but allocating aligned memory seems to make 18 | it run faster. Also, you can replace ZeroMemory with a memset that sets the memory to 0 19 | if you aren't using Win32. 20 | Input should be floats from -32768 to 32767 (processS will clip at these points for you, 21 | but clipping is bad when you are trying to convert floats to shorts). Note to reviewer - 22 | it would probably be better if you put the code in a file such as NSDither.h and have a 23 | link to it - it's rather long. 24 | 25 | (see linked file) 26 | 27 | 28 | 29 | Comments 30 | -------- 31 | 32 | - **Date**: 2003-05-14 14:01:22 33 | - **By**: mail[ns]@mutagene.net 34 | 35 | .. code-block:: text 36 | 37 | I haven't tried this class out, but it looks like there's a typo in the unrolled loop -- shouldn't it read "c[2]*EH[HistPos+2]"? This might this also account for the 3 clock cycle improvement on a P-III. 38 | 39 | // This arrangement seems to execute 3 clock cycles faster on a P-III 40 | samp -= c[8]*EH[HistPos+8] + c[7]*EH[HistPos+7] + c[6]*EH[HistPos+6] + 41 | c[5]*EH[HistPos+5] + c[4]*EH[HistPos+4] + c[3]*EH[HistPos+3] + c[2]*EH[HistPos+1] + 42 | c[1]*EH[HistPos+1] + c[0]*EH[HistPos]; 43 | 44 | 45 | 46 | - **Date**: 2005-02-15 15:18:55 47 | - **By**: moc.tnemarkas@vokiahc 48 | 49 | .. code-block:: text 50 | 51 | Great class! But I found one more mistake: function my_mod(9, 9) gives 9 instead of 0 (9 % 9 = 0). 52 | 53 | HistPos = my_mod((HistPos+8), order); 54 | EH[HistPos+9] = EH[HistPos] = output - samp; 55 | 56 | -> HistPos + 9 = 18 (max EH index is 17) which leads to out of array boundary and crash. 57 | 58 | So my_mod should look like: 59 | 60 | __inline my_mod(int x, int n) 61 | { 62 | if(x >= n) x-=n; 63 | return x; 64 | } 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /source/Synthesis/1-alias-free-waveform-generation-with-analog-filtering.rst: -------------------------------------------------------------------------------- 1 | Alias-free waveform generation with analog filtering 2 | ==================================================== 3 | 4 | - **Author or source:** Magnus Jonsson 5 | - **Type:** waveform generation 6 | - **Created:** 2002-01-15 21:25:29 7 | 8 | - **Linked files:** :download:`synthesis001.txt <../files/synthesis001.txt>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | (see linkfile) 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /source/Synthesis/11-weird-synthesis.rst: -------------------------------------------------------------------------------- 1 | Weird synthesis 2 | =============== 3 | 4 | - **Author or source:** Andy M00cho 5 | - **Created:** 2002-01-17 00:55:09 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | (quoted from Andy's mail...) 12 | What I've done in a soft-synth I've been working on is used what I've termed Fooglers, no 13 | reason, just liked the name :) Anyway all I've done is use a *VERY* short delay line of 14 | 256 samples and then use 2 controllable taps into the delay with High Frequency Damping, 15 | and a feedback parameter. 16 | 17 | Using a tiny fixed delay size of approx. 4.8ms (really 256 samples/1k memory with floats) 18 | means this costs, in terms of cpu consumption practically nothing, and the filter is a 19 | real simple 1 pole low-pass filter. Maybe not DSP'litically correct but all I wanted was 20 | to avoid the high frequencies trashing the delay line when high feedbacks (99%->99.9%) are 21 | used (when the fun starts ;). 22 | 23 | I've been getting some really sexy sounds out of this idea, and of course you can have the 24 | delay line tuneable if you choose to use fractional taps, but I'm happy with it as it is.. 25 | 1 nice simple, yet powerful addition to the base oscillators. 26 | 27 | In reality you don't need 2 taps, but I found that using 2 added that extra element of 28 | funkiness... 29 | 30 | 31 | 32 | Comments 33 | -------- 34 | 35 | - **Date**: 2002-07-18 18:57:00 36 | - **By**: moc.loa@attongamlihp 37 | 38 | .. code-block:: text 39 | 40 | Andy: 41 | I'm curious about your delay line. It's length is 42 | 4.8 m.sec.fixed. What are the variables in the two controllable taps and is the 6dB filter variable frequency wise? 43 | Phil 44 | 45 | - **Date**: 2003-01-03 20:01:34 46 | - **By**: moc.oohay@poportcele 47 | 48 | .. code-block:: text 49 | 50 | What you have there is the core of a physical modelling algorithm. I have done virtually the same thing to model plucked string instruments in Reaktor. It's amazingly realistic. See http://joeorgren.com 51 | 52 | -------------------------------------------------------------------------------- /source/Synthesis/111-phase-modulation-vs-frequency-modulation.rst: -------------------------------------------------------------------------------- 1 | Phase modulation Vs. Frequency modulation 2 | ========================================= 3 | 4 | - **Author or source:** Bram 5 | - **Created:** 2002-08-05 15:31:25 6 | 7 | - **Linked files:** :download:`SimpleOscillator.h <../files/SimpleOscillator.h>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This code shows what the difference is betwee FM and PM. 13 | The code is NOT optimised, nor should it be used like this. 14 | It is an EXAMPLE 15 | 16 | See linked file. 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /source/Synthesis/112-waveform-generator-using-minbleps.rst: -------------------------------------------------------------------------------- 1 | Waveform generator using MinBLEPS 2 | ================================= 3 | 4 | - **Author or source:** ku.oc.nomed.nafgpr@ekcol 5 | - **Created:** 2002-08-05 18:44:50 6 | 7 | - **Linked files:** :download:`MinBLEPS.zip <../files/MinBLEPS.zip>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | C code and project file for MSVC6 for a bandwidth-limited saw/square (with PWM) generator 13 | using MinBLEPS. 14 | 15 | This code is based on Eli's MATLAB MinBLEP code and uses his original minblep.mat file. 16 | Instead of keeping a list of all active MinBLEPS, the output of each MinBLEP is stored in 17 | a buffer, in which all consequent MinBLEPS and the waveform output are added together. 18 | This optimization makes it fast enough to be used realtime. 19 | 20 | Produces slight aliasing when sweeping high frequencies. I don't know wether Eli's 21 | original code does the same, because I don't have MATLAB. Any help would be appreciated. 22 | 23 | The project name is 'hardsync', because it's easy to generate hardsync using MinBLEPS. 24 | 25 | 26 | .. code-block:: c++ 27 | :linenos: 28 | :caption: code 29 | 30 | 31 | 32 | 33 | 34 | Comments 35 | -------- 36 | 37 | - **Date**: 2004-07-02 22:31:36 38 | - **By**: moc.oiduaesionetihw@ofni 39 | 40 | .. code-block:: text 41 | 42 | http://www.slack.net/~ant/bl-synth/windowed-impulse/ 43 | 44 | This page also describes a similar algorithm for generating waves. Could the aliasing be due to the fact that the blep only occurs after the discontinuity? On this page the blep also occurs in the opposite direction as well, leading up to the discontinuity. 45 | 46 | - **Date**: 2008-02-11 18:42:15 47 | - **By**: kernel[@}audiospillage.com 48 | 49 | .. code-block:: text 50 | 51 | The sawtooth is a nice oscillator but I can't seem to get the square wave to work properly. Anyone else had any luck with this? Also, it's worth noting that the code assumes it is running on a little endian architecture. 52 | 53 | - **Date**: 2009-07-07 04:45:40 54 | - **By**: moc.enecslatnemirepxe@leinad 55 | 56 | .. code-block:: text 57 | 58 | I have written GPLv3 C++ source code for a MinBLEP oscillator and also public domain C++ source code for generating the MinBLEP without MatLab. 59 | 60 | http://www.experimentalscene.com/articles/minbleps.php - Article and Code 61 | 62 | http://www.experimentalscene.com/source.php - Look in DarkWave / latest version / CoreMachines / VCO.cpp 63 | 64 | -------------------------------------------------------------------------------- /source/Synthesis/113-gaussian-white-noise.rst: -------------------------------------------------------------------------------- 1 | Gaussian White Noise 2 | ==================== 3 | 4 | - **Author or source:** uh.atsopten@egamer 5 | - **Created:** 2002-08-07 16:23:28 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | SOURCE: 12 | 13 | Steven W. Smith: 14 | The Scientist and Engineer's Guide to Digital Signal Processing 15 | http://www.dspguide.com 16 | 17 | 18 | .. code-block:: c++ 19 | :linenos: 20 | :caption: code 21 | 22 | #define PI 3.1415926536f 23 | 24 | float R1 = (float) rand() / (float) RAND_MAX; 25 | float R2 = (float) rand() / (float) RAND_MAX; 26 | 27 | float X = (float) sqrt( -2.0f * log( R1 )) * cos( 2.0f * PI * R2 ); 28 | 29 | 30 | Comments 31 | -------- 32 | 33 | - **Date**: 2002-08-28 02:05:50 34 | - **By**: gro.sdikgninnips@nap 35 | 36 | .. code-block:: text 37 | 38 | The previous one seems better for me, since it requires only a rand, half log and half sqrt per sample. 39 | Actually, I used that one, but I can't remember where I found it, too. Maybe on Knuth's book. 40 | 41 | -------------------------------------------------------------------------------- /source/Synthesis/13-sine-calculation.rst: -------------------------------------------------------------------------------- 1 | Sine calculation 2 | ================ 3 | 4 | - **Author or source:** Phil Burk 5 | - **Type:** waveform generation, Taylor approximation of sin() 6 | - **Created:** 2002-01-17 00:57:01 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Code from JSyn for a sine wave generator based on a Taylor Expansion. It is not as 13 | efficient as the filter methods, but it has linear frequency control and is, therefore, 14 | suitable for FM or other time varying applications where accurate frequency is needed. The 15 | sine generated is accurate to at least 16 bits. 16 | 17 | 18 | .. code-block:: c++ 19 | :linenos: 20 | :caption: code 21 | 22 | for(i=0; i < nSamples ; i++) 23 | { 24 | //Generate sawtooth phasor to provide phase for sine generation 25 | IncrementWrapPhase(phase, freqPtr[i]); 26 | //Wrap phase back into region where results are more accurate 27 | 28 | if(phase > 0.5) 29 | yp = 1.0 - phase; 30 | else 31 | { 32 | if(phase < -0.5) 33 | yp = -1.0 - phase; 34 | else 35 | yp = phase; 36 | } 37 | 38 | x = yp * PI; 39 | x2 = x*x; 40 | 41 | //Taylor expansion out to x**9/9! factored into multiply-adds 42 | fastsin = x*(x2*(x2*(x2*(x2*(1.0/362880.0) 43 | - (1.0/5040.0)) 44 | + (1.0/120.0)) 45 | - (1.0/6.0)) 46 | + 1.0); 47 | 48 | outPtr[i] = fastsin * amplPtr[i]; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /source/Synthesis/14-inverted-parabolic-envelope.rst: -------------------------------------------------------------------------------- 1 | Inverted parabolic envelope 2 | =========================== 3 | 4 | - **Author or source:** James McCartney 5 | - **Type:** envellope generation 6 | - **Created:** 2002-01-17 00:57:43 7 | 8 | 9 | 10 | .. code-block:: c++ 11 | :linenos: 12 | :caption: code 13 | 14 | dur = duration in samples 15 | midlevel = amplitude at midpoint 16 | beglevel = beginning and ending level (typically zero) 17 | 18 | amp = midlevel - beglevel; 19 | 20 | rdur = 1.0 / dur; 21 | rdur2 = rdur * rdur; 22 | 23 | level = beglevel; 24 | slope = 4.0 * amp * (rdur - rdur2); 25 | curve = -8.0 * amp * rdur2; 26 | 27 | ... 28 | 29 | for (i=0; i 1, but the min statement in the code must be 27 | removed, and the scaling will be weird. 28 | 29 | 30 | .. code-block:: c++ 31 | :linenos: 32 | :caption: code 33 | 34 | function output = dsf( freq, a, H, samples, beta) 35 | %a = rolloff coeffecient 36 | %H = number of harmonic overtones (fundamental not included) 37 | %beta = harmonic phase shift 38 | 39 | samplerate = 44.1e3; 40 | freq = freq/samplerate; %normalize frequency 41 | 42 | bandlimit = samplerate / 2; %Nyquist 43 | maxN = 1 + floor( bandlimit / freq ); %prevent aliasing 44 | N = min(H+2,maxN); 45 | 46 | theta = 2*pi * phasor(freq, samples); 47 | 48 | epsilon = 1e-6; 49 | a = min(a, 1-epsilon); %prevent divide by zero 50 | 51 | num = sin(beta) - a*sin(beta-theta) - a^N*sin(beta + N*theta) + a^(N+1)*sin(beta+(N-1)*theta); 52 | den = (1 + a * ( a - 2*cos(theta) )); 53 | 54 | output = 2*(num ./ den - 1) * freq; %subtract by one to remove DC, scale by freq to normalize 55 | output = output * maxN/N; %OPTIONAL: rescale to give louder output as rolloff increases 56 | 57 | function out = phasor(normfreq, samples); 58 | out = mod( (0:samples-1)*normfreq , 1); 59 | out = out * 2 - 1; %make bipolar 60 | 61 | 62 | Comments 63 | -------- 64 | 65 | - **Date**: 2003-04-03 15:05:42 66 | - **By**: David Lowenfels 67 | 68 | .. code-block:: text 69 | 70 | oops, there's an error in this version. frequency should not be normalized until after the maxN calculation is done. 71 | 72 | -------------------------------------------------------------------------------- /source/Synthesis/168-c-gaussian-noise-generation.rst: -------------------------------------------------------------------------------- 1 | C++ gaussian noise generation 2 | ============================= 3 | 4 | - **Author or source:** ku.oc.latigidpxe@luap 5 | - **Type:** gaussian noise generation 6 | - **Created:** 2004-05-20 09:12:55 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | References : 13 | Tobybears delphi noise generator was the basis. Simply converted it to C++. 14 | Link for original is: 15 | http://www.musicdsp.org/archive.php?classid=0#129 16 | The output is in noise. 17 | 18 | 19 | .. code-block:: c++ 20 | :linenos: 21 | :caption: code 22 | 23 | /* Include requisits */ 24 | #include 25 | #include 26 | 27 | /* Generate a new random seed from system time - do this once in your constructor */ 28 | srand(time(0)); 29 | 30 | /* Setup constants */ 31 | const static int q = 15; 32 | const static float c1 = (1 << q) - 1; 33 | const static float c2 = ((int)(c1 / 3)) + 1; 34 | const static float c3 = 1.f / c1; 35 | 36 | /* random number in range 0 - 1 not including 1 */ 37 | float random = 0.f; 38 | 39 | /* the white noise */ 40 | float noise = 0.f; 41 | 42 | for (int i = 0; i < numSamples; i++) 43 | { 44 | random = ((float)rand() / (float)(RAND_MAX + 1)); 45 | noise = (2.f * ((random * c2) + (random * c2) + (random * c2)) - 3.f * (c2 - 1.f)) * c3; 46 | } 47 | 48 | Comments 49 | -------- 50 | 51 | - **Date**: 2009-07-10 17:39:39 52 | - **By**: moc.enon@enon 53 | 54 | .. code-block:: text 55 | 56 | What's the difference between the much simpler noise generator: 57 | 58 | randSeed = (randSeed * 196314165) + 907633515; out=((int)randSeed)*0.0000000004656612873077392578125f; 59 | 60 | and this one? they both sound the same to my ears... 61 | 62 | - **Date**: 2011-07-22 11:07:12 63 | - **By**: moc.nwonknu@nwonknu 64 | 65 | .. code-block:: text 66 | 67 | How can you change the variance (sigma)? 68 | 69 | - **Date**: 2013-06-12 12:30:33 70 | - **By**: moc.enon@lubeb 71 | 72 | .. code-block:: text 73 | 74 | This is NOT a good code to generate Gaussian Noice. Look into: 75 | (random * c2) + (random * c2) + (random * c2) 76 | It is all nonsense! The reason of adding three numbers it the Central Limit Theorem to aproximate Gaussian distribution. But the random numbers inside must differ, which is not the case. The code on original link http://www.musicdsp.org/archive.php?classid=0#129 is correct. 77 | 78 | -------------------------------------------------------------------------------- /source/Synthesis/17-bandlimited-waveform-generation.rst: -------------------------------------------------------------------------------- 1 | Bandlimited waveform generation 2 | =============================== 3 | 4 | - **Author or source:** Joe Wright 5 | - **Type:** waveform generation 6 | - **Created:** 2002-01-17 01:06:49 7 | 8 | - **Linked files:** :download:`bandlimited.cpp <../files/bandlimited.cpp>`. 9 | - **Linked files:** :download:`bandlimited.pdf <../files/bandlimited.pdf>`. 10 | 11 | .. code-block:: text 12 | :caption: notes 13 | 14 | (see linkfile) 15 | 16 | 17 | 18 | Comments 19 | -------- 20 | 21 | - **Date**: 2012-02-10 16:26:11 22 | - **By**: ed.redienhcsslin@psdcisum 23 | 24 | .. code-block:: text 25 | 26 | The code to reduce the gibbs effect causes aliasing if a transition is made from wavetable A with x partials to wavetable B with y partials. 27 | 28 | The aliasing can clearly be seen in a spectral view. 29 | 30 | The problem is, that the volume modification for partial N is different depending on the number of partials the wavetable row contains 31 | 32 | 33 | -------------------------------------------------------------------------------- /source/Synthesis/183-drift-generator.rst: -------------------------------------------------------------------------------- 1 | Drift generator 2 | =============== 3 | 4 | - **Author or source:** ti.oohay@odrasotniuq 5 | - **Type:** Random 6 | - **Created:** 2004-09-23 16:07:34 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | I use this drift to modulate any sound parameter of my synth. 13 | It is very effective if it slightly modulates amplitude or frequency of an FM modulator. 14 | It is based on an incremental random variable, sine-warped. 15 | I like it because it is "continuous" (as opposite to "sample and hold"), and I can set 16 | variation rate and max variation. 17 | It can go to upper or lower constraint (+/- max drift) but it gradually decreases rate of 18 | variation when approaching to the limit. 19 | I use it exactly as an LFO (-1.f .. +1.f) 20 | I use a table for sin instead of sin() function because this way I can change random 21 | distribution, by selecting a different curve (different table) from sine... 22 | 23 | I hope that it is clear ... (sigh... :-) 24 | Bye!!! 25 | P.S. Thank you for help in previous submission ;-) 26 | 27 | 28 | .. code-block:: c++ 29 | :linenos: 30 | :caption: code 31 | 32 | const int kSamples //Number of samples in fSinTable below 33 | float fSinTable[kSamples] // Tabulated sin() [0 - 2pi[ amplitude [-1.f .. 1.f] 34 | float fWhere// Index 35 | float fRate // Max rate of variation 36 | float fLimit //max or min value 37 | float fDrift // Output 38 | 39 | //I assume that random() is a number from 0.f to 1.f, otherwise scale it 40 | 41 | fWhere += fRate * random() 42 | //I update this drift in a long-term cycle, so I don't care of branches 43 | if (fWhere >= 1.f) fWhere -= 1.f 44 | else if (fWhere < 0.f) sWhere += 1.f 45 | 46 | fDrift = fLimit * fSinTable[(long) (fWhere * kSamples)] 47 | 48 | 49 | Comments 50 | -------- 51 | 52 | - **Date**: 2004-09-24 17:37:38 53 | - **By**: ti.oohay@odrasotniuq 54 | 55 | .. code-block:: text 56 | 57 | ...sorry... 58 | random() must be in [-1..+1] !!! 59 | 60 | -------------------------------------------------------------------------------- /source/Synthesis/184-rossler-and-lorenz-oscillators.rst: -------------------------------------------------------------------------------- 1 | Rossler and Lorenz Oscillators 2 | ============================== 3 | 4 | - **Author or source:** moc.noicratse@ajelak 5 | - **Type:** Chaotic LFO 6 | - **Created:** 2004-10-10 00:13:58 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | The Rossler and Lorenz functions are iterated chaotic systems - they trace smooth curves 13 | that never repeat the same way twice. Lorenz is "unpitched", having no distinct peaks in 14 | its spectrum -- similar to pink noise. Rossler exhibits definite spectral peaks against a 15 | noisy broadband background. 16 | 17 | Time-domain and frequency spectrum of these two functions, as well as other info, can be 18 | found at: 19 | 20 | http://www.physics.emory.edu/~weeks/research/tseries1.html 21 | 22 | These functions might be useful in simulating "analog drift." 23 | 24 | 25 | 26 | 27 | 28 | 29 | .. code-block:: c++ 30 | :linenos: 31 | :caption: code 32 | 33 | Available on the web at: 34 | http://www.tinygod.com/code/BLorenzOsc.zip 35 | 36 | 37 | Comments 38 | -------- 39 | 40 | - **Date**: 2005-01-10 09:11:12 41 | - **By**: moc.yddaht@yddaht 42 | 43 | .. code-block:: text 44 | 45 | A Delphi/pascal version for VCL, KOL, Kylix and Freepascal on my website: 46 | http://members.chello.nl/t.koning8/loro_sc.pas 47 | 48 | Nice work! 49 | 50 | -------------------------------------------------------------------------------- /source/Synthesis/199-rbj-wavetable-101.rst: -------------------------------------------------------------------------------- 1 | RBJ Wavetable 101 2 | ================= 3 | 4 | - **Author or source:** Robert Bristow-Johnson 5 | - **Created:** 2005-05-04 20:34:05 6 | 7 | - **Linked files:** :download:`Wavetable-101.pdf <../files/Wavetable-101.pdf>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | see linked file 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /source/Synthesis/2-square-waves.rst: -------------------------------------------------------------------------------- 1 | Square Waves 2 | ============ 3 | 4 | - **Author or source:** Sean Costello 5 | - **Type:** waveform generation 6 | - **Created:** 2002-01-15 21:26:38 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | One way to do a square wave: 13 | 14 | You need two buzz generators (see Dodge & Jerse, or the Csound source code, for 15 | implementation details). One of the buzz generators runs at the desired square wave 16 | frequency, while the second buzz generator is exactly one octave above this pitch. 17 | Subtract the higher octave buzz generator's output from the lower buzz generator's output 18 | - the result should be a signal with all odd harmonics, all at equal amplitude. Filter the 19 | resultant signal (maybe integrate it). Voila, a bandlimited square wave! Well, I think it 20 | should work... 21 | 22 | The one question I have with the above technique is whether it produces a waveform that 23 | truly resembles a square wave in the time domain. Even if the number of harmonics, and the 24 | relative ratio of the harmonics, is identical to an "ideal" bandwidth-limited square wave, 25 | it may have an entirely different waveshape. No big deal, unless the signal is processed 26 | by a nonlinearity, in which case the results of the nonlinear processing will be far 27 | different than the processing of a waveform that has a similar shape to a square wave. 28 | 29 | 30 | 31 | Comments 32 | -------- 33 | 34 | - **Date**: 2003-04-01 01:28:28 35 | - **By**: dfl@stanford. edu 36 | 37 | .. code-block:: text 38 | 39 | Actually, I don't think this would work... 40 | The proper way to do it is subtract a phase shifted buzz (aka BLIT) at the same frequency. This is equivalent to comb filtering, which will notch out the even harmonics. 41 | 42 | - **Date**: 2008-11-08 16:24:18 43 | - **By**: moc.psdallahlav@naes 44 | 45 | .. code-block:: text 46 | 47 | The above comment is correct, and my concept is inaccurate. My technique may have produced a signal with the proper harmonic structure, but it has been nearly 10 years since I wrote the post, so I can't remember what I was working with. 48 | 49 | DFL's technique can be implemented with two buzz generators, or with a single buzz generator in conjunction with a fractional delay, where the delay controls the amount of phase shift. 50 | 51 | -------------------------------------------------------------------------------- /source/Synthesis/213-padsynth-synthesys-method.rst: -------------------------------------------------------------------------------- 1 | PADsynth synthesys method 2 | ========================= 3 | 4 | - **Author or source:** moc.oohay@xfbusddanyz 5 | - **Type:** wavetable generation 6 | - **Created:** 2005-11-15 22:29:01 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Please see the full description of the algorithm with public domain c++ code here: 13 | http://zynaddsubfx.sourceforge.net/doc/PADsynth/PADsynth.htm 14 | 15 | 16 | .. code-block:: c++ 17 | :linenos: 18 | :caption: code 19 | 20 | It's here: 21 | http://zynaddsubfx.sourceforge.net/doc/PADsynth/PADsynth.htm 22 | You may copy it (everything is public domain). 23 | Paul 24 | 25 | Comments 26 | -------- 27 | 28 | - **Date**: 2005-11-23 15:49:26 29 | - **By**: moc.yddaht@yddaht 30 | 31 | .. code-block:: text 32 | 33 | Impressed at first hearing! Well documented. 34 | 35 | 36 | - **Date**: 2005-11-25 08:18:58 37 | - **By**: moc.yticliam@qe.n 38 | 39 | .. code-block:: text 40 | 41 | 1. Isn't this plain additive synthesis 42 | 2. Isn't this the algorithm used by the waldorf microwave synths? 43 | 44 | - **Date**: 2005-11-30 09:48:02 45 | - **By**: mok.00hay@em 46 | 47 | .. code-block:: text 48 | 49 | 1. Nope. This is not a plain additive synthesis. It's a special kind :-P Read the doc again :) 50 | 2. No way.. this is NOT even close to waldord microwave synths. Google for this :) 51 | 52 | -------------------------------------------------------------------------------- /source/Synthesis/219-antialiased-square-generator.rst: -------------------------------------------------------------------------------- 1 | Antialiased square generator 2 | ============================ 3 | 4 | - **Author or source:** Paul Sernine 5 | - **Type:** 1st April edition 6 | - **Created:** 2006-04-01 12:46:23 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | It is based on a code by Thierry Rochebois, obfuscated by me. 13 | It generates a 16bit MONO raw pcm file. Have Fun. 14 | 15 | 16 | .. code-block:: c++ 17 | :linenos: 18 | :caption: code 19 | 20 | //sqrfish.cpp 21 | #include 22 | #include 23 | //obfuscation P.Sernine 24 | int main() {float ccc,cccc=0,CC=0,cc=0,CCCC, 25 | CCC,C,c; FILE *CCCCCCC=fopen("sqrfish.pcm", 26 | "wb" ); int ccccc= 0; float CCCCC=6.89e-6f; 27 | for(int CCCCCC=0;CCCCCC<1764000;CCCCCC++ ){ 28 | if(!(CCCCCC%7350)){if(++ccccc>=30){ ccccc =0; 29 | CCCCC*=2;}CCC=1;}ccc=CCCCC*expf(0.057762265f* 30 | "aiakahiafahadfaiakahiahafahadf"[ccccc]);CCCC 31 | =0.75f-1.5f*ccc;cccc+=ccc;CCC*=0.9999f;cccc-= 32 | 2*(cccc>1);C=cccc+CCCC*CC; c=cccc+CCCC*cc; C 33 | -=2*(C>1);c-=2*(c>1);C+=2*(C<-1); c+=1+2 34 | *(c<-1);c-=2*(c>1);C=C*C*(2 *C*C-4); 35 | c=c*c*(2*c*c-4); short cccccc=short(15000.0f* 36 | CCC*(C-c )*CCC);CC=0.5f*(1+C+CC);cc=0.5f*(1+ 37 | c+cc); fwrite(&cccccc,2,1,CCCCCCC);} 38 | //algo by Thierry Rochebois 39 | fclose(CCCCCCC); 40 | return 0000000;} 41 | 42 | 43 | -------------------------------------------------------------------------------- /source/Synthesis/220-trammell-pink-noise-c-class.rst: -------------------------------------------------------------------------------- 1 | Trammell Pink Noise (C++ class) 2 | =============================== 3 | 4 | - **Author or source:** ude.drofnats.amrcc@lfd 5 | - **Type:** pink noise generator 6 | - **Created:** 2006-05-06 08:40:38 7 | 8 | 9 | 10 | .. code-block:: c++ 11 | :linenos: 12 | :caption: code 13 | 14 | #ifndef _PinkNoise_H 15 | #define _PinkNoise_H 16 | 17 | // Technique by Larry "RidgeRat" Trammell 3/2006 18 | // http://home.earthlink.net/~ltrammell/tech/pinkalg.htm 19 | // implementation and optimization by David Lowenfels 20 | 21 | #include 22 | #include 23 | 24 | #define PINK_NOISE_NUM_STAGES 3 25 | 26 | class PinkNoise { 27 | public: 28 | PinkNoise() { 29 | srand ( time(NULL) ); // initialize random generator 30 | clear(); 31 | } 32 | 33 | void clear() { 34 | for( size_t i=0; i< PINK_NOISE_NUM_STAGES; i++ ) 35 | state[ i ] = 0.0; 36 | } 37 | 38 | float tick() { 39 | static const float RMI2 = 2.0 / float(RAND_MAX); // + 1.0; // change for range [0,1) 40 | static const float offset = A[0] + A[1] + A[2]; 41 | 42 | // unrolled loop 43 | float temp = float( rand() ); 44 | state[0] = P[0] * (state[0] - temp) + temp; 45 | temp = float( rand() ); 46 | state[1] = P[1] * (state[1] - temp) + temp; 47 | temp = float( rand() ); 48 | state[2] = P[2] * (state[2] - temp) + temp; 49 | return ( A[0]*state[0] + A[1]*state[1] + A[2]*state[2] )*RMI2 - offset; 50 | } 51 | 52 | protected: 53 | float state[ PINK_NOISE_NUM_STAGES ]; 54 | static const float A[ PINK_NOISE_NUM_STAGES ]; 55 | static const float P[ PINK_NOISE_NUM_STAGES ]; 56 | }; 57 | 58 | const float PinkNoise::A[] = { 0.02109238, 0.07113478, 0.68873558 }; // rescaled by (1+P)/(1-P) 59 | const float PinkNoise::P[] = { 0.3190, 0.7756, 0.9613 }; 60 | 61 | #endif 62 | 63 | 64 | Comments 65 | -------- 66 | 67 | - **Date**: 2007-02-09 06:15:59 68 | - **By**: ten.knilhtrae@6741emmartl 69 | 70 | .. code-block:: text 71 | 72 | Many thanks to David Lowenfels for posting this implementation of the early experimental version. I recommend switching to the new algorithm form described in 'newpink.htm' -- better range to 9+ octaves, better accuracy to +-0.25 dB, and leveled computational loading. So where is MY submission to the archive? Um... well, it's coming... if he doesn't beat me to the punch again and post his code first! -- Larry Trammell (the RidgeRat) 73 | 74 | -------------------------------------------------------------------------------- /source/Synthesis/242-pulsequad.rst: -------------------------------------------------------------------------------- 1 | PulseQuad 2 | ========= 3 | 4 | - **Author or source:** moc.ellehcim-erdna@ma 5 | - **Type:** Waveform 6 | - **Created:** 2007-01-08 10:50:55 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This is written in Actionscript 3.0 (Flash9). You can listen to the example at 13 | http://lab.andre-michelle.com/playing-with-pulse-harmonics 14 | It allows to morph between a sinus like quadratic function and an ordinary pulse width 15 | with adjustable pulse width. Note that the slope while morphing is always zero at the edge 16 | points of the waveform. It is not just distorsion. 17 | 18 | 19 | .. code-block:: c++ 20 | :linenos: 21 | :caption: code 22 | 23 | http://lab.andre-michelle.com/swf/f9/pulsequad/PulseQuad.as 24 | 25 | -------------------------------------------------------------------------------- /source/Synthesis/254-parabolic-shaper.rst: -------------------------------------------------------------------------------- 1 | Parabolic shaper 2 | ================ 3 | 4 | - **Author or source:** rf.eerf@aipotreza 5 | - **Created:** 2008-03-13 10:41:18 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | This function can be used for oscillators or shaper. 12 | it can be driven by a phase accumulator or an audio input. 13 | 14 | 15 | 16 | .. code-block:: c++ 17 | :linenos: 18 | :caption: code 19 | 20 | Function Parashape(inp:single):single; 21 | var fgh,tgh:single; 22 | begin 23 | fgh := inp ; 24 | fgh := 0.25-f_abs(fgh) ; 25 | tgh := fgh ; 26 | tgh := 1-2*f_abs(tgh); 27 | fgh := fgh*8; 28 | result := fgh*tgh ; 29 | end; 30 | // f_abs is the function of ddsputils unit. 31 | 32 | -------------------------------------------------------------------------------- /source/Synthesis/261-fast-sin-approximation-for-usage-in-e-g-additive-synthesizers.rst: -------------------------------------------------------------------------------- 1 | Fast SIN approximation for usage in e.g. additive synthesizers 2 | ============================================================== 3 | 4 | - **Author or source:** neotec 5 | - **Created:** 2008-12-09 11:56:33 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | This code presents 2 'fastsin' functions. fastsin2 is less accurate than fastsin. In fact 12 | it's a simple taylor series, but optimized for integer phase. 13 | 14 | phase is in 0 -> (2^32)-1 range and maps to 0 -> ~2PI 15 | 16 | I get about 55000000 fastsin's per second on my P4,3.2GHz which would give a nice Kawai K5 17 | emulation using 64 harmonics and 8->16 voices. 18 | 19 | 20 | 21 | .. code-block:: c++ 22 | :linenos: 23 | :caption: code 24 | 25 | float fastsin(UINT32 phase) 26 | { 27 | const float frf3 = -1.0f / 6.0f; 28 | const float frf5 = 1.0f / 120.0f; 29 | const float frf7 = -1.0f / 5040.0f; 30 | const float frf9 = 1.0f / 362880.0f; 31 | const float f0pi5 = 1.570796327f; 32 | float x, x2, asin; 33 | UINT32 tmp = 0x3f800000 | (phase >> 7); 34 | if (phase & 0x40000000) 35 | tmp ^= 0x007fffff; 36 | x = (*((float*)&tmp) - 1.0f) * f0pi5; 37 | x2 = x * x; 38 | asin = ((((frf9 * x2 + frf7) * x2 + frf5) * x2 + frf3) * x2 + 1.0f) * x; 39 | return (phase & 0x80000000) ? -asin : asin; 40 | } 41 | 42 | float fastsin2(UINT32 phase) 43 | { 44 | const float frf3 = -1.0f / 6.0f; 45 | const float frf5 = 1.0f / 120.0f; 46 | const float frf7 = -1.0f / 5040.0f; 47 | const float f0pi5 = 1.570796327f; 48 | float x, x2, asin; 49 | UINT32 tmp = 0x3f800000 | (phase >> 7); 50 | if (phase & 0x40000000) 51 | tmp ^= 0x007fffff; 52 | x = (*((float*)&tmp) - 1.0f) * f0pi5; 53 | x2 = x * x; 54 | asin = (((frf7 * x2 + frf5) * x2 + frf3) * x2 + 1.0f) * x; 55 | return (phase & 0x80000000) ? -asin : asin; 56 | } 57 | 58 | 59 | Comments 60 | -------- 61 | 62 | - **Date**: 2008-12-09 12:11:11 63 | - **By**: neotec 64 | 65 | .. code-block:: text 66 | 67 | PS: To use this as an OSC you'll need the following vars/equ's: 68 | 69 | UINT32 phase = 0; 70 | UINT32 step = frequency * powf(2.0f, 32.0f) / samplerate; 71 | 72 | Then it's just: 73 | ... 74 | out = fastsin(phase); 75 | phase += step; 76 | ... 77 | 78 | 79 | - **Date**: 2008-12-14 20:04:10 80 | - **By**: moc.toohay@bob 81 | 82 | .. code-block:: text 83 | 84 | Woah! Seven multiplies, on top of those adds and memory lookup. Is this really all that fast? 85 | 86 | -------------------------------------------------------------------------------- /source/Synthesis/262-simple-time-stretching-granular-synthesizer.rst: -------------------------------------------------------------------------------- 1 | Simple Time Stretching-Granular Synthesizer 2 | =========================================== 3 | 4 | - **Author or source:** Harry-Chris 5 | - **Created:** 2008-12-18 07:08:20 6 | 7 | 8 | .. code-block:: text 9 | :caption: notes 10 | 11 | Matlab function that implements crude time stretching - granulizing function, by overlap 12 | add in time domain. 13 | 14 | 15 | .. code-block:: c++ 16 | :linenos: 17 | :caption: code 18 | 19 | function y = gran_func(x, w, H,H2, Fs, tr_amount) 20 | 21 | 22 | % x -> input signal 23 | % w -> Envelope - Window Vector 24 | % H1 -> Original Hop Size 25 | % H2 -> Synthesis Hop Size 26 | % Fs -> Sample Rate 27 | % str_amount -> time stretching factor 28 | 29 | 30 | M = length(w); 31 | 32 | pin = 1; 33 | pend = length(x) - M; 34 | 35 | 36 | y = zeros(1, floor( str_amount * length(x)) +M); 37 | 38 | 39 | count = 1; 40 | idx = 1; 41 | 42 | while pin < pend 43 | 44 | input = x(pin : pin+M-1) .* w'; 45 | 46 | 47 | y(idx : idx + M - 1) = y(idx : idx + M - 1) + input; 48 | 49 | pin = pin + H; 50 | count = count + 1; 51 | idx = idx + H2; 52 | 53 | end 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /source/Synthesis/271-prng-for-non-uniformly-distributed-values-from-trigonometric-identity.rst: -------------------------------------------------------------------------------- 1 | PRNG for non-uniformly distributed values from trigonometric identity 2 | ===================================================================== 3 | 4 | - **Author or source:** moc.liamg@321tiloen 5 | - **Type:** pseudo-random number generator 6 | - **Created:** 2009-09-02 07:16:14 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | a method, which generates random numbers in the [-1,+1] range, while having a probability 13 | density function with less concentration of values near zero for sin(). 14 | you can use an approximation of sin() and/or experiment with such an equation for 15 | different distributions. using tan() will accordingly invert the pdf graph i.e. more 16 | concentration near zero, but the output range will be also affected. 17 | 18 | extended read on similar methods: 19 | http://www.stat.wisc.edu/~larget/math496/random2.html 20 | 21 | regards 22 | lubomir 23 | 24 | 25 | .. code-block:: c++ 26 | :linenos: 27 | :caption: code 28 | 29 | //init 30 | x=y=1; 31 | 32 | //sampleloop 33 | y=sin((x+=1)*y); 34 | 35 | 36 | -------------------------------------------------------------------------------- /source/Synthesis/59-pseudo-random-generator.rst: -------------------------------------------------------------------------------- 1 | Pseudo-Random generator 2 | ======================= 3 | 4 | - **Author or source:** Hal Chamberlain, "Musical Applications of Microprocessors" (Phil Burk) 5 | - **Type:** Linear Congruential, 32bit 6 | - **Created:** 2002-01-17 03:11:50 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | This can be used to generate random numeric sequences or to synthesise a white noise audio 13 | signal. 14 | If you only use some of the bits, use the most significant bits by shifting right. 15 | Do not just mask off the low bits. 16 | 17 | 18 | .. code-block:: c++ 19 | :linenos: 20 | :caption: code 21 | 22 | /* Calculate pseudo-random 32 bit number based on linear congruential method. */ 23 | unsigned long GenerateRandomNumber( void ) 24 | { 25 | /* Change this for different random sequences. */ 26 | static unsigned long randSeed = 22222; 27 | randSeed = (randSeed * 196314165) + 907633515; 28 | return randSeed; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /source/Synthesis/67-sawsin.rst: -------------------------------------------------------------------------------- 1 | SawSin 2 | ====== 3 | 4 | - **Author or source:** Alexander Kritov 5 | - **Type:** Oscillator shape 6 | - **Created:** 2002-02-10 12:40:59 7 | 8 | 9 | 10 | .. code-block:: c++ 11 | :linenos: 12 | :caption: code 13 | 14 | double sawsin(double x) 15 | { 16 | double t = fmod(x/(2*M_PI),(double)1.0); 17 | if (t>0.5) 18 | return -sin(x); 19 | if (t<=0.5) 20 | return (double)2.0*t-1.0; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /source/Synthesis/69-fast-square-wave-generator.rst: -------------------------------------------------------------------------------- 1 | Fast square wave generator 2 | ========================== 3 | 4 | - **Author or source:** Wolfgang (ed.tfoxen@redienhcsw) 5 | - **Type:** NON-bandlimited osc... 6 | - **Created:** 2002-02-10 12:46:22 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Produces a square wave -1.0f .. +1.0f. 13 | The resulting waveform is NOT band-limited, so it's propably of not much use for syntheis. 14 | It's rather useful for LFOs and the like, though. 15 | 16 | 17 | .. code-block:: c++ 18 | :linenos: 19 | :caption: code 20 | 21 | Idea: use integer overflow to avoid conditional jumps. 22 | 23 | // init: 24 | typedef unsigned long ui32; 25 | 26 | float sampleRate = 44100.0f; // whatever 27 | float freq = 440.0f; // 440 Hz 28 | float one = 1.0f; 29 | ui32 intOver = 0L; 30 | ui32 intIncr = (ui32)(4294967296.0 / hostSampleRate / freq)); 31 | 32 | // loop: 33 | (*((ui32 *)&one)) &= 0x7FFFFFFF; // mask out sign bit 34 | (*((ui32 *)&one)) |= (intOver & 0x80000000); 35 | intOver += intIncr; 36 | 37 | Comments 38 | -------- 39 | 40 | - **Date**: 2003-08-03 01:35:08 41 | - **By**: moc.jecnal@psdcisum 42 | 43 | .. code-block:: text 44 | 45 | So, how would I get the output into a float variable like square_out, for instance? 46 | 47 | - **Date**: 2009-04-12 15:33:37 48 | - **By**: moc.liamtoh@18_ogag_leafar 49 | 50 | .. code-block:: text 51 | 52 | In response to lancej, yo can declare a union with a float and a int and operate the floatas as here using the int part of the union. 53 | 54 | If I remeber correctly the value for -1.f = 0xBF800000 and the value for 1.f = 0x3F800000, note the 0x80000000 difference between them that is the sign. 55 | 56 | -------------------------------------------------------------------------------- /source/Synthesis/75-bandlimited-waveforms-synopsis.rst: -------------------------------------------------------------------------------- 1 | Bandlimited waveforms synopsis. 2 | =============================== 3 | 4 | - **Author or source:** Joe Wright 5 | - **Created:** 2002-02-11 17:37:20 6 | 7 | - **Linked files:** :download:`waveforms.txt <../files/waveforms.txt>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | (see linkfile) 13 | 14 | 15 | 16 | Comments 17 | -------- 18 | 19 | - **Date**: 2005-11-15 20:07:11 20 | - **By**: dflatccrmadotstanforddotedu 21 | 22 | .. code-block:: text 23 | 24 | The abs(sin) method from the Lane CMJ paper is not bandlimited! It's basically just a crappy method for BLIT. 25 | 26 | You forgot to mention Eli Brandt's minBLEP method. It's the best! You just have to know how to properly generate a nice minblep table... (slightly dilated, see Stilson and Smith BLIT paper, at the end regarding table implementation issues) 27 | 28 | -------------------------------------------------------------------------------- /source/Synthesis/8-pulsewidth-modulation.rst: -------------------------------------------------------------------------------- 1 | Pulsewidth modulation 2 | ===================== 3 | 4 | - **Author or source:** Steffan Diedrichsen 5 | - **Type:** waveform generation 6 | - **Created:** 2002-01-15 21:29:52 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Take an upramping sawtooth and its inverse, a downramping sawtooth. Adding these two waves 13 | with a well defined delay between 0 and period (1/f) 14 | results in a square wave with a duty cycle ranging from 0 to 100%. 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /source/Synthesis/80-wavetable-synthesis.rst: -------------------------------------------------------------------------------- 1 | Wavetable Synthesis 2 | =================== 3 | 4 | - **Author or source:** Robert Bristow-Johnson 5 | - **Created:** 2002-05-07 18:46:18 6 | 7 | - **Linked files:** :download:`http://www.harmony-central.com/Synth/Articles/Wavetable_101/Wavetable-101.pdf <../files/http://www.harmony-central.com/Synth/Articles/Wavetable_101/Wavetable-101.pdf>`. 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | Wavetable sythesis AES paper by RBJ. 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /source/Synthesis/9-fast-sine-wave-calculation.rst: -------------------------------------------------------------------------------- 1 | Fast sine wave calculation 2 | ========================== 3 | 4 | - **Author or source:** James McCartney in Computer Music Journal, also the Julius O. Smith paper 5 | - **Type:** waveform generation 6 | - **Created:** 2002-01-17 00:52:33 7 | 8 | 9 | .. code-block:: text 10 | :caption: notes 11 | 12 | (posted by Niels Gorisse) 13 | If you change the frequency, the amplitude rises (pitch lower) or lowers (pitch rise) a 14 | LOT I fixed the first problem by thinking about what actually goes wrong. The answer was 15 | to recalculate the phase for that frequency and the last value, and then continue 16 | normally. 17 | 18 | 19 | .. code-block:: c++ 20 | :linenos: 21 | :caption: code 22 | 23 | Variables: 24 | ip = phase of the first output sample in radians 25 | w = freq*pi / samplerate 26 | b1 = 2.0 * cos(w) 27 | 28 | Init: 29 | y1=sin(ip-w) 30 | y2=sin(ip-2*w) 31 | 32 | Loop: 33 | y0 = b1*y1 - y2 34 | y2 = y1 35 | y1 = y0 36 | 37 | output is in y0 (y0 = sin(ip + n*freq*pi / samplerate), n= 0, 1, 2, ... I *think*) 38 | 39 | Later note by James McCartney: 40 | if you unroll such a loop by 3 you can even eliminate the assigns!! 41 | 42 | y0 = b1*y1 - y2 43 | y2 = b1*y0 - y1 44 | y1 = b1*y2 - y0 45 | 46 | Comments 47 | -------- 48 | 49 | - **Date**: 2003-04-22 15:05:21 50 | - **By**: moc.liamtoh@trahniak 51 | 52 | .. code-block:: text 53 | 54 | try using this to make sine waves with frequency less that 1. I did and it gives very rough half triangle-like waves. Is there any way to fix this? I want to use a sine generated for LFO so I need one that works for low frequencies. 55 | 56 | - **Date**: 2006-10-24 22:34:59 57 | - **By**: moc.oi@htnysa 58 | 59 | .. code-block:: text 60 | 61 | looks like the formula has gotten munged. 62 | w = freq * twopi / samplerate 63 | 64 | 65 | -------------------------------------------------------------------------------- /source/Synthesis/90-bandlimited-sawtooth-synthesis.rst: -------------------------------------------------------------------------------- 1 | Bandlimited sawtooth synthesis 2 | ============================== 3 | 4 | - **Author or source:** moc.ailet@mlohednal.leuname 5 | - **Type:** DSF BLIT 6 | - **Created:** 2002-03-29 18:06:44 7 | 8 | - **Linked files:** :download:`synthesis002.txt <../files/synthesis002.txt>`. 9 | 10 | .. code-block:: text 11 | :caption: notes 12 | 13 | This is working code for synthesizing a bandlimited sawtooth waveform. The algorithm is 14 | DSF BLIT + leaky integrator. Includes driver code. 15 | 16 | There are two parameters you may tweak: 17 | 18 | 1) Desired attenuation at nyquist. A low value yields a duller sawtooth but gets rid of 19 | those annoying CLICKS when sweeping the frequency up real high. Must be strictly less than 20 | 1.0! 21 | 22 | 2) Integrator leakiness/cut off. Affects the shape of the waveform to some extent, esp. at 23 | the low end. Ideally you would want to set this low, but too low a setting will give you 24 | problems with DC. 25 | 26 | Have fun! 27 | /Emanuel Landeholm 28 | 29 | (see linked file) 30 | 31 | 32 | 33 | Comments 34 | -------- 35 | 36 | - **Date**: 2003-02-26 00:58:41 37 | - **By**: moc.liamtoh@hsats_wobniar 38 | 39 | .. code-block:: text 40 | 41 | 42 | there is no need to use a butterworth design for a simple leaky integrator, in this case actually the 43 | variable curcps can be used directly in a simple: leak += curcps * (blit - leak); 44 | 45 | this produces a nearly perfect saw shape in almost all cases 46 | 47 | - **Date**: 2011-05-31 05:25:01 48 | - **By**: pj.oc.liamtoh@evawtuah 49 | 50 | .. code-block:: text 51 | 52 | The square wave type will be able to be generated from this source. 53 | Please teach if it is possible. 54 | 55 | -------------------------------------------------------------------------------- /source/Synthesis/index.rst: -------------------------------------------------------------------------------- 1 | Synthesis 2 | ========= 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :caption: Contents: 7 | 8 | 16-allmost-ready-to-use-oscillators 9 | 224-am-formantic-synthesis 10 | 1-alias-free-waveform-generation-with-analog-filtering 11 | 152-another-lfo-class 12 | 167-another-cheap-sinusoidal-lfo 13 | 219-antialiased-square-generator 14 | 134-arbitary-shaped-band-limited-waveform-generation-using-oversampling-and-low-pass-filtering 15 | 123-audiable-alias-free-waveform-gen-using-width-sine 16 | 268-band-limited-waveforms-my-way 17 | 90-bandlimited-sawtooth-synthesis 18 | 17-bandlimited-waveform-generation 19 | 75-bandlimited-waveforms-synopsis 20 | 12-bandlimited-waveforms 21 | 227-butterworth 22 | 239-c-oscilator-class 23 | 168-c-gaussian-noise-generation 24 | 187-chebyshev-waveshaper-using-their-recursive-definition 25 | 15-cubic-polynomial-envelopes 26 | 140-dsf-super-set-of-blit 27 | 244-direct-pink-noise-synthesis-with-auto-correlated-generator 28 | 68-discrete-summation-formula-dsf 29 | 183-drift-generator 30 | 217-easy-noise-generation 31 | 189-fast-exponential-envelope-generator 32 | 151-fast-lfo-in-delphi 33 | 261-fast-sin-approximation-for-usage-in-e-g-additive-synthesizers 34 | 216-fast-whitenoise-generator 35 | 10-fast-sine-and-cosine-calculation 36 | 9-fast-sine-wave-calculation 37 | 69-fast-square-wave-generator 38 | 113-gaussian-white-noise 39 | 109-gaussian-white-noise 40 | 215-generator 41 | 14-inverted-parabolic-envelope 42 | 211-matlab-octave-code-for-minblep-table-generation 43 | 213-padsynth-synthesys-method 44 | 271-prng-for-non-uniformly-distributed-values-from-trigonometric-identity 45 | 254-parabolic-shaper 46 | 111-phase-modulation-vs-frequency-modulation 47 | 160-phase-modulation-vs-frequency-modulation-ii 48 | 59-pseudo-random-generator 49 | 242-pulsequad 50 | 8-pulsewidth-modulation 51 | 241-quick-dirty-sine 52 | 161-quick-and-dirty-sine-generator 53 | 199-rbj-wavetable-101 54 | 272-randja-compressor 55 | 184-rossler-and-lorenz-oscillators 56 | 67-sawsin 57 | 262-simple-time-stretching-granular-synthesizer 58 | 13-sine-calculation 59 | 269-smooth-random-lfo-generator 60 | 2-square-waves 61 | 220-trammell-pink-noise-c-class 62 | 112-waveform-generator-using-minbleps 63 | 80-wavetable-synthesis 64 | 11-weird-synthesis 65 | -------------------------------------------------------------------------------- /source/files/56kmidi.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/56kmidi.gif -------------------------------------------------------------------------------- /source/files/BandLimit.h: -------------------------------------------------------------------------------- 1 | class CAllPassFilter 2 | { 3 | public: 4 | 5 | CAllPassFilter(const double coefficient); 6 | ~CAllPassFilter(); 7 | double process(double input); 8 | 9 | private: 10 | double a; 11 | 12 | double x0; 13 | double x1; 14 | double x2; 15 | 16 | double y0; 17 | double y1; 18 | double y2; 19 | }; 20 | 21 | 22 | class CAllPassFilterCascade 23 | { 24 | public: 25 | CAllPassFilterCascade(const double* coefficients, int N); 26 | ~CAllPassFilterCascade(); 27 | 28 | double process(double input); 29 | 30 | private: 31 | CAllPassFilter** allpassfilter; 32 | int numfilters; 33 | }; 34 | 35 | 36 | class CHalfBandFilter 37 | { 38 | public: 39 | CHalfBandFilter(const int order, const bool steep); 40 | ~CHalfBandFilter(); 41 | 42 | double process(const double input); 43 | 44 | private: 45 | CAllPassFilterCascade* filter_a; 46 | CAllPassFilterCascade* filter_b; 47 | double oldout; 48 | }; 49 | -------------------------------------------------------------------------------- /source/files/Disassemble56k.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/Disassemble56k.zip -------------------------------------------------------------------------------- /source/files/EQ-Coefficients.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/EQ-Coefficients.pdf -------------------------------------------------------------------------------- /source/files/FFTReal.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/FFTReal.zip -------------------------------------------------------------------------------- /source/files/FIJI.ZIP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/FIJI.ZIP -------------------------------------------------------------------------------- /source/files/LFO.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/LFO.zip -------------------------------------------------------------------------------- /source/files/LFOGenerator.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/LFOGenerator.zip -------------------------------------------------------------------------------- /source/files/LockFreeFifo.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | using std::exception; 6 | 7 | template class LockFreeFifo 8 | { 9 | public: 10 | LockFreeFifo (unsigned bufsz) : readidx(0), writeidx(0), buffer(bufsz) 11 | {} 12 | 13 | T get (void) 14 | { 15 | if (readidx == writeidx) 16 | throw runtime_error ("underrun"); 17 | 18 | T result = buffer[readidx]; 19 | 20 | if ((readidx + 1) >= buffer.size()) 21 | readidx = 0; 22 | else 23 | readidx = readidx + 1; 24 | 25 | return result; 26 | } 27 | 28 | void put (T datum) 29 | { 30 | unsigned newidx; 31 | 32 | if ((writeidx + 1) >= buffer.size()) 33 | newidx = 0; 34 | else 35 | newidx = writeidx + 1; 36 | 37 | if (newidx == readidx) 38 | throw runtime_error ("overrun"); 39 | 40 | buffer[writeidx] = datum; 41 | 42 | writeidx = newidx; 43 | } 44 | 45 | private: 46 | 47 | volatile unsigned readidx, writeidx; 48 | vector buffer; 49 | }; -------------------------------------------------------------------------------- /source/files/MATLABReverb.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/MATLABReverb.zip -------------------------------------------------------------------------------- /source/files/MFX2181.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/MFX2181.zip -------------------------------------------------------------------------------- /source/files/MadShifta.sit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/MadShifta.sit -------------------------------------------------------------------------------- /source/files/MadShifta.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/MadShifta.zip -------------------------------------------------------------------------------- /source/files/MinBLEPS.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/MinBLEPS.zip -------------------------------------------------------------------------------- /source/files/VowelSynth.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/VowelSynth.zip -------------------------------------------------------------------------------- /source/files/Wavetable-101.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/Wavetable-101.pdf -------------------------------------------------------------------------------- /source/files/Wavetable.sit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/Wavetable.sit -------------------------------------------------------------------------------- /source/files/bandlimited.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/bandlimited.pdf -------------------------------------------------------------------------------- /source/files/denormal.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/denormal.pdf -------------------------------------------------------------------------------- /source/files/filter001.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/filter001.gif -------------------------------------------------------------------------------- /source/files/gigxpand.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/gigxpand.zip -------------------------------------------------------------------------------- /source/files/index.php: -------------------------------------------------------------------------------- 1 | $file"; 8 | } 9 | } 10 | closedir($handle); 11 | ?> -------------------------------------------------------------------------------- /source/files/laurent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/laurent.gif -------------------------------------------------------------------------------- /source/files/lpf18.sme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/lpf18.sme -------------------------------------------------------------------------------- /source/files/lpf18.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/lpf18.zip -------------------------------------------------------------------------------- /source/files/midinative.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/midinative.zip -------------------------------------------------------------------------------- /source/files/mmflash.txt: -------------------------------------------------------------------------------- 1 | I think I can help you. I have had the same problem, but now I can write 2 | into a FLASH-EEPROM. 3 | Use the file FLASH.asm (Inventory of your Motorola DSP56002EVM 4 | Software). 5 | In the version I use, I find a great mistake !!! 6 | The first rep-command must be rep #6 and not rep#5 (because 64=2^6 and 7 | not 2^5=32). 8 | I wrote a dokumantation about the FLASH-EEprom-Programming, but in 9 | German-Language. I try to explain it: 10 | Use Atmel 29c256 Flash-EEPROM - it works !!! 11 | Assemble your corrected Flash.asm file (asm56000 Flash.asm). 12 | You have created the Flash.cld file. 13 | Start the debugger EVM56k.exe (PC!!!) 14 | Load your usercode (for example echo.cld) into the debugger 15 | - Remember the complete usercode must be in P-memory - 16 | Find out the last address of your usercode in P-memory (look on the 17 | assembly-window). A special trick: Last address to use can be 153F hex ! 18 | Load the Flash.cld into the debugger. Flash.cld is behind your usercode 19 | at address 7f00 in P-memory - no conflicts! 20 | Write the last address of your usercode into the R1-Register. 21 | Command-window: CHANGE R1 153F 22 | Start the EEPRM-Writing-Programm Flash.cld in the debugger: 23 | Command-window: GO 7f00 24 | Now the BOOTSTRAP-COMMAND and your USERCODE will be written in the 25 | FLASH-EEPROM. Wait till the Debugger stops - Debug mode! 26 | Press the reset-button on the EVM-Board. It will boot and start your 27 | userprogramm. 28 | Ready !!! NO hardware changes nessessary 29 | EVM - stand alone 30 | Please tell me, if you are successfull!! 31 | 32 | Markus Maier, University of Applied Siences Braunschweig/Wolfenbuettel 33 | DSP-Labor - Nachrichtentechnik -------------------------------------------------------------------------------- /source/files/nsdither.txt: -------------------------------------------------------------------------------- 1 | Noise shaped dither (March 2000) 2 | ------------------- 3 | 4 | This is a simple implementation of highpass triangular-PDF dither with 5 | 2nd-order noise shaping, for use when truncating floating point audio 6 | data to fixed point. 7 | 8 | The noise shaping lowers the noise floor by 11dB below 5kHz (@ 44100Hz 9 | sample rate) compared to triangular-PDF dither. The code below assumes 10 | input data is in the range +1 to -1 and doesn't check for overloads! 11 | 12 | To save time when generating dither for multiple channels you can do 13 | things like this: r3=(r1 & 0x7F)<<8; instead of calling rand() again. 14 | 15 | 16 | 17 | int r1, r2; //rectangular-PDF random numbers 18 | float s1, s2; //error feedback buffers 19 | float s = 0.5f; //set to 0.0f for no noise shaping 20 | float w = pow(2.0,bits-1); //word length (usually bits=16) 21 | float wi= 1.0f/w; 22 | float d = wi / RAND_MAX; //dither amplitude (2 lsb) 23 | float o = wi * 0.5f; //remove dc offset 24 | float in, tmp; 25 | int out; 26 | 27 | 28 | //for each sample... 29 | 30 | r2=r1; //can make HP-TRI dither by 31 | r1=rand(); //subtracting previous rand() 32 | 33 | in += s * (s1 + s1 - s2); //error feedback 34 | tmp = in + o + d * (float)(r1 - r2); //dc offset and dither 35 | 36 | out = (int)(w * tmp); //truncate downwards 37 | if(tmp<0.0f) out--; //this is faster than floor() 38 | 39 | s2 = s1; 40 | s1 = in - wi * (float)out; //error 41 | 42 | 43 | 44 | -- 45 | paul.kellett@maxim.abel.co.uk 46 | http://www.maxim.abel.co.uk 47 | -------------------------------------------------------------------------------- /source/files/other001.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/other001.gif -------------------------------------------------------------------------------- /source/files/other001.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/other001.zip -------------------------------------------------------------------------------- /source/files/pdc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/pdc.pdf -------------------------------------------------------------------------------- /source/files/pink.txt: -------------------------------------------------------------------------------- 1 | Filter to make pink noise from white (updated March 2000) 2 | ------------------------------------ 3 | 4 | This is an approximation to a -10dB/decade filter using a weighted sum 5 | of first order filters. It is accurate to within +/-0.05dB above 9.2Hz 6 | (44100Hz sampling rate). Unity gain is at Nyquist, but can be adjusted 7 | by scaling the numbers at the end of each line. 8 | 9 | If 'white' consists of uniform random numbers, such as those generated 10 | by the rand() function, 'pink' will have an almost gaussian level 11 | distribution. 12 | 13 | 14 | b0 = 0.99886 * b0 + white * 0.0555179; 15 | b1 = 0.99332 * b1 + white * 0.0750759; 16 | b2 = 0.96900 * b2 + white * 0.1538520; 17 | b3 = 0.86650 * b3 + white * 0.3104856; 18 | b4 = 0.55000 * b4 + white * 0.5329522; 19 | b5 = -0.7616 * b5 - white * 0.0168980; 20 | pink = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362; 21 | b6 = white * 0.115926; 22 | 23 | 24 | An 'economy' version with accuracy of +/-0.5dB is also available. 25 | 26 | b0 = 0.99765 * b0 + white * 0.0990460; 27 | b1 = 0.96300 * b1 + white * 0.2965164; 28 | b2 = 0.57000 * b2 + white * 1.0526913; 29 | pink = b0 + b1 + b2 + white * 0.1848; 30 | 31 | 32 | 33 | --- 34 | paul.kellett@maxim.abel.co.uk 35 | http://www.abel.co.uk/~maxim/ 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /source/files/qft.tar_1.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/qft.tar_1.gz -------------------------------------------------------------------------------- /source/files/rbj_eq.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/rbj_eq.xls -------------------------------------------------------------------------------- /source/files/simpleSource.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/simpleSource.zip -------------------------------------------------------------------------------- /source/files/sincos.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/sincos.zip -------------------------------------------------------------------------------- /source/files/wavetabl.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdejong/musicdsp/43f156280273010e0fd45b4003dc8a6d9c5dfce6/source/files/wavetabl.zip -------------------------------------------------------------------------------- /source/index.rst: -------------------------------------------------------------------------------- 1 | Musicdsp.org 2 | ============ 3 | 4 | Welcome to musicdsp.org. 5 | 6 | Musicdsp.org is a collection of algorithms, thoughts and snippets, gathered for the music dsp community. Most of this data was gathered by and for the people of the splendid Music-DSP mailing list at http://sites.music.columbia.edu/cmc/music-dsp/ 7 | 8 | .. important:: 9 | Please help us edit these pages at https://github.com/bdejong/musicdsp 10 | 11 | - Special thanks: http://www.fxpansion.com for sponsoring a server to host the archive for many, many years 12 | - Special thanks: http://www.dspdimension.com for pointing http://www.musicdsp.com to this site too 13 | 14 | .. toctree:: 15 | :maxdepth: 1 16 | :caption: Contents: 17 | 18 | Synthesis/index 19 | Analysis/index 20 | Filters/index 21 | Effects/index 22 | Other/index 23 | 24 | Indices and tables 25 | ================== 26 | 27 | * :ref:`genindex` 28 | * :ref:`search` 29 | --------------------------------------------------------------------------------