Skip to content

Conversation

@chattob
Copy link
Contributor

@chattob chattob commented Jan 10, 2026

Add tape modulation to delay module

Adds a new "Tape" waveform option that simulates analog tape wow and flutter using Perlin noise.

Changes

  • New TapeModulator class using 1D Perlin noise
  • Separate wow (slow) and flutter (fast) modulation components
  • When using Tape modulation on delay time: dynamic minimum delay calculation prevents buffer underruns, allowing the delay to work as a real-time tape effect (delay time = 0, feedback = 0, mix = 1)

chattob added 6 commits December 25, 2025 23:29
Wrap time accumulators to prevent floating-point precision loss.
Without wrapping, t_wow_ and t_flutter_ grow indefinitely, causing
precision issues in the Perlin noise calculations that result in
getTapeSpeed returning constant values.
@chattob chattob changed the title Feat/tape modulation Add tape modulation to delay module Jan 10, 2026
@xconverge
Copy link
Collaborator

Right on! I had a chase bliss lost and found and sent it back because it wasn't doing it for me. My board is missing a lot of modulation options and this was definitely something I was interested in! Thanks!

@xconverge xconverge merged commit f2031eb into bkshepherd:main Jan 11, 2026
1 check passed
@chattob chattob deleted the feat/tapeModulation branch January 12, 2026 06:48
@chattob
Copy link
Contributor Author

chattob commented Jan 12, 2026

Great! I am glad you like it! Thanks for all the work you have been doing on the project!

Some optimizations I realized are possible only after the PR:

  • In tape_modulator: perm_[512] doesn't actually need to be so big since we wraparound X at 255. We only access up to index 256, so perm_[257] would be enough (saves 255 bytes). We could even have just 1 compile-time constexpr array instead of both p_ and perm_, eliminating the initialization loop.
  • In delay_module: The wow_rate and flutter_rate magic numbers might not be the best choice. You might want to try different rates for yourself.

@GuitarML
Copy link
Collaborator

GuitarML commented Jan 17, 2026

@chattob I just tried this out and I love it!! I'll dig into the code soon, but is there an easy way to apply this to the live guitar stream, not just the delay? I would really like it as a stand alone effect separate from the Delay module. Or is the delayline part of how it operates and it can't really be separated out. Either way thanks for the contribution and hard work!

Edit: I tried turning the delay time all the way down, and the mix all the way to the right (full delay) and it gets close to what I'm imagining.

Nevermind, I see in your initial PR that also turning the feedback to 0 will give the effect I'm looking for. Very cool!

@chattob
Copy link
Contributor Author

chattob commented Jan 18, 2026

@GuitarML Hi Keith! Yes, my intent when I coded this was to apply it as a live effect. I believe some latency is unavoidable because when the virtual tape speed goes above 1×, the reader has to consume samples faster than they arrive. So we need to keep a small buffer to read from. Maybe there is some smart way around it, but I didn't find it!

To get as close as possible to real-time, I don't use m_delaySamplesMin and set the min delay samples as low as possible instead (just making sure delayTarget is always >= 1 after applying modulation): see lines 273 to 288. With delay time all the way down the latency I measured is around 40ms, so not too bad ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants