Any thoughts on implementing an "infinite hold" ef
Moderator: frank
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
Any thoughts on implementing an "infinite hold" ef
This is really just meant to get some creative thinking happening. The HOG by Electro Harmonix allows you to freeze a note or chord, so that it plays infinitely, and glissando into new notes or chords played. The freeze is not a simple 100% feedback delay, it doesn't repeat the attack and decay phase, just sustains infinitely.
I assume this is being done with FFT, which is probably outside the capability of the FV-1.
But is there any way to do a freeze of all current frequencies, then on some trigger (footswitch or the attack of a new note) blend between the old note and the new one? I think an actual pitch glissando would be asking too much here, but I think just a volume fade between old and new notes would be fine. The hard part is the freeze without sounding like a repeating delay.
I assume this is being done with FFT, which is probably outside the capability of the FV-1.
But is there any way to do a freeze of all current frequencies, then on some trigger (footswitch or the attack of a new note) blend between the old note and the new one? I think an actual pitch glissando would be asking too much here, but I think just a volume fade between old and new notes would be fine. The hard part is the freeze without sounding like a repeating delay.
-
- Posts: 53
- Joined: Thu Jan 07, 2010 2:29 pm
- Location: Windsor, Colorado
Maybe I am not understanding your intent, but I am thinking it would be easier to do in the time domain on the FV-1.
To do the sustain, you could set up two delay memories and toggle/pan between them, just like you would set up to do pitch shifting. You could switch from live to delay memory as the envelop falls below a threshold. (Pan this transition too to void transients.)
Don't know how to do a real glissando, but you could at least do a soft pan from the sustain memory back to the live next note, rather that a hard switch back to live on the envelope threshold. This might sound pretty cool.
If you could figure out whether the next note(s) were going up or going down in pitch, you could start a pitch shift in the delay memory in the right direction, then pan to the live input. This might give a pretty reasonable facsimile of a glissando.
I can't think of a way to get the "pitch up", "pitch down", or "pitch the same" indication to drive the sustain/pitch-shift/pan-to-live transition. Pitch detection in general is hard, and with cords is REALLY hard. (I have done some work in this area.) The up/down/same detection should be much easier.
If this line of thought is interesting to you, I will give it more thought.
To do the sustain, you could set up two delay memories and toggle/pan between them, just like you would set up to do pitch shifting. You could switch from live to delay memory as the envelop falls below a threshold. (Pan this transition too to void transients.)
Don't know how to do a real glissando, but you could at least do a soft pan from the sustain memory back to the live next note, rather that a hard switch back to live on the envelope threshold. This might sound pretty cool.
If you could figure out whether the next note(s) were going up or going down in pitch, you could start a pitch shift in the delay memory in the right direction, then pan to the live input. This might give a pretty reasonable facsimile of a glissando.
I can't think of a way to get the "pitch up", "pitch down", or "pitch the same" indication to drive the sustain/pitch-shift/pan-to-live transition. Pitch detection in general is hard, and with cords is REALLY hard. (I have done some work in this area.) The up/down/same detection should be much easier.
If this line of thought is interesting to you, I will give it more thought.
Don Stavely
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
Hmm, interesting ideas. I think that doing it with a repeating delay will create a bit of a tremulous sound, but it's not too bad a compromise. The "fake glissando", which is a pitch shift in the right direction with a pan, is actually I think what's going on in the HOG.
I really appreciate that response, and I'm going to read it a few more times and think about translating it to code. I would definitely be interested in any more thoughts you might have on this.
I really appreciate that response, and I'm going to read it a few more times and think about translating it to code. I would definitely be interested in any more thoughts you might have on this.
-
- Posts: 53
- Joined: Thu Jan 07, 2010 2:29 pm
- Location: Windsor, Colorado
I haven't had a chance to do any real coding, but I have thought a lot about the "pitch metric" problem. I call it a pitch metric rather than true pitch detection because we need a relative measure of pitch from note to note or cord to cord, but trying to extract pitches from cords is too hard. I am interested in this function because I want to play with sweepable filters that roughly track notes on guitar.
What I will do is low-pass filter the input to get rid of some of the harmonics, then clip to square waves, then integrate to triangle waves (whose amplitude now varies inversely with frequency.) Then envelope-detect this and invert it for pitch.
Of course, this metric will also vary with the decay of harmonics, not just pitch of the fundamental(s). But it should be valid to compare at the same time of the attack envelope from note to note. So we have to envelope-detect the original input, and save the pitch metric near the peak. (You needed th envelope-detect the input for the rest of the sustain effect anyway.) This saved metric value is what we compare to the metric at the peak of the next note, to see if the pitch is going up or down for the glissando. (Remember that we had the inverse of pitch, and needed to invert it, so doing the ratio of last note to current note just requires a multiply of one note with the inverse of the other.)
This may sound convoluted, but it is the best thought I have had so far. I am hoping to try it out this weekend. I will keep you posted.
What I will do is low-pass filter the input to get rid of some of the harmonics, then clip to square waves, then integrate to triangle waves (whose amplitude now varies inversely with frequency.) Then envelope-detect this and invert it for pitch.
Of course, this metric will also vary with the decay of harmonics, not just pitch of the fundamental(s). But it should be valid to compare at the same time of the attack envelope from note to note. So we have to envelope-detect the original input, and save the pitch metric near the peak. (You needed th envelope-detect the input for the rest of the sustain effect anyway.) This saved metric value is what we compare to the metric at the peak of the next note, to see if the pitch is going up or down for the glissando. (Remember that we had the inverse of pitch, and needed to invert it, so doing the ratio of last note to current note just requires a multiply of one note with the inverse of the other.)
This may sound convoluted, but it is the best thought I have had so far. I am hoping to try it out this weekend. I will keep you posted.
Don Stavely
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
-
- Posts: 53
- Joined: Thu Jan 07, 2010 2:29 pm
- Location: Windsor, Colorado
A square wave switches from a constant positive value to a constant negative value and back. If you integrate this, you get a signal that ramps positive, then ramps negative at the same rate. If the square wave amplitude is constant due to the clipping, the ramp rate (slope) will be constant. If the period of the square wave is short, you only ramp up for a short time, then ramp down, and so on. So the triangle wave is relatively low amplitude. But if the period of the square wave is long, it ramps up at that same slope for longer before it ramps down again. So the triangle wave is higher amplitude. If fact the amplitude will be directly proportional to the period, and so inversely proportional to frequency.
An integrator in the analog world is just an accumulator in the digital world - i.e. a register that get the (scaled) input signal added to it each pass. You would just use a low-pass filter with a cutoff below the frequencies of interest, like 20Hz or so. A single-pole low-pass filter and a "leaky integrator" are exactly the same thing, and have the same effect on a signal. This is another way to look at it. If the frequency of the input signal is above the cutoff frequency, then we are "operating on the slope" of the filter. The higher the frequency, the lower the amplitude. the lower the frequency, the higher the amplitude (assuming we are still above the cutoff) just as described above.
So at this point, we have a triangle wave whose amplitude varies with the frequency of the original signal. It does NOT vary with the amplitude of that original signal, because we clipped the hell out of it into the square wave before we integrated (LP filtered) it.
Then we envelope detect, to go from an AC signal to a positive only signal that rises and falls with the amplitude of the triangle wave. The next steps are described in the previous post.
An integrator in the analog world is just an accumulator in the digital world - i.e. a register that get the (scaled) input signal added to it each pass. You would just use a low-pass filter with a cutoff below the frequencies of interest, like 20Hz or so. A single-pole low-pass filter and a "leaky integrator" are exactly the same thing, and have the same effect on a signal. This is another way to look at it. If the frequency of the input signal is above the cutoff frequency, then we are "operating on the slope" of the filter. The higher the frequency, the lower the amplitude. the lower the frequency, the higher the amplitude (assuming we are still above the cutoff) just as described above.
So at this point, we have a triangle wave whose amplitude varies with the frequency of the original signal. It does NOT vary with the amplitude of that original signal, because we clipped the hell out of it into the square wave before we integrated (LP filtered) it.
Then we envelope detect, to go from an AC signal to a positive only signal that rises and falls with the amplitude of the triangle wave. The next steps are described in the previous post.
Don Stavely
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
Wow, it's interesting because this is completely different from the way I would've tried to solve this, but your idea is a lot more fleshed out than mine would be before putting together code.
So the code would go something like
I haven't tried this code yet and the filter coefficients, etc. have not been figured at all, just placeholder numbers. Here I'm just trying to think about your idea and how it would translate into FV-1 code.
Is that close to what you were thinking?
So the code would go something like
Code: Select all
rdax adcr,1 ;read input
RDFX reg0,0.001 ;filter harmonics
WRLX reg0,-1 ;infinite shelf LPF
sof -2,0 ;amplify to clipping
sof -2,0
sof -2,0
sof -2,0
sof -2,0
sof -2,0
rdax integrate,1 ;add current signal to previous integrator value
wrax integrate,1 ;overwrite previous integrator value
RDFX reg0,0.001 ;filter with LPF cutoff below audio frequencies
WRLX reg0,-1 ;infinite shelf LPF
absa ;rectify
RDFX reg0,0.001 ;filter to get envelope
WRLX reg0,-1 ;
sof -1,.999 ;invert pitch
Is that close to what you were thinking?
-
- Posts: 53
- Joined: Thu Jan 07, 2010 2:29 pm
- Location: Windsor, Colorado
I think you are on the right track, with two exceptions:
- You have a pure integrator followed by the sub-audio low-pass filter, which is also acting as a "leaky integrator". You only want one of these to convert the square into the triangle. I was just trying to make the point that a leaky integrator and a low-pass filter can be one and the same, and are just two different ways of looking at the same function. You don't actually want a pure integrator, because it will drift up and down with any long-term mismatch in duty cycle of the square wave. So nix the two lines with the "integrate" variable.
- At the end, when I said we need to invert the period envelope signal to get frequency, I meant using the 1/X function, rather than negation. Sorry, I should have been clear on this point.
Now it should make more sense when I said that we have everything we need to get the frequency ratio of previous note to current note, since we have both F (frequency, from 1/period) and 1/F (period, from before the 1/X function). If we saved period (1/F) from the previous note, then we can just multiply by F (freq) from the current note to get the ratio of past to present pitches to decide if we pitch-shift up or down for the glissando. (You have to be careful about scaling when using the 1/X function, as described in the Knowledge Base.)
As you work forward through this next part of the process, feel free to keep asking questions.
- You have a pure integrator followed by the sub-audio low-pass filter, which is also acting as a "leaky integrator". You only want one of these to convert the square into the triangle. I was just trying to make the point that a leaky integrator and a low-pass filter can be one and the same, and are just two different ways of looking at the same function. You don't actually want a pure integrator, because it will drift up and down with any long-term mismatch in duty cycle of the square wave. So nix the two lines with the "integrate" variable.
- At the end, when I said we need to invert the period envelope signal to get frequency, I meant using the 1/X function, rather than negation. Sorry, I should have been clear on this point.
Now it should make more sense when I said that we have everything we need to get the frequency ratio of previous note to current note, since we have both F (frequency, from 1/period) and 1/F (period, from before the 1/X function). If we saved period (1/F) from the previous note, then we can just multiply by F (freq) from the current note to get the ratio of past to present pitches to decide if we pitch-shift up or down for the glissando. (You have to be careful about scaling when using the 1/X function, as described in the Knowledge Base.)
As you work forward through this next part of the process, feel free to keep asking questions.
Don Stavely
-
- Posts: 53
- Joined: Thu Jan 07, 2010 2:29 pm
- Location: Windsor, Colorado
Livingston, I don't know if you are still interested in this thread, but I coded up and tested the pitch detection algorithm I previously proposed. It was a complete bust, at least on guitar waveforms as inputs. (There was another thread about pitch detection, also taking the zero-crossing route.)
I went back and coded up an algorithm that I implemented in analog hardware a little while ago. Here is the explanation in the code header:
; This pitch detection routine is a firmware version of the analog technique used in
; the Boss Octave OC-2 pedal and Ray Wilson's Sub-Commander guitar synthesizer.
; Positive and negative envelope followers are compared to the input to detect the
; positive and negative peaks of a complex waveform.
; These are used to set and reset a flip-flop with the same period as the input.
; A linear ramp generator is captured and reset by rising edges, generating the
; period. It is then filtered to smooth duty cycle glitches.
; While it may seem more convoluted than it needs to be, the complexity is necessary
; to handle a guitar input. A plucked guitar string waveform contains harmonics
; that "roll through" the fundamental, causing multiple, shifting peaks.
; Simple zero-crossing or peak detection cannot reliably detect the period of such
; a complex waveform.
It is actually quite robust. The downside is that it take 30 instructions, almost a quarter of the FV-1 power. It is only accurate for single-note detection, of course.
If you are interested, I will post the code after a little more testing and tuning.
I went back and coded up an algorithm that I implemented in analog hardware a little while ago. Here is the explanation in the code header:
; This pitch detection routine is a firmware version of the analog technique used in
; the Boss Octave OC-2 pedal and Ray Wilson's Sub-Commander guitar synthesizer.
; Positive and negative envelope followers are compared to the input to detect the
; positive and negative peaks of a complex waveform.
; These are used to set and reset a flip-flop with the same period as the input.
; A linear ramp generator is captured and reset by rising edges, generating the
; period. It is then filtered to smooth duty cycle glitches.
; While it may seem more convoluted than it needs to be, the complexity is necessary
; to handle a guitar input. A plucked guitar string waveform contains harmonics
; that "roll through" the fundamental, causing multiple, shifting peaks.
; Simple zero-crossing or peak detection cannot reliably detect the period of such
; a complex waveform.
It is actually quite robust. The downside is that it take 30 instructions, almost a quarter of the FV-1 power. It is only accurate for single-note detection, of course.
If you are interested, I will post the code after a little more testing and tuning.
Don Stavely
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
Yeah, would love to see the code. I was thinking of adding this to a Slow Gear kind of thing (pretty easy to do in the FV-1) plus an expander (just envelope detect then MULX input with its own envelope) to get a whole synth-style ADSR kind of thing for guitar or bass. But I haven't had time to really dig into it.
-
- Posts: 53
- Joined: Thu Jan 07, 2010 2:29 pm
- Location: Windsor, Colorado
Here is the code for the guitar pitch period detect. I followed it with a sine wave VCO whose frequency is driven by the detector, shifted in pitch, and with the original envelope put back on it. A very weird effect, but it demonstrates that things are basically working.
Code: Select all
; This pitch detection routine is a firmware version of the analog technique used in
; the Boss Octave OC-2 pedal and Ray Wilson's Sub-Commander guitar synthesizer.
; Positive and negative envelope followers are compared to the input to detect the
; positive and negative peaks of a complex waveform.
; These are used to set and reset a flip-flop with the same period as the input.
; A linear ramp generator is captured and reset by rising edges, generating the
; period. It is then filtered to smooth duty cycle glitches.
; While it may seem more convoluted than it needs to be, the complexity is necessary
; to handle a guitar input. A plucked guitar string waveform contains harmonics
; that "roll through" the fundamental, causing multiple, shifting peaks.
; Simple zero-crossing or peak detection cannot reliably detect the period of such
; a complex waveform.
;
equ in reg0 ; input
;equ lpin reg1 ; filtered input
equ posenv reg2 ; positive envelope follower
equ negenv reg3 ; negative envelope follower
equ square reg4 ; pitch detected square wave
equ ramp reg5 ; 1-e^kt ramp from 0 to aproaching 1
equ period reg6 ; log of period, due to nonlinear ramp
equ avper reg7 ; filtered period
;
; Read A/D's and save input
;
rdax adcl, 0.5 ; read and scale left A/D
rdax adcr, 0.5 ; read and scale right A/D
wrax in, 0 ; save input for later, clear ACC
;
; Get positive envelope and set square wave on positive peaks
;
rdax posenv, 0.9985 ; get positive envelope, a little smaller
wrax posenv, -1.0015 ; save decaying, keep neg full value
rdax in, 1 ; add input, leave in ACC for test
skp neg, NoPosPeak ; is input > positive envelope?
; Yes, this is a positive peak
ldax square ; test current square state
skp gez, PosAlrdy ; was it negative?
ldax ramp ; yes, this is the first pos peak
wrax period, 1 ; so capture period, leave in ACC
rdfx avper, 0.4 ; filter to average out the period
wrlx avper, -1 ; infinite shelf LPF
ldax in ; let's use the peak for the square
wrax square, 0 ; set square positive clear ACC
wrax ramp, 0 ; and save to reset period ramp
PosAlrdy: ; input > positive envelope
ldax in ; get input (ACC not clear after skp)
wrax posenv, 0 ; save as new envelope
NoPosPeak: ; done handling positive peaks
clr ; clear ACC from skp
;
; Get negative envelope and reset square wave on negative peaks
;
rdax negenv, 0.9985 ; get negative envelope, a little smaller
wrax negenv, -1.0015 ; save decaying, keep neg full value
rdax in, 1 ; add input, leave in ACC for test
skp gez, NoNegPeak ; is input < negative envelope?
; Yes, this is a negative peak
ldax square ; test current square state
skp neg, NegAlrdy ; was it positive?
; yes, this was first neg peak
ldax in ; let's use the peak for the square
wrax square, 0 ; set square negative
NegAlrdy: ; input < negative envelope
ldax in ; get input (ACC not clear after skp)
wrax negenv, 0 ; save as new envelope
NoNegPeak: ; done handling negative peaks (ACC not clear)
;
; Update ramp to finish
;
sof 0, 0.001 ; get a small value
rdax ramp, 1 ; add it to the ramp
wrax ramp, 0 ; save it
;
; End of pitch detection
;
equ freq reg10 ; frequency, 1/period
equ sine reg11 ; sine integrator
equ cosine reg12 ; cosine integrator
equ envfil reg13 ; envelope filter
equ out reg13 ; output
;
; Sine VCO to demonstrate pitch detection
;
skp run, SineOn ; need to kick-start oscillator
sof 0, 0.99 ; amplitude
wrax sine, 0 ; save in one integrator
SineOn:
;
; Need to convert period to frequency
;
rdax avper, 1 ; get smoothed period
log -1, -0.49 ; need 1/X, the offset scales frequency
exp 1, 0 ; linear frequency
wrax freq, 0 ; save it
;
; Here is the oscillator, as described in the Knowledge Base
;
rdax sine, -1
mulx freq
rdax cosine, 1
wrax cosine, 1
mulx freq
rdax sine, 1
wrax sine, 1
;
mulx posenv ; put an envelope on it
wrax out, 0 ; sine wave with original envelope
;
; Write debug values
;
rdax square, 1 ; this is the pitch detector digital wave
wrax dacl, 0 ;
rdax out, 1 ; this is a reconstructed, shifted sine wave
wrax dacr, 0 ;
Don Stavely
-
- Posts: 74
- Joined: Mon Sep 11, 2006 10:04 pm
Re: Any thoughts on implementing an "infinite hold"
Take any of the existing reverb programs, and set the feedback gain to 1. Infinite reverb results. It won't sound like a repeating delay, due to the diffusion (allpasses) within the reverb network.livingston wrote: But is there any way to do a freeze of all current frequencies, then on some trigger (footswitch or the attack of a new note) blend between the old note and the new one? I think an actual pitch glissando would be asking too much here, but I think just a volume fade between old and new notes would be fine. The hard part is the freeze without sounding like a repeating delay.
If you wanted to control this with a footswitch, you could use something that sends the maximum voltage to one of the pot inputs, and use this to calculate the reverb time. A SPDT switch would allow you to select between a reverb time pot and a fixed voltage.
Miller Puckette has shown how to use an envelope detector to control the input gain and decay time of a reverb, in order to get automatic infinite sustain without any attack sound:
http://crca.ucsd.edu/~msp/techniques/la ... de112.html
Hope this is useful.
Sean Costello
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
-
- Posts: 53
- Joined: Thu Jan 07, 2010 2:29 pm
- Location: Windsor, Colorado
cant reply
I have tried to reply to a private message, but the replies remain in my "outbox", not the "sentbox", so I assume they didn't get sent. Any suggestions?
Don Stavely