Cabbage Logo
Back to Cabbage Site

Smooth Crossfade between two convolution files

Hi!

I have a combobox where I can select Reverb files (IRs).

When switching through them I am getting short delays and interreuption of the material that is played until it gets back to normal. Maybe it has to do with the re-calculation of the new (switched) IR file (?).

Is there a way to avoid this or to make a smooth transition from one file to the other?

Thank you very much!
//rootnote

Would it be simpler create two convolution reverbs and simply fade between the two rather than trying to switch IRs. Or you could use start a second instance of your convolution reverb instrument using the new IR?

If you are switching IR a lot, and also between several different IRs, it might make sense to use liveconv as the convolution opcode. Here you can update the IR by rewriting the contents sequentially.

2 Likes

Hi @Oeyvind!
How can I access liveconv in cabbage? I have version 2.5.0 installed and cant seem to initialize it.

Thank you!

Seems to be recognised here without any problem. What error are you getting?

No error, doesnt seems to get loaded (it doesnt get red)

image

That doesn’t mean it’s not there. It just means Cabbage doesn’t highlight the opcode because it’s not part of its opcode list. It is now however as I just added it :wink:

@rorywalsh great! Thank you!

“Would it be simpler create two convolution reverbs and simply fade between the two rather than trying to switch IRs. Or you could use start a second instance of your convolution reverb instrument using the new IR?”

could I maybe ask for an example ? Thanks!

I’ve never used liveconv (sorry @Oeyvind , it’s high on my list of things to do in 2021!). But there is a Csound manual example that you should be able to quickly use in Cabbage :thinking:

I don’t have an example of this, I was just thinking aloud. But feel free to post your original code in order to start the ball rolling :+1:

1 Like

Yes, as Rory mentions, the example from the manual should get you started.
https://csound.com/docs/manual/liveconv.html
To reload the IR, you would start a new instance of instr 13 and give it the name of the new IR as a pfield.
If you constantly reload the same set of IRs back and forth a lot, then you might optimize the example by e.g. preloading the all IRs into tables. We have also sketched some ideas for reloading the spectral data directly without reanalysis, which might be useful if you reload very often, e.g. several times a second. Do tell if you need that and it might kick us into gear for implementing it :slight_smile:
Using liveconv and building your imeplementation from the manual example should be a very CPU effective way of accomplishing IR switching without clicks, as there is always just one convolution process running, even when you switch IR.

1 Like

ok, I have a simple version of it already running

giImpulse1L    ftgen   1, 0, 44100, 1, "1.WAV" , 0, 0, 1	;stereo file
giImpulse1R    ftgen   2, 0, 44100, 1, "1.WAV" , 0, 0, 1	;stereo file
giImpulse2L    ftgen   3, 0, 44100, 1, "2.wav"         , 0, 0, 1	;stereo file
giImpulse2R    ftgen   4, 0, 44100, 1, "2.wav"         , 0, 0, 1	;stereo file
    
ainL,ainR	ins	;READ STEREO AUDIO INPUT
    
instr	1	;CONVOLUTION INSTRUMENT

ainL,ainR	ins	;READ STEREO AUDIO INPUT


;---------------------------

    iplen		=	1024				;Buffer
itab1		=	giImpulse1L			
itab2		=	giImpulse1R
itab3		=	giImpulse2L
    itab4             =  	      giImpulse2R

;----------------------------

iirlen1L		=	nsamp(itab1)			
iskipsamples1L	=	nsamp(itab1)/2.3
iirlen1R		=	nsamp(itab2)			
iskipsamples1R	=	nsamp(itab2)/2.3
iirlen2L		=	nsamp(itab3)			
iskipsamples2L	=   nsamp(itab3)/2.3
iirlen2R		=	nsamp(itab4)			
iskipsamples2R	=   nsamp(itab4)/2.3
kupdate = 1
kclear = 0

;start-up impulse

aL 	liveconv ainL, itab1, 8192, kupdate, kclear
aR 	liveconv ainR, itab2, 8192, kupdate, kclear

Is it possible to skip samples in the IR like the iskipsamples in the fconv opcode or any other workaround?
Since the delay in the IR will be create delay when bypassing and switching it back on as VST version in a DAW.
http://www.csounds.com/manual/html/ftconv.html

Thanks

Ok. Good. Almost there. What is missing is the activity that happens in instr 13 in the manual example.

The way you have set it up now, you refer liveconv directly to the table where the ausdio is stored. This will not help you in replacing the IR, since the contents of the table is now static.
What you need to do:
Instead of changing the table reference in order to replace the IR, you should rewrite the contents of the table holding the IR (all the time referring liveconv to the same table).
This is what happens in instr 13. You can also use “skiptime” type tricks to jumpo ahead in the IR: you would do this as the skiptime for diskin (again, as in instr 13).

all best
Øyvind

1 Like

Thank you for the response!

So in my understanding I would add new IRs by something like this (by filling giIR_record table):

andx_IR1 line 0, 1, 1/(ftlen(giIR_record)/sr)
tablew a1amp, andx_IR1, giIR_record, 1
outch 1, a1
amp ; output the IR1

andx_IR2 line 0, 1, 1/(ftlen(giIR_record)/sr)
tablew a2amp, andx_IR2, giIR_record, 1
outch 1, a2
amp ; output the IR2

is that correct?
thanks

@Oeyvind am I on the correct path here? Thanks! :slight_smile:

Hi,
sorry for the delay.

Yes, you are on the right path. Just remember to also trigger the liveconv update:

ktrig 	init	1
if ktrig > -1 then
	chnset	ktrig, "conv_update"
	ktrig -= 1
endif

This will tell liveconv to start replacing the IR internally, and it will then progress to do so at audio rate (ensuring that the IR is replaced at the same rate that it is “consumed”).
The giIR_record table is only used to hold the audio until the IR has been updated internally in liveconv. If you replace the contents of the table, nothing will happen until you trigger the kupdate input to liveconv.

thank you @Oeyvind

I will try that!!!

@Oeyvind

In some way I can get it to give me a convolution sound, but I can only trigger one switch via a Knobs position.
Also the output is only on one side (right) and I don’t really know how to fix that.
I still want to switch between IRs via a Knob Position and the program should output stereo as well.

I have attached my current achievement to this post, I hope you can find the problem easily.

Thank you very much!!!

liveconv experiment.csd (1.8 KB)

Ok. Getting closer :slight_smile:

The audio output on one side (right) is because you have written the audio output from instr 14 like:
outch 2, aconv
This explicitly defines audio output on channel 2 (stereo right channel), and nothing on channel 1.

**
You will want to use two instances of liveconv, one for each stereo channel. I think you had this in an earlier example). Also, you want to use a different IR for each of these two instances. Like:
a1 inch 1
a2 inch 2
kupdate chnget “conv_update”
aconv1 liveconv a1, giIR_record1, 32768, kupdate, 0
aconv2 liveconv a1, giIR_record2, 32768, kupdate, 0
outs aconv1, aconv2


Also allocate two record tables, lik:
giIR_record1 ftgen 0, 0, 131072, 2, 0
giIR_record2 ftgen 0, 0, 131072, 2, 0


You want to split the IR switch control from the instrument that reads audio and out it in the record table.
So in instr 1
if chnget:k(“switcher”)==1 then
event “i”, 0, 13, -1
endif

and in instr 13 you do almost what you have done now, skipping the chnget switcher,
and also take care to write these two signals each to their own record table giIR_record1 and giIR_record2. Do note that these represent the convolution IR for the left and right channel (not two different impulse responses). So, in order to switch IR you need to make instr 13 read from another audio source, depending on the setting of the switch.

To do this, then in instr 1 you could do it like:
if changed(chnget:k(“switcher”))==1 then
event “i”, 0, 13, -1, chnget:k(“switcher”)
endif

and in instr 13:
if p4 == 1 then
a1 diskin2 “D://Cabbage/firstIR_left.wav”, 1 ;, iskip
a2 diskin2 “D://Cabbage/firstIR_right.wav”, 1 ;, iskip
endif
if p4 == 2 then
a1 diskin2 “D://Cabbage/secondIR_left.wav”, 1 ;, iskip
a2 diskin2 “D://Cabbage/secondIR_right.wav”, 1 ;, iskip
endif
(This can be done more elegantly, but it should work like this)


All of this done without testing, so please excuse any typos or other errors I might have made :slight_smile: