Delay Servo Technique

Algorithm development and general DSP issues

Moderator: frank

elmood
Posts: 16
Joined: Sun Jun 01, 2008 3:19 pm
Location: Toronto Canada
Contact:

Delay Servo Technique

Post by elmood »

I'm particularly interested in the delay servo technique shown on the Coding Examples page of the SpinSemi website. Dialing through different delay settings is really noisy. But perhaps I'm not understanding the example correctly. All the setup instructions use RMP0 and the CHO RDA instructions use RMP1. Is this correct?

When I implemented it in my program, it made a crazy sweeping delay modulation thing which, although very cool, wasn't really what I was expecting.

skp run,1 ;only establish the LFO on the first sample pass
wldr rmp0,0,4096 ;set rmp0 to its widest range
cho rdal,rmp0 ;load in the current RMP0 pointer
rdax mpos,-1 ;subtract the desired position
wrax rmp0_rate,0 ;write the position error to the ramp rate register
cho rda,rmp1,reg|compc,del
cho rda,rmp1,0,del+1

Any help making it would would be great. Also, is there any way to ensure that if the delay memory is only part of the total delay mem that the chorus pointer won't go into adjacent blocks?


Cheers,

Andrew
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

I believe you are correct, they should all be rmp0 or rmp1, not a mix of the two.

The only way to make sure the chorus doesn't exceed it's range is basically to make sure the coefficients keep it in the memory range it is to use. Since there is some rounding in the address calculation in the chorus generator, I usually add 1 or 2 samples to each end of the block just to have a little buffer between the chorus block and adjacent blocks.
Frank Thomson
Experimental Noize
elmood
Posts: 16
Joined: Sun Jun 01, 2008 3:19 pm
Location: Toronto Canada
Contact:

Post by elmood »

Thanks for the advice... I confirmed that I am in fact using RMP0 for both.

But I'm still not able to get it working correctly. For very short delays it seems to work fine, I hear a slight pitch shift as the LFO moves the pointer to the right location. But for longer delays (I'm using the entire delay RAM) I just hear a repeated sweeping pitch as the LFO appears to never make it to the right location.

Any ideas?
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

I do not believe this technique will work properly for a delay longer than 4096 samples. The limit is in the interpolation:

cho rda,rmp0,reg|compc,del
cho rda,rmp0,0,del+1

The ramp uses a fixed size in memory so you are limited to that length for the delay del.

What is your ultimate goal with this? Removing zipper noise? Changing the delay length with minimal pitch artifacts?
Frank Thomson
Experimental Noize
elmood
Posts: 16
Joined: Sun Jun 01, 2008 3:19 pm
Location: Toronto Canada
Contact:

Post by elmood »

What I'm trying to do is avoid zipper noise so people can dial through the delay while playing.

Is there a proper way to do it? I noticed that the chorus servo method makes the pitch shift up and down slightly. Obviously moving the pointer is going to cause some discontinuity, but what is the least offensive way to do it?
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

What I like to do:

Code: Select all

;Mono delay in left chan
;Frank Thomson
;OCT Distribution (310)348-9626
;
;pot0 adjusts delay time

equ	length	32767
equ 	smooth	0.000125	; Adjust to your liking of speed/noise tradeoff, can be adjusted over a LARGE range
			; 0.125 Fast but zipper noise
			; 0.000125 Little zipper but more frequency shifting when changing, like an old tape delay

mem	echo	length		;echo delay

equ	del_read	reg0

; Clear register on start
skp	RUN,	loop
clr
wrax	del_read,0

loop:

; Select tap from delay based on pot0, should range 0 to length
; Since pot only has 512 states, want to filter pot to avoid jumping

; Smooth POT0
clr				; Clear the ACC
or 	length*256		; Put delay length into ACC alligned to ACC[22:8]
mulx 	pot0			; Multiply by POT0, new target value
rdfx 	del_read, smooth		; Smooth it : (target - current) * C + current
wrax 	del_read, 0		; Save it
; 
rdax 	adcl,	0.5		; Get input
rdax	adcr,	0.5
wra 	echo,	1.0		; Write it to the head of the delay
wrax	dacr,	0		; Write non-delayed to right DAC
;
rdax	del_read, 1.0		; Get the delay tap to read
wrax 	addr_ptr, 0	; Write it to the address pointer register
rmpa 	1			; Read from memory
wrax 	dacl,	0		; ACC-> DAC

Frank Thomson
Experimental Noize
Keith
Posts: 9
Joined: Sun Oct 30, 2005 2:30 pm

Post by Keith »

Making a variable delay that does not "zip"...

If you're making a commercial product like a guitar amp, and have reserved say, 0.5 seconds of delay RAM for the task, realize that 512 possible delay selections represents 1mS increments... That's tiny.

You can make the situation much better by quantizing the pot value with the AND instruction to maybe 5 bits, which gives 15mS increments, but greatly reduces the noise when the pot is rotated. 4 bits is even better, and few musicians would complain about the limited selection.

If you're not doing much else, you can detect any change in the pot value and mute the delay output until the pot is stable.

Keith
Mcfly
Posts: 46
Joined: Fri Mar 08, 2013 2:38 pm
Location: Argentina

Post by Mcfly »

Hi! When i run the fv-1 internal program rom_pt_echo from the fv1 internal memory, i don't hear any zipper noise from the pot.
But when i load it into an external eeprom, it makes a much louder noise. Is there any reason for this to happen?
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

They should be identical. The ROM programs were made with an old, never released version of the assembler and a few of the mnemonics were different. I updated the code for the website to work with the released assembler so it is possible I made an error in updating the code. I will try to take a look at it in a few days when I can dig into it.
Frank Thomson
Experimental Noize
Mcfly
Posts: 46
Joined: Fri Mar 08, 2013 2:38 pm
Location: Argentina

Post by Mcfly »

frank wrote:They should be identical. The ROM programs were made with an old, never released version of the assembler and a few of the mnemonics were different. I updated the code for the website to work with the released assembler so it is possible I made an error in updating the code. I will try to take a look at it in a few days when I can dig into it.
Thanks Frank, please let me know when the code is up.
Mcfly
Posts: 46
Joined: Fri Mar 08, 2013 2:38 pm
Location: Argentina

Post by Mcfly »

Mcfly wrote:
frank wrote:They should be identical. The ROM programs were made with an old, never released version of the assembler and a few of the mnemonics were different. I updated the code for the website to work with the released assembler so it is possible I made an error in updating the code. I will try to take a look at it in a few days when I can dig into it.
Thanks Frank, please let me know when the code is up.
Hey Frank, any updates on this?
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

I compared them and they sound the same to me, no difference in zipper noise or other artifacts.
Frank Thomson
Experimental Noize
Digital Larry
Posts: 338
Joined: Mon Nov 12, 2012 1:12 pm
Contact:

Post by Digital Larry »

I have a few questions about this.

First, I have implemented a delay (well actually slacker sent me the original idea) which can be adjusted to be short or long and uses a control input from 0 to 1.0 to sweep over the whole delay range.

It uses RMPA so there is no inter-sample interpolation. This seems to mostly affect flanging - there's not much effect noticeable.

I want to implement this, with some flexibility. Now I know that I will have to choose one of the acceptable RMP LFO amplitudes of 256, 512, 2048, 4096 (or whatever it is).

This is the given sample code:

Code: Select all

skp run,1 ;only establish the LFO on the first sample pass 
wldr rmp0,0,4096 ;set rmp0 to its widest range 
cho rdal,rmp0 ;load in the current RMP0 pointer 
rdax mpos,-1 ;subtract the desired position 
wrax rmp0_rate,0 ;write the position error to the ramp rate register 
cho rda,rmp0,reg|compc,del 
cho rda,rmp0,0,del+1 
Here's my question - what is "del"?
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

Keith wrote the code but based on his normal way of doing things "del" was his default name for a delay so it is probably the delay line.
Frank Thomson
Experimental Noize
Digital Larry
Posts: 338
Joined: Mon Nov 12, 2012 1:12 pm
Contact:

Post by Digital Larry »

In the examples for a sin/cos modulating delay using CHO RDA, the parameter there is del^ because it's assumed that you will be sweeping +/- around the center of the delay - as sin/cos LFO generates + and - values. However, the ramp LFO (so far as I know) only generates positive values, so the statements as written would start at a minimum at "del" which is (light goes off, got it now) the beginning of the delay. For some reason I thought that was the end of the delay, but that would be del#.

So most people wanting to implement this would want to have a statement like:

del mem 4096

to match the amplitude of the ramp LFO. And if I choose to use a smaller buffer for shorter delay times, I'll need to stick with one of the available ramp LFO amplitudes and make sure that this matches the length of the buffer.

Thanks!

DL
Post Reply