Reducing the tremolo artefact from pitch shifting
Moderator: frank
Reducing the tremolo artefact from pitch shifting
Will the following idea work?
Send signal to be shifted down two parallel paths.
Each path has a delay line (of length D) for pitch-shifting, but the ramp LFOs on those lines are offset in time by a suitable fraction of the line length (I am guessing D/4).
The idea being that peaks of the tremolo (or pitch warble) artefacts in one path coincide with troughs of the artefacts in the other line.
I am guessing its possible to use the JAM instruction to zero RMP1 when RMP0 reaches some particular level, and then set a flag indicating not to do that zero-ing again.
Has this been tried before?
If it's feasible then what condition should be checked in order to get D/4 offset. Can I assume that an increasing ramp will always go from 0 to 1, and a decreasing ramp will always got from 1 to 0. i.e. just check if RMP level is 0.25 (or 0.75) to trigger the JAM ?
Send signal to be shifted down two parallel paths.
Each path has a delay line (of length D) for pitch-shifting, but the ramp LFOs on those lines are offset in time by a suitable fraction of the line length (I am guessing D/4).
The idea being that peaks of the tremolo (or pitch warble) artefacts in one path coincide with troughs of the artefacts in the other line.
I am guessing its possible to use the JAM instruction to zero RMP1 when RMP0 reaches some particular level, and then set a flag indicating not to do that zero-ing again.
Has this been tried before?
If it's feasible then what condition should be checked in order to get D/4 offset. Can I assume that an increasing ramp will always go from 0 to 1, and a decreasing ramp will always got from 1 to 0. i.e. just check if RMP level is 0.25 (or 0.75) to trigger the JAM ?
Re: Reducing the tremolo artefact from pitch shifting
It works !!! (EDIT: Well no it doesn't. See below).
I did an octave-up test and got big improvement, especially in the higher pitches,
when compared to case when the two lines have ramps with the same phase.
My ramp adjustment code assumes the ramps are decreasing (i.e. upward pitch shift),
so would need adjusting to handle the case when the ramps are increasing (i.e. down pitch shift).
Would be interested if it can be done with fewer instructions.
I did an octave-up test and got big improvement, especially in the higher pitches,
when compared to case when the two lines have ramps with the same phase.
My ramp adjustment code assumes the ramps are decreasing (i.e. upward pitch shift),
so would need adjusting to handle the case when the ramps are increasing (i.e. down pitch shift).
Would be interested if it can be done with fewer instructions.
Code: Select all
MEM tmp 1 ; Temp memory for octave-up routines
MEM octave1 4096 ; Delay line for octave-up
MEM octave2 4096 ; Delay line for octave-up
EQU adjust_ramps REG0 ; Stop adjusting RMPs when this flag goes negative
EQU lp_antialias REG1 ; Anti-alias LPF before octave up
EQU octaveOut1 REG2
EQU octaveOut2 REG3
;-------------- Initialize LFOs etc -------------------
SKP RUN,end_init
WLDR RMP0,16384,4096 ; Ramp LFO for octave1
WLDR RMP1,16384,4096 ; Ramp LFO for octave2
JAM RMP0 ; Not sure resetting RMP0 is required
JAM RMP1 ; Not sure resetting RMP1 is required
CLR
WRAX adjust_ramps,0 ; Initialise the "adjust_ramps" flag
end_init:
;-------------------------------------------------
;--------------- Ramp adjustment ------------------
; After the first tick, both ramps should go high and
; then start to decrease towards 0.
; We'll keep resetting RMP1 so long as RMP0 is above 0.25
RDAX adjust_ramps,1 ; Read the "adjust_ramps" flag ...
SKP neg,done ; ... if it's negative, then we're done adjusting the RMPs
RDAX RMP0,1 ; Read RMP0...
SKP zro,done ; ... and if its zero then we must be at start up, so do nothing
SOF 0,-0.25 ; else
SKP gez,reset_rmp1 ; ... if RMP0 >= 0.25, then reset RMP1
WRAX adjust_ramps,1 ; else set the "adjust_ramps" flag to negative
SKP neg,done
reset_rmp1:
JAM RMP1
CLR
done:
;-------------------------------------------------
;---------- Take average of L and R inputs -----------
RDAX ADCL,0.5
RDAX ADCR,0.5
;-------------------------------------------------
;--------- Anti-alias LPF before the octave up ---------
; We don't want doubling pitch to give a tone above 16kHz
RDFX lp_antialias, 0.792; ; 8192Hz ==> 1 - exp(-2*pi*8192/32768)
WRAX lp_antialias, 1
WRA octave1,1 ; Write to octave1
WRA octave2,0 ; Write to octave2
;-------------------------------------------------
;------------- Octave up 1 ------------------------
CHO RDA,RMP0,REG|COMPC,octave1
CHO RDA,RMP0,,octave1+1
WRA tmp,0
CHO RDA,RMP0,RPTR2|COMPC,octave1
CHO RDA,RMP0,RPTR2,octave1+1
CHO SOF,RMP0,NA|COMPC,0
CHO RDA,RMP0,NA,tmp
WRAX octaveOut1,0
;-------------------------------------------------
;------------- Octave up 2 ------------------------
CHO RDA,RMP1,REG|COMPC,octave2
CHO RDA,RMP1,,octave2+1
WRA tmp,0
CHO RDA,RMP1,RPTR2|COMPC,octave2
CHO RDA,RMP1,RPTR2,octave2+1
CHO SOF,RMP1,NA|COMPC,0
CHO RDA,RMP1,NA,tmp
WRAX octaveOut2,0
;-------------------------------------------------
;--------------- Make output signal -----------------
RDAX octaveOut1,0.5
RDAX octaveOut2,0.5
WRAX DACL,0
Last edited by DrAlx on Thu Mar 28, 2019 4:26 pm, edited 1 time in total.
Re: Reducing the tremolo artefact from pitch shifting
The same trick doesn't seem to work for octave down though !!!
I found the octave down effect was weaker and lots of "unshifted" signal seemed to
get through to the output somehow, and this was often stronger than the octave down.
I don't know if this was a coding error and the ramps were not being offset correctly,
or if I am missing some fundamental point that would say this trick won't work for octave down.
Code included anyway for reference...
I found the octave down effect was weaker and lots of "unshifted" signal seemed to
get through to the output somehow, and this was often stronger than the octave down.
I don't know if this was a coding error and the ramps were not being offset correctly,
or if I am missing some fundamental point that would say this trick won't work for octave down.
Code included anyway for reference...
Code: Select all
MEM tmp 1 ; Temp memory for detune and octave-down routines
MEM octave1 4096 ; Delay line for octave-down
MEM octave2 4096 ; Delay line for octave-down
EQU adjust_ramps REG0 ; Stop adjusting RMPs when this flag goes >=0
EQU octaveOut1 REG2
EQU octaveOut2 REG3
;-------------- Initialize LFOs etc -------------------
SKP RUN,end_init
WLDR RMP0,-8192,4096 ; Ramp LFO for octave1
WLDR RMP1,-8192,4096 ; Ramp LFO for octave2
JAM RMP0 ; Not sure resetting RMP0 is required
JAM RMP1 ; Not sure resetting RMP1 is required
SOF 0,-0.5
WRAX adjust_ramps,0 ; Initialise "adjust_ramps" flag to < 0
end_init:
;-------------------------------------------------
;--------------- Ramp adjustment ------------------
; We'll keep resetting RMP1 so long as RMP0 is below 0.25
RDAX adjust_ramps,1 ; Read the "adjust_ramps" flag ...
SKP gez,done ; ... if >= 0, then we're done adjusting the RMPs
RDAX RMP0,1 ; Read RMP0...
SOF 0,-0.25 ;
SKP neg,reset_rmp1 ; ... if RMP0 < 0.25, then reset RMP1
WRAX adjust_ramps,1 ; else set the "adjust_ramps" flag to >= 0
SKP gez,done
reset_rmp1:
JAM RMP1
CLR
done:
;-------------------------------------------------
;---------- Take average of L and R inputs -----------
RDAX ADCL,0.5
RDAX ADCR,0.5
WRA octave1,1 ; Write to octave1
WRA octave2,0 ; Write to octave2
;-------------------------------------------------
;------------- Octave down 1 ------------------------
CHO RDA,RMP0,REG|COMPC,octave1
CHO RDA,RMP0,,octave1+1
WRA tmp,0
CHO RDA,RMP0,RPTR2|COMPC,octave1
CHO RDA,RMP0,RPTR2,octave1+1
CHO SOF,RMP0,NA|COMPC,0
CHO RDA,RMP0,NA,tmp
WRAX octaveOut1,0
;-------------------------------------------------
;------------- Octave down 2 ------------------------
CHO RDA,RMP1,REG|COMPC,octave2
CHO RDA,RMP1,,octave2+1
WRA tmp,0
CHO RDA,RMP1,RPTR2|COMPC,octave2
CHO RDA,RMP1,RPTR2,octave2+1
CHO SOF,RMP1,NA|COMPC,0
CHO RDA,RMP1,NA,tmp
WRAX octaveOut2,0
;-------------------------------------------------
;--------------- Make output signal -----------------
RDAX octaveOut1,0.5
RDAX octaveOut2,0.5
WRAX DACL,0
Re: Reducing the tremolo artefact from pitch shifting
Actually just tested the octave up again (on my electric guitar instead of my acoustic) and the tremolo is still there, just double the rate.
Not sure why it seemed less noticeable originally.
I think staggering the ramps as I am doing means I'm effectively reading the signal twice along the delay line but not cross fading in any way.
Oh well. Was worth a shot.
Not sure why it seemed less noticeable originally.
I think staggering the ramps as I am doing means I'm effectively reading the signal twice along the delay line but not cross fading in any way.
Oh well. Was worth a shot.
Re: Reducing the tremolo artefact from pitch shifting
You can improve it by diffusion. Something like this diffuser from Dattorro.
;------ Diffuser
LDAX REG1
RDA 4255,-0.75
WRAP 4099,0.75
RDA 4373,-0.75
WRAP 4256,0.75
RDA 4791,-0.625
WRAP 4374,0.625
RDA 5097,-0.625
WRAP 4792,0.625
WRAX REG2,0.0000000000
;------ Diffuser
LDAX REG1
RDA 4255,-0.75
WRAP 4099,0.75
RDA 4373,-0.75
WRAP 4256,0.75
RDA 4791,-0.625
WRAP 4374,0.625
RDA 5097,-0.625
WRAP 4792,0.625
WRAX REG2,0.0000000000
Re: Reducing the tremolo artefact from pitch shifting
You may use compressor/normalizer to make audio more flat and write your own transposition snippet with custom fadein-fadeout on buffer boundaries. I tried once, 256 samples for both was enough.
FV-1 uses fixed x-fade coefficients, but, AL3201 (afair) had about 8 types with different angles.
If your x-fade would be short and sin based, i think, sound will be more pleasant.
After transposition, it's good way to use resonant filter, it smoothing tremolo too
FV-1 uses fixed x-fade coefficients, but, AL3201 (afair) had about 8 types with different angles.
If your x-fade would be short and sin based, i think, sound will be more pleasant.
After transposition, it's good way to use resonant filter, it smoothing tremolo too
Re: Reducing the tremolo artefact from pitch shifting
I tried the diffusion but it didn't really help.
I am not sure how much benefit comes from using sine weighting instead of linear increasing/decreasing weights.
The mix ratios for the two read pointers will still cycle between (1 : 0), (0.5 : 0.5), (0, 1).
I am assuming those 3 mix ratios corresponded to the maximum and minimum points of the tremolo sound.
I'll see if I can get info on what the AL3201 does. Thanks.
I am not sure how much benefit comes from using sine weighting instead of linear increasing/decreasing weights.
The mix ratios for the two read pointers will still cycle between (1 : 0), (0.5 : 0.5), (0, 1).
I am assuming those 3 mix ratios corresponded to the maximum and minimum points of the tremolo sound.
I'll see if I can get info on what the AL3201 does. Thanks.
Re: Reducing the tremolo artefact from pitch shifting
audio is logarithmic, so it need to square x-fade coefficients to make volume more natural.
wrap, as far as i understand, gets obertones or harmonics , but you need whole tone.
And only one way - make transpose function yourself, with x-fades, filters, etc
wrap, as far as i understand, gets obertones or harmonics , but you need whole tone.
And only one way - make transpose function yourself, with x-fades, filters, etc
Re: Reducing the tremolo artefact from pitch shifting
Regarding square x-fade. Are you suggesting to make the two weighting functions intersect each other at a level not equal to 0.5 ?
I can understand that instead of averaging voltage levels (V) you may want to average power levels (V^2) instead.
That makes sense to me if the 2 signals are not correlated, but I don't see how it helps when the signals are highly corellated (e.g. when playing a single tone).
I'll give it a try anyway.
EDIT: Thinking about it more, for the case when the signal is a single tone, I don't see how any choice of weight function can remove the tremolo so long as the distance between the read pointers is fixed.
There will always be some point where the two weighting functions have equal value, and at that point we are adding two sine waves that have a phase difference between them. This is a flanger type effect (i.e. comb filter). For some input signal tones, the equal mixing will result in total cancellation of the two signals.
So as the mix ratio varies in time, we hear a sound with no comb filtering (i.e. signal comes mainly from one read pointer) changing to a sound with comb filtering (where there are equal contributions from both read pointers). The only way I can see of trying to remove that effect is by dynamically varying the separation between the read pointers according to the signal waveform, and I don't think the FV-1 is powerful enough to do that.
I can understand that instead of averaging voltage levels (V) you may want to average power levels (V^2) instead.
That makes sense to me if the 2 signals are not correlated, but I don't see how it helps when the signals are highly corellated (e.g. when playing a single tone).
I'll give it a try anyway.
EDIT: Thinking about it more, for the case when the signal is a single tone, I don't see how any choice of weight function can remove the tremolo so long as the distance between the read pointers is fixed.
There will always be some point where the two weighting functions have equal value, and at that point we are adding two sine waves that have a phase difference between them. This is a flanger type effect (i.e. comb filter). For some input signal tones, the equal mixing will result in total cancellation of the two signals.
So as the mix ratio varies in time, we hear a sound with no comb filtering (i.e. signal comes mainly from one read pointer) changing to a sound with comb filtering (where there are equal contributions from both read pointers). The only way I can see of trying to remove that effect is by dynamically varying the separation between the read pointers according to the signal waveform, and I don't think the FV-1 is powerful enough to do that.
Re: Reducing the tremolo artefact from pitch shifting
you may simply smooth signal by resonant filter and reverb after octaver and compress signal before octaver.
with custom octaver with 256 words cross-fade window, I think, it can give significant result.
with custom octaver with 256 words cross-fade window, I think, it can give significant result.