Any thoughts on implementing an "infinite hold" ef

Algorithm development and general DSP issues

Moderator: frank

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

Post by frank » Wed Mar 09, 2011 9:08 pm

Ah, well, that is not what I thought you were trying to do, I thought you were trying to make it fade out over time in playback mode. Adjusting the delay length involves some deeper understanding of memory addressing in the FV-1.

So, when I said the problem is here:
wrax reg0,1 ; write the value to reg0, save it for later

I thought you wanted to fade out and the solution to do that is to change the line to:
wrax reg0,0 ; write the value to reg0, save it for later

The "1" coefficient is keeping the value in the accumulator so the next line:
rda delL#,1 ; Read tail of left delay

Is adding the accumulator to the value read from the end of the delay so it was constantly increasing and saturating the output.
Frank Thomson
Experimental Noize

soundsubs
Posts: 24
Joined: Fri Feb 25, 2011 10:49 am

Post by soundsubs » Thu Mar 10, 2011 10:21 am

see, this makes perfect sense to me when you put it that way. thanks!

for the operation "adjustment of the delay length which is sustained" it shouldnt be any different than a typical delay adjustment length code snippet.
i'll see if i can dig that up and burn it when im back home.

soundsubs
Posts: 24
Joined: Fri Feb 25, 2011 10:49 am

Post by soundsubs » Fri Mar 11, 2011 1:03 pm

Tried the following:

Code: Select all

; this is borrowed heavily from the delay/play alg posted by frank
; meant to be a "freeze" effect where it samples input and 
; outputs a shortened loop of the input audio, near a single cycle. 
; If POT0 is 0 to 0.5 we are in record mode 
; If 0.5 to 0.999 we are in playback mode 
; 
delL mem 4096 		; Define delay as really really small 
ldax pot0 		; Read in POT0 
sof 1.0,-0.5 		; Add -0.5 to the POT0 value so it ranges -0.5 to +0.5 
skp gez,play 		; If ACC is >=0 we are in playback mode so jump to play 
ldax adcl 		; Read in ADC left 
wra delL,1.0 		; Write to left delay line 
wrax dacl,0 		; and to DAC left 
wra delL#,0 		; write 0 at end of delay line to limit record length 
skp zro, end 		; Jump to end 
; 
; Play back mode 
play: 
clr ; Clear ACC 
rda delL#,1.0 		; Read tail of left delay 
wra delL,1.0 		; Write to head of delay 
wrax dacl,0 		; Write it to DAC left 
wra delL#,0 		; write a 0 to end of delay, not really needed but will make sure rest of memory is 0 if you add other functions 
;
;get address pointer from pot1: 
;
rdax   pot1,1 		; Read value of Pot1, multiply by 1
and   %01111110_00000000_00000000   ;don't make jumps too small 
sof   61/64,3/64         	;50 ms to 1 second 
wrax   addr_ptr,0 
; 
end:
....hoping that POT1 would adjust buffer amount, but it doesnt.
do i need to have the POT1 portion elsewhere in the code?

thanks in advance.

slacker
Posts: 116
Joined: Tue Feb 01, 2011 12:13 pm

Post by slacker » Sat Mar 12, 2011 5:11 am

The way you've done the code for the pot it's just stuck at the end of the program and doesn't do anything.
What the code does is read the value from the pot and writing it to the delay memory address pointer. In order to make it do anything you then need to read from the address pointer instead of reading from the tail of the delay.

I think this should work, it will set the buffer length anywhere from 0 to 4096 samples. It will probably won't work if you change the buffer size whilst it's playing back, you'd need to set it and then record another loop to hear the effect.

Code: Select all

; this is borrowed heavily from the delay/play alg posted by frank
; meant to be a "freeze" effect where it samples input and
; outputs a shortened loop of the input audio, near a single cycle.
; If POT0 is 0 to 0.5 we are in record mode
; If 0.5 to 0.999 we are in playback mode
;
delL mem 4096       ; Define delay as really really small
ldax pot0       ; Read in POT0
sof 1.0,-0.5       ; Add -0.5 to the POT0 value so it ranges -0.5 to +0.5
skp gez,play       ; If ACC is >=0 we are in playback mode so jump to play
ldax adcl       ; Read in ADC left
wra delL,1.0       ; Write to left delay line
wrax dacl,0       ; and to DAC left
wra delL#,0       ; write 0 at end of delay line to limit record length
skp zro, end       ; Jump to end
;
; Play back mode
play:
clr ; Clear ACC

rdax   pot1,0.125       ; Read value of Pot1, divide by 8 to scale from 0 to 4096
wrax   addr_ptr,0
rmpa 1               ; Read from address pointer
wra delL,1.0       ; Write to head of delay
wrax dacl,0       ; Write it to DAC left
wra delL#,0       ; write a 0 to end of delay, not really needed but will make sure rest of memory is 0 if you add other functions
;
end:
I think that's correct, I'm not 100% sure about scaling the pot, I've only just started messing with this stuff.

soundsubs
Posts: 24
Joined: Fri Feb 25, 2011 10:49 am

Post by soundsubs » Sat Mar 12, 2011 8:22 am

Thanks slacker!

this is ALMOST working perfectly:

Code: Select all

; this is borrowed heavily from the delay/play alg posted by frank 
; meant to be a "freeze" effect where it samples input and 
; outputs a shortened loop of the input audio, near a single cycle. 
; If POT0 is 0 to 0.5 we are in record mode 
; If 0.5 to 0.999 we are in playback mode 
; 
delL mem 8148       	; Define delay as small 
ldax pot0       		; Read in POT0 
sof 1.0,-0.5       		; Add -0.5 to the POT0 value so it ranges -0.5 to +0.5 
skp gez,play       		; If ACC is >=0 we are in playback mode so jump to play 
ldax adcl       		; Read in ADC left 
wra delL,1.0       		; Write to left delay line 
wrax dacl,0       		; and to DAC left 
wra delL#,0       		; write 0 at end of delay line to limit record length 
skp zro, end       		; Jump to end 
; 
; Play back mode 
play: 
clr 			; Clear ACC 

rdax   pot1,0.5       	; Read value of Pot1, divide by 2 to scale from 0 to 8148 
and   %01111111_10000000_00000000 
sof  243/256,13/256         ;50 ms to 1 second 
wrax   addr_ptr,0 
rmpa 1               		; Read from address pointer 
wra delL,1.0       		; Write to head of delay 
wrax dacl,0       		; Write it to DAC left 
wra delL#,0       		; write a 0 to end of delay, not really needed but will make sure rest of memory is 0 if you add other functions 
; 
end:



it will even "hold" the buffer while i move POT1! this makes for really interesting effects that happen while the buffer is moving around.
the only issue is that when POT1 is above about 45%, the buffer is silent.
any ideas?

slacker
Posts: 116
Joined: Tue Feb 01, 2011 12:13 pm

Post by slacker » Sat Mar 12, 2011 8:57 am

I think your pot scaling is wrong, the maximum length is 32767 so to get to 8148 you need to deivide by 4 not 2. What's probably happening now is once you get past half way you'e gone outside the buffer.

soundsubs
Posts: 24
Joined: Fri Feb 25, 2011 10:49 am

Post by soundsubs » Sat Mar 12, 2011 3:50 pm

ok here it is:

Code: Select all

; this is borrowed heavily from the delay/play alg posted by frank 
; meant to be a "freeze" effect where it samples input and 
; outputs a shortened loop of the input audio, near a single cycle. 
; If POT0 is 0 to 0.5 we are in record mode 
; If 0.5 to 0.999 we are in playback mode 
; 
delL mem 8148       	; Define delay as small 
ldax pot0       		; Read in POT0 
sof 1.0,-0.5       		; Add -0.5 to the POT0 value so it ranges -0.5 to +0.5 
skp gez,play       		; If ACC is >=0 we are in playback mode so jump to play 
ldax adcl       		; Read in ADC left 
wra delL,1.0       		; Write to left delay line 
wrax dacl,0       		; and to DAC left 
wra delL#,0       		; write 0 at end of delay line to limit record length 
skp zro, end       		; Jump to end 
; 
; Play back mode 
play: 
clr 			; Clear ACC 
rdax   pot1,1       		; Read value of POT1, multiply by 1 to get a positive integer
mulx   pot1		; multiply the value in POT1 by itself
mulx   pot1		; multiply the value by itself again
and   %01111111_10000000_00000000 
sof  243/256,13/256         ; 50 ms to 1 second 
wrax   addr_ptr,0 
rmpa 1               		; Read from address pointer 
wra delL,1.0       		; Write to head of delay 
wrax dacl,0       		; Write it to DAC left 
; 
end:

this will take the input, loop it infinitely if POT0 is above halfway
POT1 controls Loop buffer length.

lots and lots of fun here.


....now, to figure out the livecut algorithm.

jovesdies
Posts: 32
Joined: Wed Feb 25, 2009 2:55 am

Post by jovesdies » Wed Mar 16, 2011 8:57 am

Hi,
I think that there is a better way to do "freeze" effect.
The problem with the posted code is the "click" sound due to the fact that the recorded sample doesn't start and stop at the same point.

Now, we can use the delay program with infinite feedback with this setup:
left channel for "freeze" effect only, right channel for clean, direct signal.
Set the initial feedback short and connect a momentary switch to the feedback pot so when the switch is pressed we turn the pot to max (infinite feedback). then we must tell the program to don't read anymore from left channel. In this way we can play over the feedback signal recorded.
Now, I don't know where to start to program but if there is anyone who can ....

Alex MAK
Posts: 89
Joined: Fri Nov 05, 2010 1:00 pm

Post by Alex MAK » Sun Nov 25, 2012 5:33 am

Hi guys! This code works for me is not correct, it's like a tremolo effect. How can you get rid of this artifact? Thank you! Alex.

slacker
Posts: 116
Joined: Tue Feb 01, 2011 12:13 pm

Post by slacker » Mon Nov 26, 2012 1:13 pm

The code Soundsubs posted should work fine, it does not give a smooth infinite sustain sound though, it just loops short sections of audio. If you want to make it smoother you could try adding some reverb after it.
Or you could use a reverb program instead like Sean Costello suggested on the first page of this thread, the Reverb+HP+LP code in the free DSP programs section does this, works really well.

Alex MAK
Posts: 89
Joined: Fri Nov 05, 2010 1:00 pm

Post by Alex MAK » Mon Nov 26, 2012 10:16 pm

Thank you! I'll try it :)

MacroMachines
Posts: 71
Joined: Fri Dec 12, 2014 9:45 pm
Location: Detroit,MI
Contact:

Post by MacroMachines » Fri Aug 05, 2016 6:50 am

The best thing I've found so far is to use this rec/play but with a few allpass delays in the circulating locked feedback buffer, it blurs the loop from being a ridged stutter to being more of a spectral feeling hold.
http://MacroMachines.net
Digital Control for your Analog Soul.

MacroMachines
Posts: 71
Joined: Fri Dec 12, 2014 9:45 pm
Location: Detroit,MI
Contact:

Post by MacroMachines » Tue Dec 06, 2016 10:02 pm

Ive also been playing with a combination of the tap tempo/ flip flop code in other threads to create a zero crossing repeater. I would love to figure out a way to have start and end points of a loop able to snap to the nearest zero cross, but its a bit tricky. This would be good for both pitch shifting and sustain.
http://MacroMachines.net
Digital Control for your Analog Soul.

Post Reply