Any thoughts on implementing an "infinite hold" ef

Algorithm development and general DSP issues

Moderator: frank

livingston
Posts: 131
Joined: Sun Nov 15, 2009 3:37 pm
Location: New Orleans, LA US

Any thoughts on implementing an "infinite hold" ef

Post by livingston »

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.
donstavely
Posts: 53
Joined: Thu Jan 07, 2010 2:29 pm
Location: Windsor, Colorado

Post by donstavely »

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.
Don Stavely
livingston
Posts: 131
Joined: Sun Nov 15, 2009 3:37 pm
Location: New Orleans, LA US

Post by livingston »

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.
donstavely
Posts: 53
Joined: Thu Jan 07, 2010 2:29 pm
Location: Windsor, Colorado

Post by donstavely »

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.
Don Stavely
livingston
Posts: 131
Joined: Sun Nov 15, 2009 3:37 pm
Location: New Orleans, LA US

Post by livingston »

Really interesting, though it's a little bit over my head. I'm following you through filtering and clipping, but I'm not sure how you can turn a square into a triangle in such a way that amplitude varies with input frequency.

I'll be interested to hear about your results.
donstavely
Posts: 53
Joined: Thu Jan 07, 2010 2:29 pm
Location: Windsor, Colorado

Post by donstavely »

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.
Don Stavely
livingston
Posts: 131
Joined: Sun Nov 15, 2009 3:37 pm
Location: New Orleans, LA US

Post by livingston »

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

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
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?
donstavely
Posts: 53
Joined: Thu Jan 07, 2010 2:29 pm
Location: Windsor, Colorado

Post by donstavely »

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.
Don Stavely
donstavely
Posts: 53
Joined: Thu Jan 07, 2010 2:29 pm
Location: Windsor, Colorado

Post by donstavely »

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.
Don Stavely
livingston
Posts: 131
Joined: Sun Nov 15, 2009 3:37 pm
Location: New Orleans, LA US

Post by livingston »

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.
jovesdies
Posts: 33
Joined: Wed Feb 25, 2009 3:55 am

Post by jovesdies »

yeah, Donstavely, post it, post it !!
donstavely
Posts: 53
Joined: Thu Jan 07, 2010 2:29 pm
Location: Windsor, Colorado

Post by donstavely »

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
seancostello
Posts: 74
Joined: Mon Sep 11, 2006 10:04 pm

Re: Any thoughts on implementing an "infinite hold"

Post by seancostello »

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.
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.

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
livingston
Posts: 131
Joined: Sun Nov 15, 2009 3:37 pm
Location: New Orleans, LA US

Post by livingston »

2 excellent posts, lots to digest. Thanks guys!
donstavely
Posts: 53
Joined: Thu Jan 07, 2010 2:29 pm
Location: Windsor, Colorado

cant reply

Post by donstavely »

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
Post Reply