Flip flop
Moderator: frank
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
Flip flop
I'm trying to do something kind of like the old analog octave down pedals that generate a square wave, except going several (say 4) octaves down. These, I think, use flip flop circuits to change sign every time a rising edge happens at their input, generating a square wave an octave lower than the input. So I'd like to do something like that, where the square wave is divided in frequency several times.
How do I do the logic? I know from previous threads how to count zero crossings, but how can we either ignore every other zero crossing, or read only positive-going edges?
I plan to iterate this several times, so if there's way to discard 7 out of every 8 zero crossings, without doing intermediary flip-flops, that would be even better.
How do I do the logic? I know from previous threads how to count zero crossings, but how can we either ignore every other zero crossing, or read only positive-going edges?
I plan to iterate this several times, so if there's way to discard 7 out of every 8 zero crossings, without doing intermediary flip-flops, that would be even better.
To avoid using extra flip flops use a counter, logic would be something like (excuse the pseudo code, not in the office to try this)
at start load counter with X (X is number of crossings to skip before inverting flop) and set "flop" to 0
at zero crossing, decrement counter
is counter <= 0?
if yes, invert flop, reload counter with X
if no, do nothing
output flop
at start load counter with X (X is number of crossings to skip before inverting flop) and set "flop" to 0
at zero crossing, decrement counter
is counter <= 0?
if yes, invert flop, reload counter with X
if no, do nothing
output flop
Frank Thomson
Experimental Noize
Experimental Noize
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
So here's what I came up with:
What it's supposed to do is: make an audio rate square wave triggered by zero crossings in the input signal. Then divide that square wave down to an LFO whose pitch is proportional to the input pitch. Then use this square to cut the input on and off, thus creating a square wave tremolo whose speed changes on different notes.
But it doesn't work. What I get out of the output is the input, with some noise on top. It's kind of like a terrible fuzz pedal sound. I know there's got to be some error in the logic, but I can't figure it out. I know you said to load the flop with zero ("square" is the flop here) but I figured that couldn't be right since changing the sign of zero just gives you zero.
Any thoughts?
Code: Select all
equ old_sig reg0
equ counter reg1
equ square reg2
skp run, doit
clr
rdax pot0,1
wrax counter,0 ;load counter with a number. Number is varied by pot0
sof 0,.5
wrax square,0 ;create square wave
doit:
ldax old_sig ; read in saved value
ldax adcr ; read in ADC left, also pushes ACC -> PACC
skp zrc,different ; skip if the signs of ACC and PACC are different
; if here the sign of both old_sig and adcl are the same
wrax old_sig,0 ; save the adcl to old_sig
clr
skp zro,end ; jump over the routine for zero crossing
different:
; if here the signs are different so a zero crossing happened
wrax old_sig,0 ; save the adcl to old_sig
rdax counter,1
sof 1,-.1 ;decrement counter
skp gez,nothing ;if counter is greater than zero, do nothing
rdax square,1 ;if counter is less than zero, flip sign of square
sof -1,0
wrax square,0
sof 0, .7
wrax counter,0
nothing:
wrax counter,0
end:
rdax square,1
SKP GEZ,1 ;make square only positive
CLR ;make square only positive
mulx adcr
wrax dacr,0
But it doesn't work. What I get out of the output is the input, with some noise on top. It's kind of like a terrible fuzz pedal sound. I know there's got to be some error in the logic, but I can't figure it out. I know you said to load the flop with zero ("square" is the flop here) but I figured that couldn't be right since changing the sign of zero just gives you zero.
Any thoughts?
I haven't had the chance to run it but a quick read seems like the logic is sound, a couple things to try:
1. Give the input signal lots of gain, we want to try to "square it up" prior to using it.
2. You said:
A = 0x01000
B = 0x01000
A = A XOR B results in A = 0x00000
If we do it again
A = A XOR B results in A = 0x01000
So if we treat A as the square wave and B as our inversion mask we can flip the value between 0 and 1 easily. This removes the need at the end of your code for the GEZ and forcing a negative value to 0 to have a positive only output. Note that a +/-1 output should also work fine so you can still do the SOF and just output the result directly, again getting rid of the GEZ at the end.
1. Give the input signal lots of gain, we want to try to "square it up" prior to using it.
2. You said:
Actually zero is correct but I failed to explain how to use it, sorry. For things like this I tend to use XOR to invert a bit value. For example:livingston wrote:I know you said to load the flop with zero ("square" is the flop here) but I figured that couldn't be right since changing the sign of zero just gives you zero.
A = 0x01000
B = 0x01000
A = A XOR B results in A = 0x00000
If we do it again
A = A XOR B results in A = 0x01000
So if we treat A as the square wave and B as our inversion mask we can flip the value between 0 and 1 easily. This removes the need at the end of your code for the GEZ and forcing a negative value to 0 to have a positive only output. Note that a +/-1 output should also work fine so you can still do the SOF and just output the result directly, again getting rid of the GEZ at the end.
Frank Thomson
Experimental Noize
Experimental Noize
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
I see what you're saying, and you're right, but low input gain wouldn't make it not work, I think it would just have bad tracking, right? If you do have a chance to try the code it would be a big help. I can't seem to get anywhere with this.frank wrote:I haven't had the chance to run it but a quick read seems like the logic is sound, a couple things to try:
1. Give the input signal lots of gain, we want to try to "square it up" prior to using it.
Give this a try, reads audio in from left and outputs audio on left (clean, no effect) and square wave on right. POT0 varies square wave frequency ratio.
Code: Select all
equ old_sig reg0
equ counter reg1
equ square reg2
equ length reg3
skp run, doit
clr
wrax square,0 ;initialize square wave
doit:
clr
rdax pot0,1 ; read in POT0
wrax length,0 ; load count length with a number. Number is varied by pot0
ldax old_sig ; read in saved value
ldax adcl ; read in ADC left, also pushes ACC -> PACC
skp zrc,different ; skip if the signs of ACC and PACC are different
; if here the sign of both old_sig and adcl are the same
wrax old_sig,0 ; save the adcl to old_sig
skp zro,end ; jump over the routine for zero crossing
different:
; if here the signs are different so a zero crossing happened
wrax old_sig,0 ; save the adcl to old_sig
rdax counter,1 ; read in the counter
sof 1,-.2 ;decrement counter
skp gez,nothing ;if counter is greater than zero, do nothing
clr
rdax square,1 ;if counter is less than zero, flip sign of square
xor 0x7fffff
wrax square,0 ; save the inverted square
rdax length,1.0 ; read in the counter reload value
nothing:
wrax counter,0 ; save the counter value
end:
rdax square,1 ; read the square wave
wrax dacr,0 ; output square wave on DAC right
rdax adcl, 1.0 ; read in audio from ADC left
wrax dacl, 1 ; Output audio on DAC left
Frank Thomson
Experimental Noize
Experimental Noize
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
Aha, yes I needed that clear the counter before creating the square wave. And the addition of the Length register is probably important, though I'm not sure I understand precisely what it's for. I guess it's not good to write a pot directly to the counter?
BTW, the program as you've got it there makes a very nice little square wave octave synth effect. Just tack the input envelope onto that square wave and maybe a filter on the end.
BTW, the program as you've got it there makes a very nice little square wave octave synth effect. Just tack the input envelope onto that square wave and maybe a filter on the end.
Habit, normally I would have done things like limited the range of the pot or made it an exponential sweep or ??? So I would save the result in a reg then use that where necessary. But if you want to use the raw pot value there is nothing wrong with doing that if it fits the program.livingston wrote:And the addition of the Length register is probably important, though I'm not sure I understand precisely what it's for. I guess it's not good to write a pot directly to the counter?
Hmmm, may try to play with that later. I developed the program using a function generator and a scope to watch the signals to make sure it was working properly so really haven't listened to it.livingston wrote:BTW, the program as you've got it there makes a very nice little square wave octave synth effect. Just tack the input envelope onto that square wave and maybe a filter on the end.
Frank Thomson
Experimental Noize
Experimental Noize
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
So how would we do a multiplier instead of divider? I don't need actual code, just having a hard time coming up with the conceptual basis.
If we keep the zero crossing routine, and every time there's a zero crossing, we flip the phase twice, I suppose that would give an octave up, but the positive pulse would have the same width no matter what the input pitch, which might sound weird.
Maybe the easiest way to do this in the FV-1 is to just use the pitch shifter algo, do it a few times to give 3 or 4 octaves up (quality of audio won't matter since we're converting to a square wave), then divide down as much as we want. The pitch shift's delay might get too bad iterating it that much though.
If we keep the zero crossing routine, and every time there's a zero crossing, we flip the phase twice, I suppose that would give an octave up, but the positive pulse would have the same width no matter what the input pitch, which might sound weird.
Maybe the easiest way to do this in the FV-1 is to just use the pitch shifter algo, do it a few times to give 3 or 4 octaves up (quality of audio won't matter since we're converting to a square wave), then divide down as much as we want. The pitch shift's delay might get too bad iterating it that much though.
A digital PLL is a typical way to do a multiplier. It will lag a little and it won't respond as fast to changes on the input as the divide does but it should have less delay than the pitch shift algo.
Frank Thomson
Experimental Noize
Experimental Noize
When you cross zero going up, you output a pulse of a fixed width. When it crosses zero going down, you output another pulse... this effectively doubles the frequency. I've made this with cmos chips and it works but the sound will be somewhat synth-like.livingston wrote:So how would we do a multiplier instead of divider? I don't need actual code, just having a hard time coming up with the conceptual basis.
regards, Jack
-
- Posts: 131
- Joined: Sun Nov 15, 2009 3:37 pm
- Location: New Orleans, LA US
Right, that's what I was getting at here, though it may not have been clear:
So the width of the pulse would have to be set in the code, I think, which would be strange since in a regular pulse wave, the proportion between high and low is the same at any frequency, whereas here, low notes would have very narrow pulse width, approaching 100% duty cycle on the lowest notes.livingston wrote: If we keep the zero crossing routine, and every time there's a zero crossing, we flip the phase twice, I suppose that would give an octave up, but the positive pulse would have the same width no matter what the input pitch, which might sound weird.
The high E string at the 12th fret of a guitar is 660Hz (approx). This means that each wave cycle takes 1.5 ms.livingston wrote:So the width of the pulse would have to be set in the code, I think, which would be strange since in a regular pulse wave, the proportion between high and low is the same at any frequency, whereas here, low notes would have very narrow pulse width, approaching 100% duty cycle on the lowest notes.
So if we output a pulse of 1.2 ms then we have an "on" time of around 80% of the cycle.
The low E note on the guitar is 82 Hz with a cycle taking 12.2 ms. A 1.2 ms pulse is "on" about 10% of the time.
We have a pulse width that is varying from 10% to 80%, and that's not too bad. What changes is the harmonics of the sound... 50% duty cycle is woody sounding while a narrow duty cycle is more string-like. There were string synths back in the day of top-octave-dividers that used narrow pulses for string synth sounds. An 80% duty cycle and a 20% will sound much the same.
None of them sound bad and it might even give a more realistic quality with different pulse widths. Varying the duty cycle sounds a lot like a filter opening and closing since the harmonics are changing.
A 2.4 ms wave will be 50% duty cycle and this is very close to G#4 - high E guitar string's 4th fret.
Note to Frequency calculator: http://www.muzique.com/schem/freq.htm
regards, Jack