Code: Select all
asfv1 -p 0 spin-fv1-pitch-detector.txt test.bank
FV-1 Assembler v1.2.7
info: Reading input from spin-fv1-pitch-detector.txt
parse error: S1_14 arg -0x1 out of range for WRLX on line 41
parse error: Expected EQU or MEM but saw OPERATOR & on line 45
parse error: Unexpected OPERATOR & on line 45
scan error: Unrecognised input # on line 45
parse error: Expected EQU or MEM but saw OPERATOR & on line 48
parse error: Unexpected OPERATOR & on line 48
scan error: Unrecognised input # on line 48
parse error: Expected EQU or MEM but saw OPERATOR & on line 63
parse error: Unexpected OPERATOR & on line 63
scan error: Unrecognised input # on line 63
parse error: Expected EQU or MEM but saw OPERATOR & on line 66
too many errors, aborting.
donstavely wrote: ↑Wed Feb 17, 2010 9:32 am 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 ;