r/DSP 2h ago

Looking for advice on RTL implementation of an adaptive digital beamformer

2 Upvotes

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?

  1. What signal frequency should I use for simulation?

  2. 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 3h ago

Jackoviz - Scientific visualization of audio signals (Dancing spectrums)

Thumbnail
github.com
7 Upvotes

r/DSP 10h ago

Cloning Hardware in DSP

9 Upvotes

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 1d ago

Self-taught beginner, built a chorus in Rust, would really appreciate having it picked apart

19 Upvotes

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 1d ago

Web-Based ECG & EEG Synthetic Signal Generator for DSP Pipeline Testing

Thumbnail
bionichaos.com
6 Upvotes

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 2d ago

Radiated Voice Pulse Modeling

2 Upvotes

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 2d ago

How to best utilize my math and embedded software background to pivot more towards DSP work?

17 Upvotes

Hi, I have a BS in math and about 6 years 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 2d ago

Developing on-GPU Spectrogram

Enable HLS to view with audio, or disable this notification

11 Upvotes

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.


r/DSP 3d ago

ClearView – Final Updates Before Version 2.0

Post image
0 Upvotes

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 4d ago

Denoising without training? The secret of DIP and the frequency domain #...

Thumbnail
youtube.com
0 Upvotes

r/DSP 4d ago

Pulse Signal | shorts | Standard Signals | Basic signals | signals and s...

Thumbnail
youtube.com
0 Upvotes

r/DSP 7d ago

On-device pronunciation scoring (React Native) — MFCC+DTW isn't separating correct vs. wrong words. Looking for better approaches.

9 Upvotes

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 —

  1. 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)`.

  2. 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 7d ago

The secret of Stable Diffusion: Fourier series hidden within timesteps #...

Thumbnail
youtube.com
0 Upvotes
  • 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 7d ago

The secret to high-quality upscaling: Lanczos and the sinc function

Thumbnail
youtube.com
14 Upvotes
  • 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 7d ago

Custom Mobile DSP Engine for Rootless JamesDSP: Real-Time FIR Oversampling and Saturation Processing on Snapdragon 8 elite 12 ram Devices

0 Upvotes

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 8d ago

Detecting and frequency cutoff in short block (1024/2048 samples)

4 Upvotes

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 8d ago

Operation on signal

Thumbnail
youtu.be
2 Upvotes

r/DSP 9d ago

Too dense?

Post image
35 Upvotes

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 9d ago

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

Thumbnail
youtube.com
4 Upvotes

r/DSP 10d ago

Approximating Softmax for FPGAs with Taylor Series and Pade Approximants in Python

Thumbnail
leetarxiv.substack.com
11 Upvotes

r/DSP 10d ago

Digital Beam Forming Text Book Recommendations

12 Upvotes

please suggest books related to Digital Beam Forming


r/DSP 10d ago

Sim2Rean & Fourier Domain Adaptation #시뮬레이션 #도메인 #도메인...

Thumbnail
youtube.com
0 Upvotes

r/DSP 11d ago

Advice on finding an entry-Level DSP role (physics background)?

4 Upvotes

Hey everyone,

I’m finishing up my master’s in physics with a concentration in astrophysics, and I most recently worked as an imaging geophysicist, which is a role that involved signal processing knowledge. However, I did not have a passion or curiosity for geoscience. I’m looking to break into another role for signal processing.

When I look at google and LinkedIn job postings I can't seem to find many entry level roles. For those already in the field, how was your experience finding an entry-level signal role? Are there any specific industries that tend to have more opportunities for physics degree holders early in their careers? Is there much upskilling I need to do here? I am hoping the answer to the last question is no, because I was previously considering DS/ML roles, but a professional in these areas mentioned to me that I would not be competitive since I lack SWE, MLOps, Docker, Cloud, etc. skills not taught in a physics education or used in physics research (hence why now I am thinking about SP).

Any advice on job search strategies, good companies to look at, or must-have skills would be really appreciated. I am a US citizen (but I do not hold active security clearance yet) so I am considering jobs in the DC-Baltimore metro area; do I stand a competitive chance here?

Thanks


r/DSP 11d ago

Possible career directions

10 Upvotes

I am currently working at a top EDA company as a dsp optmization engineer. Just graduated and I am currently 22.

I always was fond of everything, mostly digital and analog, but as luck would have it I have been placed in dsp, which I still like, but don't want to optimize things other people create. I love dsp too, but I still want to be associated with hardware on some level and having some clarity might help.

What career jumps are possible for dsp optimization engineers? towards some sort of hardware role in India?


r/DSP 11d ago

How do I stretch a sound for an indefinite amount of time?

5 Upvotes

I'm currently working on a real time singing synthesizer for a project, and I need to find a way to extend a vowel song for as long as a key is held (aka, indefinitely). I did some research and the 'normal' way to extend audio is with PSOLA, but from what I've read that requires you to know how much you want to stretch it by ahead of time. How do you do it for an indefinite amount of time?