Modulte filter frequency but only allow frequencies from scale

I want to randomly modulate the filter frequency (synced to the tempo of the song, e.g. 1/16, 1/8 , etc.) with the formula device, but only want to allow frequencies from a given scale to get these bubbly sounds when the resonance is close to maximum. Did anybody programmed such a snippet?

1 Like

Add an LFO device into your chain that is linked to your filter, give it a custom envelope that hits the min/max value filter frequency limits that you desire, and then automate the LFO’s Reset parameter to change positions within your custom envelope.

That way it will never exceed the frequency limits of what you consider to be acceptable. You can then also automate the LFO’s own frequency to fit your song’s tempo-synced wobbles, or set it to “INF LPC” to make it freeze in place (handy for wavetable-ish control), etc.

Plenty of options to explore :slight_smile:

PS: Check out my included tutorial song: Help > Tutorial and Demo Songs > Beat Synced Wobbles

3 Likes

what about KeyTracker ? It will be synced with notes.

2 Likes

I believe it can be done with a formula device to discretize the cutoff steps according to a preset scale and periodic update frequency.

I have not done this exactly yet, but very similar things, with formula devices.

For one thing this code may be useful for you: https://forum.renoise.com/t/effect-presets-tuned-keytracked-effects-formulas-doofers-ktrk-1-1/ - these are keytracker tuning formula device presets, they allow certain renoise native effects to be tuned to a keytracker…also all the native analog/digital track effect filters’ cutoffs…

The other code I had already done was tuning the pitch of an instrument (via inst.macros feedback on pitch modulation) to an array of predefined harmonic steps of the base note, so you could zoom with a dial and repitch the sound to natural harmonic sequences. I used a table of harmonics which then defined a scale, and instead of playing a pitch, you’d play a base note and use a knob or pedal or modwheel to scan through that scale.

So I can imagine, using the tuning functions of the ktrk code you can tune the filter, and then instead of a key tracker, you can use another formula which will translate the cutoff knob/envelope/modulation into discrete steps within the desired scale, and which will relay an update until the preset time (i.e. 1/16, 1/8, triplets etc.) had passed.

Of course this will only work with actual DSP filter devices; you could also control the (polyphonic) instrument filter with way with a macro, but it will not work polyphonic, all note’s cutoffs must be set to the same value. So using the Analog/Digital filter DSP device and going monophonic is the better way to achieve this. There is no formula action inside the instrument modulation, only in the DSP, so that’s why.

I could try to help you with this, but I’m currently ultra stressed out with different other things, maybe I can find an hour or two for it on the weekend.

2 Likes

Thanks, I will have a look. Thanks also for offering help, but it’s actually not that important and I will figure it out on my own :slight_smile:

This goes into the right direction. Not sure yet how to sync the tempo correctly:

--[[
 This formula generates a beat-synced random frequency 
 based on specified musical notes in the A minor scale.
]]

-- Function to convert note number to frequency
local function note_to_frequency(note)
  return 440 * pow(2, (note - 69) / 12)
end

local CUTOFF_SCALING = 100
local hl = 40
local hh = 18000

-- Log scaling for the filter frequency
local function cutoff_lin2log(value)
  if value > 0.0 then
    return log10((CUTOFF_SCALING - 1.0) * value + 1.0) / log10(CUTOFF_SCALING)
  else
    return 0
  end
end

-- Maps Hz value to a cutoff frequency parameter value
local function frq2flt(frequency)
  local normalized = (frequency - hl) / (hh - hl)
  normalized = max(0, min(1, normalized))
  local scaled = cutoff_lin2log(normalized)
  return scaled
end

---@param speed number
local function beat_random_scale(speed)
  -- Define the note numbers for the A minor scale
   local notes = { 69, 71, 72, 74, 76, 77, 79 }  -- A4 = 69, B4 = 71, C5 = 72, D5 = 74, E5 = 76, F5 = 77, G5 = 79
  
 
  
  -- Determine the current seed based on BEATS and speed
  local seed = floor(BEATS / speed)
  randomseed(seed)  -- Set the random seed to maintain tempo sync
  
  -- Generate a random index to select a note from the scale
  local index = random(1, #notes)  -- Random index from 1 to the length of the notes table
  local note = notes[index]  -- Get the random note number
  local frequency = note_to_frequency(note)  -- Convert note to frequency
   local scaledFrequency = frq2flt(frequency)
  
  return  scaledFrequency
end  

Hey bro. I’ve been dabbling thx to your idea. Working on 2 doofers, one locks a filter cutoff into harmonics from a keytracked base note, the other locks into scale… Harmonics is already hot, but I want odd/even selectable, and also octave repeat or array of harmonics to have less dirt in the upper octaves. The scale lock filter will lock into defined scale like scala file, but don’t have it full on bugfree yet, it works with a 12 semitone octave, but might mess with anything else…

So much for now, merry X-Mas, I want to share what I’ve made to lock tempo into a time measure. This is code for line-synced sample&hold in a formula which I’ve just made, seems to work fine not tested rigorously but I think there’s not much surprise to wait for, tell me if you used it with success, cheers

local time_division = 1/(8*3) -- time discretizer in bars
local beatperbar = 4 -- time measure in beats per bar

--time discretizer
local lastresult = 0.0
local toffset = 0.0
local playstate = nil
local reset = false

function beatnhold(time_division, beatsperbar, cutoff)
  local tcode
  local divlines = LPB*beatperbar*time_division
  if PLAYING == 1 then --playing, sync to pattern start...
    tcode = LINEF
    if playstate ~= true then
      playstate = true
      toffset = 0.0
      reset = true
    end
    if tcode < toffset then --reached pattern border, reset to pattern start
      toffset = 0.0
      reset = true
    end
  else --not playing, keep free running
    tcode = LINEFCOUNTER
    if playstate ~= false then
      playstate = false
      toffset = tcode
      reset = true
    end
    if tcode < toffset then --dunno why this would happen...
      toffset = tcode
      reset = true
    end
  end
  if tcode-toffset > divlines then
    toffset = toffset + divlines*floor((tcode-toffset)/divlines)
    reset = true
  end
  if reset then
    reset = false
    lastresult = discretize_cutoff(cutoff)
  end
  return lastresult
end

So you define the steps like “1/4” is a quarter, “1/8” is an eight note, the “1/(8*3)” is eigth triplets by the way…

Then you must go into the “lastresult = discretize_cutoff” function in the “if reset” block, and use it to update your filter cutoff, i.e. call another function from yourself to update to another note to play back. you can pass the parameters to the “beatnhold” function by adding them to it, and then passing to the reset function.

It will update the effect in a sample&hold fashion, evey x notes, synced to song tempo. It will act free running when not playing, and it will sync itself (i.e. issue a reset) to the pattern start when playback is active. If the time division is changed (i.e. modulated), the code should act fine, i.e. it should always respect the last reset point and reset each time after the currently given time has passed.

Let me know if you have problems with it!

EDIT: sorry posted a borked version at first, hope it should now work…

2 Likes