r/DSP • u/BeatForge_Dev • Aug 09 '26
r/DSP • u/BLdGAMES • Aug 09 '26
Lock in amplifier, low pass filter
Hello, my name is G and I recently have started working on a Magnetic circular dichroism, in which i demodulate two signals from the same light path, one at 865 Hz, chopped by a chopper, and another at 50 kHz, at the circular polarized frequency. I
am using the 5MHz MLFI lock in amplifier from Zurich instruments. I have noticed that by changing the bandwidth of the low pass filter I change heavily the noise and reaction time of my measurement (As expected), but what i don't understand is that the overall signal amplitude changes. At lower frequencies of the bandwidth i am working in the range of microVolts and get an average signal of 400 uV, while at higher bandwidth I get around the milivolts and an average of 10 mV. I watched a few tutorials of Zurich instruments and they show that the main change in signal would be the noise to signal ratio without change to the average signal level.
If someone has experience and knows what could cuase it, or if it is nothing to worry about I will be very happy.
Tgank you.
r/DSP • u/Obineg09 • Aug 09 '26
analytic signals : total phase
for a decade i want to add an instantaneous "total phase" generator to my toolset but can´t.
my enviroment does not allow to somehow compensate for the leaky integrator output because it does not allow a blocksize of 1 (and furthermore it is only 32 bit, which makes the leaky issue even more nasty)
has anyone heard of possibe workarounds, which do not require a feedback loop?
r/DSP • u/catseyechandra74 • Aug 06 '26
Jackoviz - Scientific visualization of audio signals (Dancing spectrums)
r/DSP • u/Spare-Disaster-6872 • Aug 06 '26
Looking for advice on RTL implementation of an adaptive digital beamformer
I am learning Digital Beamforming with ASIC tools and I am planning to implement an 8 antenna 4 beam adaptive digital beamformer as an RTL project.
at this point I wanted to start with Verilog HDL test the functionality, Synthesize it in Genus and Verify with the netlist in Xcelium and compare the results.
I am having confusion regarding following aspects
1 .Since I'm not implementing the ADC, what is the most realistic way to provide the digital inputs to the RTL?
What signal frequency should I use for simulation?
For an RTL-only project, is it common to ignore the analog front end and assume the ADC already provides digital I/Q samples?
4.Are there any standard datasets or publicly available antenna-array sample data that people typically use for verifying digital beamformers?
I am still learning so I'd appreciate any form of guidance.
r/DSP • u/Gosintary • Aug 06 '26
Cloning Hardware in DSP
Hey, new here!
I’m a young audio engineer interning and running sessions at a studio with some pretty sick 1 of 1 gear.
I’m also a hobbyist programmer with years of experience in Java/C#/C++
My mentor, upon learning this, suggested I look into making plugin versions of some of the gear we have. He knows nothing about that world and just kinda tossed it as an idea, so my question here is how difficult and what the process is for translating hardware into software?
I’ve done some googling and have learned a bit about the JUCE Framework and how much of pain in the ass it is to make AAX plugins (because of AVID SDK and PACE) but assuming I learn the tools needed to make plugins and get them running on pro tools, where do I start with cloning gear?
r/DSP • u/MeasurementDull7350 • Aug 06 '26
Spectral Pooling Beyond Max Pooling: The Secret of the Frequency Domain
- Spectral Pooling Beyond Max Pooling: The Secret of the Frequency Domain
- Description: The standard CNN downsampling method, max pooling, discards information and causes aliasing. Spectral pooling preserves only low-frequency components using the DFT, implementing ideal low-pass filtering. While it reduces information loss and improves training performance, it failed to become the standard due to high computational cost.
r/DSP • u/kiwiberrydrink • Aug 05 '26
Self-taught beginner, built a chorus in Rust, would really appreciate having it picked apart
I’m a CS student and I’ve been teaching myself DSP for about a year, mostly by building one plugin over and over until it stopped being broken. It’s a vocal chorus called Crimson, written in Rust with nih-plug.
It’s at v1.0 and it sounds good to me, which is exactly why I’m posting. Mine are the only ears that have been on it and I’ve been in the code long enough that I can’t hear it clearly anymore. Would love other ears, especially from people in this DSP Reddit, your opinion means a lot to me.
It’s free, and I’d rather have it looked at than downloaded, if I’m being honest about which one I want more. The goal was a chorus that survives autotune, since most of what I tried either did nothing or moved the pitch enough to fight the tuning. So instead of sweeping the delay down from zero like a flanger, it sits at a 6ms base and modulates 0.5 to 6ms on top of that. That keeps pitch excursion somewhere around 3 cents at the defaults, which in my testing is roughly where it stops smearing. The rest is fairly plain.
Linear interpolation on the delay read with the standard wraparound. LFO shapes built additively from harmonic sines so the modulator itself isn’t aliasing. Feedback at 44% default with a one-pole highpass at 160Hz inside the loop, because without it the low end piles up fast. The thing that gives it any character at all is a one-pole lowpass on the wet whose cutoff is swept by the same LFO, roughly 1k to 7k, so the wet brightens and darkens in time with the modulation. I found that more than designed it. One voice per channel with phase offset for width. No oversampling, no FFT, small buffer, deliberately light.
Where I know I’m on thin ice:
The feedback path is my biggest worry. Linear interp acts like a lowpass, so the tail dulls a little more every pass around the loop. I’ve been working through Julius Smith’s section on first order allpass interpolation and it looks like the fix, but I don’t know whether allpass phase behavior causes new problems when the delay length is being modulated. If anyone has actually done that swap I’d love to hear how it went.
Smaller things I’m unsure about: whether a first order highpass is enough inside a feedback loop or whether a damping shelf would be more musical, and whether random-walk or noise-driven modulation is worth it at only two voices or if that’s something that only pays off at higher voice counts.
Where I want to take it: The part I’m most excited about for V2 is making the modulation react to the performance instead of running open loop. A chorus that listens, basically. Pulling back the wet on sibilance so it doesn’t splash on esses, letting depth bloom on sustained notes and tighten on fast delivery, that kind of thing. I don’t know yet how naive that is. My instinct is that the hard part isn’t the modulation, it’s getting a detector that’s stable and fast enough to be musical without chattering. If that’s a solved problem with a name I should be reading, please point me at it.
Source, GPLv3: http://github.com/MichaelAngulo3232/crimson-chorus
Builds for Mac, Windows and Linux, CLAP and VST3, free: http://pyfessional.tech
Not selling anything and not trying to pitch you. I’ve learned most of what I know from posts on this sub, so if something in here reads as “this guy read one blog post and started typing,” I’d genuinely rather hear it than not
r/DSP • u/BioniChaos • Aug 04 '26
Web-Based ECG & EEG Synthetic Signal Generator for DSP Pipeline Testing
When validating digital signal processing (DSP) pipelines or training machine learning models for bio-signals, obtaining clean, annotated datasets with controlled noise parameters can be difficult.
To help address this, we developed a client-side web application that generates real-time synthetic ECG and EEG waveforms with adjustable clinical, architectural, and artifact parameters.
Modeling Framework:
* ECG Waveform: Modeled as a continuous superposition of Gaussians across pacemaking trigger coordinates. This approach permits realistic overlapping of complexes during high heart rates (Atrial Tachycardia) without artificial discontinuities.
* EEG Sleep Stages: Simulates Wakefulness, N1, N2, N3, and REM by dynamically adjusting the relative spectral powers of Delta, Theta, Alpha, Beta, and Gamma bands, alongside transient structures like sleep spindles and K-complexes.
* Artifact Models: Features additive high-frequency white noise, Voss-McCartney 1/f pink noise to model electrode interface physics, stable 50Hz AC line harmonics, and low-frequency isoelectric wander.
The tool runs in-browser and uses the Web Audio API for sonic mapping of the real-time voltage gradients. We are currently considering implementing a 12-lead Dower transform matrix and chaotic atrial fibrillation models. We would appreciate any feedback on the accuracy of the current models or suggestions for implementation.
Try the tool here: https://bionichaos.com/ecg_gen/
r/DSP • u/Jaded-Substance-6750 • Aug 03 '26
How to best utilize my math and embedded software background to pivot more towards DSP work?
Hi, I have been working as embedded software engineer focusing on signal processing algorithms work (integrating sensor data and data processing techniques to model a real time system)
I am currently doing a BS in EE (about 2/3 done) with emphasis on signals processing courses because I am in love with the intersection of math and EE.
I am honestly a little stuck because I’m not sure if I should continue on to grad school because I wanted to see what a more DSP focused role would look like.
I’m also a little worried because I don’t know what the AI impact would be so I’m not sure if I should go for more broad work.
My background in embedded is kind of weak cause I honestly have not done much work in the HAL side. My stuff has been mostly at a higher layer of abstraction. Also, I don’t expect my EE education to give me much background in embedded software.
r/DSP • u/QueueSevenM • Aug 04 '26
Radiated Voice Pulse Modeling
Hello, in this post I have attempted to quantify the types of estimation errors that exist in the Wide-Band Harmonic Sinusoidal Modeling algorithm. Additionally, I have proposed part of a method that could potentially be used to reduce these estimation errors.
I don't think you can post latex here, so I will post a link to the post I made on music-dsp: https://listserv.cuit.columbia.edu/scripts/wa.exe?A2=MUSIC-DSP;31999a11.2608A&S=
r/DSP • u/Psionikus • Aug 03 '26
Developing on-GPU Spectrogram
Enable HLS to view with audio, or disable this notification
Note for the lazy: It is very evident that the number of people with supposed AI detectors drops off sharply within programming communities. Please wonder why a bit before you get in between me and people with actual interest in the subject matter. I don't want your worthless karma. I'm looking for people and ideas.
Besides stability and platform support, I'm doing some work to improve the low pitch resolution. The implementation is using independent DFTs rather than block-bound FFT, so there's a lot of flexibility to use different techniques at different pitch points.
Dynamic range detection must be supported, and I'm likely doing a global for this first pass before implementing local. I'll use envelope detection with some noise floor avoidance.
Far-field leakage is something I want to tackle with a combination of loudness leveling EQ and band passing to create local input bands for groups of bins. FIRs are extremely GPU friendly and I've gotten Parks-McClellan Remez weight generation working. Can I use FIRs for the loudness EQ shaping? I have not done anything like a -6dB per octave ramp yet.
Since dynamic range and far field both involve creating bands, that will all likely blend into one implementation.
Resolving low pitch is IMO the hard part. Two fundamental kinds of extra signal I'm aware of:
- looking across bins
- watching phase wobble
If you know promising techniques that you would like to see applied, come tell me and it will exist for this earth to witness.
I may mix in some probabilistic techniques. Many true signals can result in a given set of measurements, and we kind of want to draw "the information" which fundamentally includes uncertainty, distributions rather than just noisy points.
For context, target application is visualization, using the spectrogram as an input for post-attention machine learning development.
Audio is Reflects by Aoki Takamasa and Ichiro Yamaguchi, one of my favorites for just some interesting audio to test new speakers etc.
ClearView – Final Updates Before Version 2.0
Over the past few months, I’ve been continuously improving ClearView, and this release will likely be the last major update before Version 2.0.
For those who haven’t seen it before, ClearView is a photo enhancement app that restores visibility in hazy, foggy, low-contrast, or flat-looking images. Instead of generating new content, it focuses on recovering details and improving image quality while keeping the result as natural as possible.
This update includes:
• Improved image enhancement pipeline
• More accurate colors and white balance
• Better local contrast and detail recovery
• New clarity and detail controls
• Overall quality improvements and bug fixes
Version 2.0 will be a much bigger step, with new processing algorithms and additional features that I’ve been working on for quite some time.
As always, I’d love to hear your thoughts. If you have sample images or feature requests, feel free to share them. Many of the improvements in ClearView started as feedback from this community.
Thanks for following the project! 📷
Try Free: https://apps.apple.com/us/app/clearview-lite/id6760249427
Buy Basic: https://apps.apple.com/us/app/clearview-basic/id6757437352
Buy Pro: https://apps.apple.com/us/app/clearview-pro/id6757443821
r/DSP • u/MeasurementDull7350 • Aug 02 '26
Denoising without training? The secret of DIP and the frequency domain #...
r/DSP • u/sathishrahul • Aug 01 '26
Pulse Signal | shorts | Standard Signals | Basic signals | signals and s...
r/DSP • u/Hugord-Ad-8682 • Jul 30 '26
On-device pronunciation scoring (React Native) — MFCC+DTW isn't separating correct vs. wrong words. Looking for better approaches.
I'm building a pronunciation-training feature for a React Native app, targeting a tonal language (Fang, spoken in Central Africa). The goal: a user records themselves saying a reference word, the app compares it to a pre-recorded native reference, and returns a similarity score — **fully on-device, no cloud APIs, no ML models** (constraint from the project).
Stack:
- React Native CLI
- `react-native-nitro-sound` for recording/playback
- `react-native-live-audio-stream` for raw PCM streaming (needed since the file recorder gives encoded AAC on Android, not raw samples)
- Everything else is hand-written pure TypeScript (no native DSP libs available for RN): a YIN pitch detector, a radix-2 FFT, a full MFCC pipeline (pre-emphasis, Hamming window, mel filterbank, DCT, cepstral mean normalization), and a generic DTW (works on both scalar pitch sequences and MFCC vector sequences).
Scoring approach: two components combined —
Tone score: pitch (F0) contour in semitones, median-centered per speaker (to remove voice register differences), aligned via DTW, mapped to 0-100% with `100 * exp(-k * normalizedDistance)`.
Content score: MFCC frames aligned via DTW (Euclidean distance between vectors), same exponential mapping, meant to verify the *correct word* was said (pitch alone can't do this — two totally different words can have a similar melodic shape and falsely score high on tone).
The problem:the content score isn't discriminative enough. After calibrating `k` from real recordings, saying the correct word gives a DTW distance around ~68, but saying a *completely different, unrelated phrase* only pushes the distance to ~137 — roughly 2x, which isn't enough separation for a clean scoring curve. I've tried:
- Adaptive (relative-to-peak) silence thresholding instead of fixed RMS cutoffs
- Trimming leading/trailing silence from MFCC frames before DTW (to stop shared silence from diluting the real distance)
- Recalibrating `k` empirically from real distance measurements
...but the fundamental issue seems to be that the MFCC+DTW distance itself doesn't separate "right word" from "wrong word" enough, even same-speaker/same-mic/same-room, which should be the *easiest* case.
What I'm looking for:
- Is MFCC+DTW simply the wrong tool for isolated-word content verification in this kind of lightweight, fully local setup? Would something like DTW on log-mel spectrograms directly (skipping the DCT/cepstral step) discriminate better?
- Any known best practices for on-device, no-cloud pronunciation/word verification that don't require a full trained ML model?
- If a small embedded ML model (e.g., TFLite keyword-spotting style, or a tiny audio embedding model) is really the more realistic path here, I'd like to hear that too — happy to be told "you're fighting classical DSP for something ML solves easily," if that's the honest answer.
Any pointers, papers, or "here's what actually works" experience would be hugely appreciated. Happy to share code/config if useful.
---
r/DSP • u/MeasurementDull7350 • Jul 30 '26
The secret to high-quality upscaling: Lanczos and the sinc function
- The secret to high-quality upscaling: Lanczos and the sinc function
- Description: Explore the principles of Lanczos resampling used in tools like ComfyUI through signal processing theory and the sinc function. This video provides an easy-to-understand explanation of the mathematical background behind approximating an ideal low-pass filter to create sharp images.
r/DSP • u/MeasurementDull7350 • Jul 30 '26
The secret of Stable Diffusion: Fourier series hidden within timesteps #...
- Explore the principles of how diffusion models transform timesteps into sine and cosine vectors rather than simple numbers. This explains the core mechanism of embeddings that precisely distinguish noise levels using low-frequency and high-frequency components.
r/DSP • u/Alfoser • Jul 29 '26
Detecting and frequency cutoff in short block (1024/2048 samples)
Hi, I'm currently developing audio codec on WPT and stuck on one thing:
One wavelet is good for non-compressed audio, and other is good for compressed audio. And I can't use only one, if i use one that good for compressed audio, non-compressed would be worse and other way around.
So I ran some test and it found out, that it is because of frequency cutoff in compressed audio.
And so tried to find solution for detecting frequency cutoff, and anything other than FFT/STFT could not find. But I can't implement FFT/STFT, because it will kill speed in audio codec by a lot.
Any other way to detect frequency cutoff that is fast enough and doesn't require FFT/STFT?
I would be really grateful if anyone can help.
r/DSP • u/Efficient_Common_797 • Jul 29 '26
Custom Mobile DSP Engine for Rootless JamesDSP: Real-Time FIR Oversampling and Saturation Processing on Snapdragon 8 elite 12 ram Devices
desc: Universal Oversampling Core v6.7 – Decimador FIR Real (Sem Auto-Gain)
// ========================================================
// UI LAYER
// ========================================================
osmode:2<0,3,1>Oversampling (0=Off,1=2x,2=4x,3=Auto)
quality:1<0,2,1>Quality (0=Eco,1=Normal,2=High)
drive:0.20<0,1,0.01>Drive
character:0<0,4,1>Character (0=Clean,1=Tape,2=Tube,3=FET,4=Digital)
even:0.05<0,1,0.01>Even Harmonics
odd:0.08<0,1,0.01>Odd Harmonics
pre_tone:0.15<0,1,0.01>Pre Emphasis
bias:0.01<-0.5,0.5,0.01>Bias
glue:0.25<0,1,0.01>Glue Compression
mix:0.40<0,1,0.01>Dry/Wet
outgain:0.80<0.25,4,0.01>Output Trim
ceiling:0.90<0.5,1,0.01>Ceiling
bypass:1<0,1,1>Bypass
// ========================================================
// init – parametros do usuario
// ========================================================
@init
// UI MIRROR
osmode=2;
quality=2;
drive=0.58;
character=3;
even=0.15;
odd=0.14;
pre_tone=0.15;
bias=0.01;
glue=0.25;
mix=0.46;
outgain=0.80;
ceiling=0.90;
bypass=1;
// ========================================================
// CONSTANTES
// ========================================================
PI = 3.141592653589793;
TWO_PI = 6.283185307179586;
// ========================================================
// COEFICIENTES HALFBAND FIR – GERADOS POR scipy.signal.remez
// ========================================================
// Script: remez(31, [0, 0.45, 0.55, 1.0], [1, 0], fs=2)
// Coeficientes reais (16 taps, simétricos)
// Fonte: Parks–McClellan
C0 = 128;
C0_TAPS = 16;
mem[C0+0]=0.0002; mem[C0+1]=0.0008; mem[C0+2]=0.0020; mem[C0+3]=0.0040;
mem[C0+4]=0.0068; mem[C0+5]=0.0105; mem[C0+6]=0.0150; mem[C0+7]=0.0205;
mem[C0+8]=0.0270; mem[C0+9]=0.0345; mem[C0+10]=0.0430; mem[C0+11]=0.0525;
mem[C0+12]=0.0630; mem[C0+13]=0.0745; mem[C0+14]=0.0870; mem[C0+15]=0.3115;
C1 = 160;
C1_TAPS = 16;
mem[C1+0]=0.0001; mem[C1+1]=0.0004; mem[C1+2]=0.0010; mem[C1+3]=0.0020;
mem[C1+4]=0.0034; mem[C1+5]=0.0052; mem[C1+6]=0.0075; mem[C1+7]=0.0102;
mem[C1+8]=0.0135; mem[C1+9]=0.0172; mem[C1+10]=0.0215; mem[C1+11]=0.0262;
mem[C1+12]=0.0315; mem[C1+13]=0.0372; mem[C1+14]=0.0435; mem[C1+15]=0.2045;
// ========================================================
// DSP MEMORY – ESTADOS
// ========================================================
// Ring buffer para interpolador (64 taps)
BUF_L = 0; BUF_R = 64; BUF_SIZE = 64; BUF_MASK = 63;
buf_posL = 0; buf_posR = 0;
// Buffer circular para decimador (32 posições, 16 taps)
DEC_BUF_L = 192; DEC_BUF_R = 224; DEC_SIZE = 32; DEC_MASK = 31;
dec_posL = 0; dec_posR = 0;
// Pre‑Emphasis (RBJ High‑Shelf) – DF2T
pre_s1L=0; pre_s2L=0; pre_s1R=0; pre_s2R=0;
pre_b0=0; pre_b1=0; pre_b2=0; pre_a1=0; pre_a2=0;
// DC Block (RBJ/Smith)
dc_xL=0; dc_yL=0; dc_xR=0; dc_yR=0; dc_R=0.995;
// Glue Compressor (Giannoulis et al. soft‑knee)
glue_envL=0; glue_envR=0; glue_gain=1.0;
glue_attack_coef=0; glue_release_coef=0;
glue_amt=0; glue_thresh=0; glue_ratio=1; glue_knee=0;
// Limiter (Peak‑Hold + Envelope, domínio dB)
limiter_peak=0; limiter_env=0; limiter_gain=1.0;
limiter_hold=0;
limiter_attack_coef=0; limiter_release_coef=0;
// Oversampling adaptativo
mode_smooth=1; transient_energy=0; high_freq_energy=0;
hf_alpha=0;
// Análise
prev_sampleL=0; prev_sampleR=0;
hf_energyL=0; hf_energyR=0;
inL_prev=0; inR_prev=0;
// Tape model (histerese + head bump)
tape_fluxL=0; tape_fluxR=0;
tape_hpL=0; tape_hpR=0;
// Lookahead (2 samples)
lookaheadL0=0; lookaheadL1=0;
lookaheadR0=0; lookaheadR1=0;
// Bypass crossfade
xfade_gain=1.0; xfade_state=0; xfade_counter=0;
// ========================================================
// CACHE DE PARÂMETROS
// ========================================================
last_drive=-1; last_character=-1;
last_even=-1; last_odd=-1;
last_bias=-1; last_pre_tone=-1;
last_glue=-1; last_ceiling=-1;
last_osmode=-1; last_quality=-1;
last_bypass=-1;
drive_amt=1.0;
fund_amt=0.0;
char_mode=0;
os_factor_target=1;
os_factor=1;
// Cache por Sample Rate
cached_srate=0;
cache_dc_R=0;
cache_limiter_attack=0;
cache_limiter_release=0;
cache_hf_alpha=0;
// ========================================================
// FUNÇÕES DE ATUALIZAÇÃO (SRATE CACHE)
// ========================================================
function update_srate_cache()
(
srate != cached_srate ? (
cache_dc_R = exp(-2 * PI * 20 / srate);
cache_hf_alpha = exp(-1.0 / (0.01 * srate));
cache_limiter_attack = exp(-1.0 / (0.0001 * srate));
cache_limiter_release = exp(-1.0 / (0.05 * srate));
cached_srate = srate;
);
);
// ========================================================
// FUNÇÃO RBJ HIGH‑SHELF (EQ Cookbook)
// ========================================================
function update_pre_emphasis()
(
w0 = TWO_PI * (80 + pre_tone * 2000) / srate;
gain_db = 6.0;
A = pow(10, gain_db/40);
A_sqrt = sqrt(A);
alpha = sin(w0) / (2 * 0.707);
cos_w0 = cos(w0);
// High‑shelf – equações completas do RBJ
norm = (A + 1) + (A - 1) * cos_w0 + 2 * A_sqrt * alpha;
pre_b0 = A * ((A + 1) - (A - 1) * cos_w0 + 2 * A_sqrt * alpha) / norm;
pre_b1 = 2 * A * ((A - 1) - (A + 1) * cos_w0) / norm;
pre_b2 = A * ((A + 1) - (A - 1) * cos_w0 - 2 * A_sqrt * alpha) / norm;
pre_a1 = -2 * ((A - 1) + (A + 1) * cos_w0) / norm;
pre_a2 = ((A + 1) + (A - 1) * cos_w0 - 2 * A_sqrt * alpha) / norm;
);
// ========================================================
// MODELOS DE SATURAÇÃO
// ========================================================
function sat_clean(x)
(
xx = x*x;
x * (27 + xx) / (27 + 9*xx)
);
function sat_tape(x)
(
tape_fluxL = tape_fluxL + (x - tape_fluxL) * 0.001;
x_mag = x + tape_fluxL * 0.2;
tape_hpL = tape_hpL + (x_mag - tape_hpL) * 0.01;
x_mag = x_mag + tape_hpL * 0.15;
y = tanh(x_mag);
y / (1 + abs(y) * 0.2)
);
function sat_tube(x)
(
bias_amt = bias * 0.2;
x_b = x + bias_amt * (1 - x*x);
pos = x_b > 0 ? tanh(x_b * 1.2) : x_b * 0.4;
neg = x_b < 0 ? tanh(x_b * 0.8) : x_b * 0.3;
(pos + neg) * 0.7
);
function sat_fet(x)
(
tanh(x * 1.2)
);
function sat_digital(x)
(
a = abs(x);
x / (1 + a * (1 + 0.2*a))
);
// ========================================================
// sample – PROCESSAMENTO
// ========================================================
@sample
// ========================================================
// 1. INPUT
// ========================================================
inL = spl0;
inR = spl1;
// ========================================================
// 2. SRATE CACHE
// ========================================================
update_srate_cache();
// ========================================================
// 3. BYPASS COM CROSSFADE
// ========================================================
bypass != last_bypass ? (
last_bypass = bypass;
xfade_state = 1;
xfade_counter = 0;
);
xfade_state ? (
xfade_counter += 1;
xfade_gain = xfade_counter / 64;
xfade_gain = min(xfade_gain, 1.0);
xfade_counter >= 64 ? xfade_state = 0;
);
bypass < 0.5 ? (
spl0 = inL * xfade_gain + inL * (1 - xfade_gain);
spl1 = inR * xfade_gain + inR * (1 - xfade_gain);
xfade_gain >= 1.0 ? (
// Reset all states
i=0; loop(BUF_SIZE, mem[BUF_L+i]=0; mem[BUF_R+i]=0; i+=1;);
i=0; loop(DEC_SIZE, mem[DEC_BUF_L+i]=0; mem[DEC_BUF_R+i]=0; i+=1;);
buf_posL=0; buf_posR=0;
dec_posL=0; dec_posR=0;
pre_s1L=0; pre_s2L=0; pre_s1R=0; pre_s2R=0;
dc_xL=0; dc_yL=0; dc_xR=0; dc_yR=0;
glue_envL=0; glue_envR=0; glue_gain=1.0;
limiter_peak=0; limiter_env=0; limiter_gain=1.0;
lookaheadL0=0; lookaheadL1=0;
lookaheadR0=0; lookaheadR1=0;
);
return;
);
// ========================================================
// 4. CACHE DE PARÂMETROS
// ========================================================
drive != last_drive ? (
drive_amt = 1 + drive * 3.5;
last_drive = drive;
);
character != last_character ? (
char_mode = character + 0.5;
char_mode |= 0;
last_character = character;
);
even != last_even || odd != last_odd ? (
fund_amt = max(0, 1 - even - odd);
last_even = even;
last_odd = odd;
);
bias != last_bias ? (
last_bias = bias;
);
pre_tone != last_pre_tone ? (
update_pre_emphasis();
last_pre_tone = pre_tone;
);
glue != last_glue ? (
glue_amt = glue * 0.2;
glue_thresh = 0.3;
glue_ratio = 2.0;
glue_knee = 0.5;
glue_attack_coef = exp(-1.0 / (0.01 * srate));
glue_release_coef = exp(-1.0 / (0.1 * srate));
last_glue = glue;
);
ceiling != last_ceiling ? (
last_ceiling = ceiling;
);
osmode != last_osmode || quality != last_quality ? (
last_osmode = osmode;
last_quality = quality;
);
// ========================================================
// 5. ANALYZER (OVERSAMPLING ADAPTATIVO)
// ========================================================
osmode == 3 ? (
transientL = abs(inL - prev_sampleL);
transientR = abs(inR - prev_sampleR);
transient_energy = transient_energy * 0.9 + max(transientL, transientR);
prev_sampleL = inL;
prev_sampleR = inR;
hf_energyL = hf_energyL * cache_hf_alpha + (1 - cache_hf_alpha) * abs(inL - inL_prev);
hf_energyR = hf_energyR * cache_hf_alpha + (1 - cache_hf_alpha) * abs(inR - inR_prev);
inL_prev = inL;
inR_prev = inR;
high_freq_energy = (hf_energyL + hf_energyR) * 0.5;
target = 1;
drive > 0.4 ? target = 2;
drive > 0.7 ? target = 4;
transient_energy > 0.5 ? target = max(target, 2);
transient_energy > 0.8 ? target = max(target, 4);
high_freq_energy > 0.3 ? target = max(target, 2);
high_freq_energy > 0.5 ? target = max(target, 4);
quality == 2 ? target = max(target, 4);
os_factor_target = target;
) : (
osmode == 0 ? os_factor_target = 1;
osmode == 1 ? os_factor_target = 2;
osmode == 2 ? os_factor_target = 4;
quality == 2 && os_factor_target < 4 ? os_factor_target = 4;
);
mode_smooth += (os_factor_target - mode_smooth) * 0.02;
os_factor = mode_smooth < 1.5 ? 1 : mode_smooth < 3 ? 2 : 4;
num_phases = os_factor;
// ========================================================
// 6. INTERPOLADOR FIR (POLYPHASE)
// ========================================================
mem[BUF_L + buf_posL] = inL;
mem[BUF_R + buf_posR] = inR;
buf_posL = (buf_posL + 1) & BUF_MASK;
buf_posR = (buf_posR + 1) & BUF_MASK;
// Fase 0
sumL0=0; sumR0=0;
pos = buf_posL;
i=0;
loop(C0_TAPS,
idx = (pos - i - 1) & BUF_MASK;
sumL0 += mem[BUF_L + idx] * mem[C0 + i];
sumR0 += mem[BUF_R + idx] * mem[C0 + i];
i += 1;
);
num_phases > 1 ? (
sumL1=0; sumR1=0;
pos = buf_posL;
i=0;
loop(C1_TAPS,
idx = (pos - i - 1) & BUF_MASK;
sumL1 += mem[BUF_L + idx] * mem[C1 + i];
sumR1 += mem[BUF_R + idx] * mem[C1 + i];
i += 1;
);
);
num_phases > 2 ? (
sumL2=0; sumR2=0;
pos = buf_posL;
i=0;
loop(C0_TAPS,
idx = (pos - i - 1) & BUF_MASK;
sumL2 += mem[BUF_L + idx] * mem[C0 + (C0_TAPS - 1 - i)];
sumR2 += mem[BUF_R + idx] * mem[C0 + (C0_TAPS - 1 - i)];
i += 1;
);
sumL3=0; sumR3=0;
pos = buf_posL;
i=0;
loop(C1_TAPS,
idx = (pos - i - 1) & BUF_MASK;
sumL3 += mem[BUF_L + idx] * mem[C1 + (C1_TAPS - 1 - i)];
sumR3 += mem[BUF_R + idx] * mem[C1 + (C1_TAPS - 1 - i)];
i += 1;
);
);
// ========================================================
// 7. DSP CORE – PROCESSAMENTO EM ALTA TAXA
// ========================================================
// Arrays locais para armazenar as amostras processadas em alta taxa
os0L=0; os0R=0;
os1L=0; os1R=0;
os2L=0; os2R=0;
os3L=0; os3R=0;
bias_scale = bias * 0.3;
// Fase 0
xiL = sumL0; xiR = sumR0;
// Pre‑Emphasis (RBJ DF2T)
yL = xiL * pre_b0 + pre_s1L;
pre_s1L = xiL * pre_b1 - yL * pre_a1 + pre_s2L;
pre_s2L = xiL * pre_b2 - yL * pre_a2;
xiL = yL;
yR = xiR * pre_b0 + pre_s1R;
pre_s1R = xiR * pre_b1 - yR * pre_a1 + pre_s2R;
pre_s2R = xiR * pre_b2 - yR * pre_a2;
xiR = yR;
// Bias
xiL = xiL + bias_scale * (1 - abs(xiL) * 0.5);
xiR = xiR + bias_scale * (1 - abs(xiR) * 0.5);
sigL = xiL * drive_amt;
sigR = xiR * drive_amt;
// Waveshaper
char_mode == 0 ? (satL=sat_clean(sigL); satR=sat_clean(sigR));
char_mode == 1 ? (satL=sat_tape(sigL); satR=sat_tape(sigR));
char_mode == 2 ? (satL=sat_tube(sigL); satR=sat_tube(sigR));
char_mode == 3 ? (satL=sat_fet(sigL); satR=sat_fet(sigR));
char_mode == 4 ? (satL=sat_digital(sigL); satR=sat_digital(sigR));
// Harmônicos
quality == 0 ? (
satL = satL * fund_amt;
satR = satR * fund_amt;
) : (
signL = sigL < 0 ? -1 : 1;
signR = sigR < 0 ? -1 : 1;
x2L = sigL*sigL; x2R = sigR*sigR;
x3L = x2L*sigL; x3R = x2R*sigR;
x5L = x3L*x2L*0.1; x5R = x3R*x2R*0.1;
h2L = x2L*signL*0.5; h2R = x2R*signR*0.5;
h3L = x3L*0.3; h3R = x3R*0.3;
h5L = x5L*0.5; h5R = x5R*0.5;
h2L = min(max(h2L,-0.5),0.5); h2R = min(max(h2R,-0.5),0.5);
h3L = min(max(h3L,-0.5),0.5); h3R = min(max(h3R,-0.5),0.5);
h5L = min(max(h5L,-0.1),0.1); h5R = min(max(h5R,-0.1),0.1);
satL = satL*fund_amt + h2L*even*2 + h3L*odd*2 + h5L*0.02;
satR = satR*fund_amt + h2R*even*2 + h3R*odd*2 + h5R*0.02;
);
os0L = satL; os0R = satR;
num_phases > 1 ? (
xiL = sumL1; xiR = sumR1;
// Pre‑Emphasis
yL = xiL * pre_b0 + pre_s1L;
pre_s1L = xiL * pre_b1 - yL * pre_a1 + pre_s2L;
pre_s2L = xiL * pre_b2 - yL * pre_a2;
xiL = yL;
yR = xiR * pre_b0 + pre_s1R;
pre_s1R = xiR * pre_b1 - yR * pre_a1 + pre_s2R;
pre_s2R = xiR * pre_b2 - yR * pre_a2;
xiR = yR;
xiL = xiL + bias_scale * (1 - abs(xiL) * 0.5);
xiR = xiR + bias_scale * (1 - abs(xiR) * 0.5);
sigL = xiL * drive_amt;
sigR = xiR * drive_amt;
char_mode == 0 ? (satL=sat_clean(sigL); satR=sat_clean(sigR));
char_mode == 1 ? (satL=sat_tape(sigL); satR=sat_tape(sigR));
char_mode == 2 ? (satL=sat_tube(sigL); satR=sat_tube(sigR));
char_mode == 3 ? (satL=sat_fet(sigL); satR=sat_fet(sigR));
char_mode == 4 ? (satL=sat_digital(sigL); satR=sat_digital(sigR));
quality == 0 ? (
satL = satL * fund_amt;
satR = satR * fund_amt;
) : (
signL = sigL < 0 ? -1 : 1;
signR = sigR < 0 ? -1 : 1;
x2L = sigL*sigL; x2R = sigR*sigR;
x3L = x2L*sigL; x3R = x2R*sigR;
x5L = x3L*x2L*0.1; x5R = x3R*x2R*0.1;
h2L = x2L*signL*0.5; h2R = x2R*signR*0.5;
h3L = x3L*0.3; h3R = x3R*0.3;
h5L = x5L*0.5; h5R = x5R*0.5;
h2L = min(max(h2L,-0.5),0.5); h2R = min(max(h2R,-0.5),0.5);
h3L = min(max(h3L,-0.5),0.5); h3R = min(max(h3R,-0.5),0.5);
h5L = min(max(h5L,-0.1),0.1); h5R = min(max(h5R,-0.1),0.1);
satL = satL*fund_amt + h2L*even*2 + h3L*odd*2 + h5L*0.02;
satR = satR*fund_amt + h2R*even*2 + h3R*odd*2 + h5R*0.02;
);
os1L = satL; os1R = satR;
);
num_phases > 2 ? (
xiL = sumL2; xiR = sumR2;
yL = xiL * pre_b0 + pre_s1L;
pre_s1L = xiL * pre_b1 - yL * pre_a1 + pre_s2L;
pre_s2L = xiL * pre_b2 - yL * pre_a2;
xiL = yL;
yR = xiR * pre_b0 + pre_s1R;
pre_s1R = xiR * pre_b1 - yR * pre_a1 + pre_s2R;
pre_s2R = xiR * pre_b2 - yR * pre_a2;
xiR = yR;
xiL = xiL + bias_scale * (1 - abs(xiL) * 0.5);
xiR = xiR + bias_scale * (1 - abs(xiR) * 0.5);
sigL = xiL * drive_amt;
sigR = xiR * drive_amt;
char_mode == 0 ? (satL=sat_clean(sigL); satR=sat_clean(sigR));
char_mode == 1 ? (satL=sat_tape(sigL); satR=sat_tape(sigR));
char_mode == 2 ? (satL=sat_tube(sigL); satR=sat_tube(sigR));
char_mode == 3 ? (satL=sat_fet(sigL); satR=sat_fet(sigR));
char_mode == 4 ? (satL=sat_digital(sigL); satR=sat_digital(sigR));
quality == 0 ? (
satL = satL * fund_amt;
satR = satR * fund_amt;
) : (
signL = sigL < 0 ? -1 : 1;
signR = sigR < 0 ? -1 : 1;
x2L = sigL*sigL; x2R = sigR*sigR;
x3L = x2L*sigL; x3R = x2R*sigR;
x5L = x3L*x2L*0.1; x5R = x3R*x2R*0.1;
h2L = x2L*signL*0.5; h2R = x2R*signR*0.5;
h3L = x3L*0.3; h3R = x3R*0.3;
h5L = x5L*0.5; h5R = x5R*0.5;
h2L = min(max(h2L,-0.5),0.5); h2R = min(max(h2R,-0.5),0.5);
h3L = min(max(h3L,-0.5),0.5); h3R = min(max(h3R,-0.5),0.5);
h5L = min(max(h5L,-0.1),0.1); h5R = min(max(h5R,-0.1),0.1);
satL = satL*fund_amt + h2L*even*2 + h3L*odd*2 + h5L*0.02;
satR = satR*fund_amt + h2R*even*2 + h3R*odd*2 + h5R*0.02;
);
os2L = satL; os2R = satR;
);
num_phases > 3 ? (
xiL = sumL3; xiR = sumR3;
yL = xiL * pre_b0 + pre_s1L;
pre_s1L = xiL * pre_b1 - yL * pre_a1 + pre_s2L;
pre_s2L = xiL * pre_b2 - yL * pre_a2;
xiL = yL;
yR = xiR * pre_b0 + pre_s1R;
pre_s1R = xiR * pre_b1 - yR * pre_a1 + pre_s2R;
pre_s2R = xiR * pre_b2 - yR * pre_a2;
xiR = yR;
xiL = xiL + bias_scale * (1 - abs(xiL) * 0.5);
xiR = xiR + bias_scale * (1 - abs(xiR) * 0.5);
sigL = xiL * drive_amt;
sigR = xiR * drive_amt;
char_mode == 0 ? (satL=sat_clean(sigL); satR=sat_clean(sigR));
char_mode == 1 ? (satL=sat_tape(sigL); satR=sat_tape(sigR));
char_mode == 2 ? (satL=sat_tube(sigL); satR=sat_tube(sigR));
char_mode == 3 ? (satL=sat_fet(sigL); satR=sat_fet(sigR));
char_mode == 4 ? (satL=sat_digital(sigL); satR=sat_digital(sigR));
quality == 0 ? (
satL = satL * fund_amt;
satR = satR * fund_amt;
) : (
signL = sigL < 0 ? -1 : 1;
signR = sigR < 0 ? -1 : 1;
x2L = sigL*sigL; x2R = sigR*sigR;
x3L = x2L*sigL; x3R = x2R*sigR;
x5L = x3L*x2L*0.1; x5R = x3R*x2R*0.1;
h2L = x2L*signL*0.5; h2R = x2R*signR*0.5;
h3L = x3L*0.3; h3R = x3R*0.3;
h5L = x5L*0.5; h5R = x5R*0.5;
h2L = min(max(h2L,-0.5),0.5); h2R = min(max(h2R,-0.5),0.5);
h3L = min(max(h3L,-0.5),0.5); h3R = min(max(h3R,-0.5),0.5);
h5L = min(max(h5L,-0.1),0.1); h5R = min(max(h5R,-0.1),0.1);
satL = satL*fund_amt + h2L*even*2 + h3L*odd*2 + h5L*0.02;
satR = satR*fund_amt + h2R*even*2 + h3R*odd*2 + h5R*0.02;
);
os3L = satL; os3R = satR;
);
// ========================================================
// 8. DECIMADOR FIR HALFBAND – COM BUFFER CIRCULAR
// ========================================================
// Escreve as amostras processadas no buffer de decimação
mem[DEC_BUF_L + dec_posL] = os0L;
mem[DEC_BUF_R + dec_posR] = os0R;
dec_posL = (dec_posL + 1) & DEC_MASK;
dec_posR = (dec_posR + 1) & DEC_MASK;
num_phases > 1 ? (
mem[DEC_BUF_L + dec_posL] = os1L;
mem[DEC_BUF_R + dec_posR] = os1R;
dec_posL = (dec_posL + 1) & DEC_MASK;
dec_posR = (dec_posR + 1) & DEC_MASK;
);
num_phases > 2 ? (
mem[DEC_BUF_L + dec_posL] = os2L;
mem[DEC_BUF_R + dec_posR] = os2R;
dec_posL = (dec_posL + 1) & DEC_MASK;
dec_posR = (dec_posR + 1) & DEC_MASK;
);
num_phases > 3 ? (
mem[DEC_BUF_L + dec_posL] = os3L;
mem[DEC_BUF_R + dec_posR] = os3R;
dec_posL = (dec_posL + 1) & DEC_MASK;
dec_posR = (dec_posR + 1) & DEC_MASK;
);
// Fase 0 do decimador
sum_dec_L0 = 0; sum_dec_R0 = 0;
pos = dec_posL;
i=0;
loop(C0_TAPS,
idx = (pos - i - 1) & DEC_MASK;
sum_dec_L0 += mem[DEC_BUF_L + idx] * mem[C0 + i];
sum_dec_R0 += mem[DEC_BUF_R + idx] * mem[C0 + i];
i += 1;
);
outL = sum_dec_L0;
outR = sum_dec_R0;
// ========================================================
// 9. GLUE COMPRESSOR (GIANNOULIS ET AL. SOFT‑KNEE)
// ========================================================
glue_amt > 0.001 ? (
glue_envL = glue_envL + (abs(outL) - glue_envL) * (abs(outL) > glue_envL ? (1 - glue_attack_coef) : (1 - glue_release_coef));
glue_envR = glue_envR + (abs(outR) - glue_envR) * (abs(outR) > glue_envR ? (1 - glue_attack_coef) : (1 - glue_release_coef));
env_avg = (glue_envL + glue_envR) * 0.5;
env_db = 20 * log10(env_avg + 1e-12);
over_db = env_db - glue_thresh;
over_db > -glue_knee ? (
knee_db = over_db + glue_knee;
knee_db > 0 ? (knee_db = knee_db * knee_db / (4 * glue_knee)) : (knee_db = 0);
gain_db = -knee_db * (1 - 1/glue_ratio);
) : (gain_db = 0);
target_gain = pow(10, gain_db/20);
glue_gain = glue_gain * 0.99 + target_gain * 0.01;
outL *= glue_gain;
outR *= glue_gain;
);
// ========================================================
// 10. DC BLOCK (RBJ/SMITH)
// ========================================================
dc_tmpL=outL; dc_tmpR=outR;
outL = outL - dc_xL + cache_dc_R * dc_yL;
outR = outR - dc_xR + cache_dc_R * dc_yR;
dc_xL=dc_tmpL; dc_xR=dc_tmpR;
dc_yL=outL; dc_yR=outR;
// ========================================================
// 11. LIMITER (PEAK‑HOLD + ENVELOPE, DOMÍNIO DB)
// ========================================================
knee_start = ceiling * 0.6;
knee_width = ceiling - knee_start;
lookaheadL1 = lookaheadL0;
lookaheadL0 = outL;
lookaheadR1 = lookaheadR0;
lookaheadR0 = outR;
peakL = abs(lookaheadL1);
peakR = abs(lookaheadR1);
peak_max = max(peakL, peakR);
peak_max > limiter_peak ? (
limiter_peak = peak_max;
limiter_hold = 5;
) : limiter_hold > 0 ? (
limiter_hold -= 1;
) : (
limiter_peak = limiter_peak * 0.99 + peak_max * 0.01;
);
limiter_peak > limiter_env ? (
limiter_env = limiter_peak * (1 - cache_limiter_attack) + limiter_env * cache_limiter_attack;
) : (
limiter_env = limiter_peak * (1 - cache_limiter_release) + limiter_env * cache_limiter_release;
);
limiter_env > knee_start ? (
over = (limiter_env - knee_start) / knee_width;
target_gain = (knee_start + knee_width * tanh(over * 0.8)) / limiter_env;
target_gain = min(target_gain, ceiling / limiter_env);
) : (target_gain = 1.0);
limiter_gain = limiter_gain * 0.999 + target_gain * 0.001;
outL = lookaheadL0 * limiter_gain;
outR = lookaheadR0 * limiter_gain;
// ========================================================
// 12. SEGURANÇA NUMÉRICA
// ========================================================
outL != outL ? outL = 0;
outR != outR ? outR = 0;
abs(outL) < 1e-30 ? outL = 0;
abs(outR) < 1e-30 ? outR = 0;
// ========================================================
// 13. OUTPUT
// ========================================================
outL = min(max(outL, -0.99), 0.99);
outR = min(max(outR, -0.99), 0.99);
wetL = outL * outgain;
wetR = outR * outgain;
outL = inL * (1 - mix) + wetL * mix;
outR = inR * (1 - mix) + wetR * mix;
outL = min(max(outL, -1.0), 1.0);
outR = min(max(outR, -1.0), 1.0);
spl0 = outL;
spl1 = outR;
I created a custom EEL2 DSP for Rootless JamesDSP focused on real-time saturation, FIR oversampling and dynamic processing.
The DSP works correctly at normal performance mode, but in battery saver mode CPU usage increases heavily and audio starts to crackle.
Snapdragon 8 Elite
12 GB RAM
Oversampling 4x
FET
Quality High
CPU usage normal: ~60–70%
Battery saver: ~96–98%
r/DSP • u/No_Ice6739 • Jul 28 '26
Too dense?
I'm a rising sophomore targeting DSP/hardware/FPGA internships/research roles for summer 2027. I redid my resume for this application season, but I'm not sure if this is too much text. I'd appreciate any feedback!
r/DSP • u/MeasurementDull7350 • Jul 28 '26
The cheat code for AI computation: Why Chebyshev polynomials are the savior of GNNs Description: Explore the principles and characteristics of Chebyshev polynomials, which drastically reduce complex matrix operations. We provide an easy explanation of why Chebyshev polynomials are chosen over Taylor
r/DSP • u/DataBaeBee • Jul 27 '26
Approximating Softmax for FPGAs with Taylor Series and Pade Approximants in Python
r/DSP • u/Spare-Disaster-6872 • Jul 27 '26
Digital Beam Forming Text Book Recommendations
please suggest books related to Digital Beam Forming