Hi everyone,
before hacking it up myself I thought, I'd ask if anything like that already is realized or could be implemented in an abstraction using standard pd objects (I could imagine it's somehow possible, but couldn't find a way).
I need to gradually transform the contents of a sample buffer from one sound to another, by crossfading all of the samples from sound A to sound B in a given time (say 2000 msecs). What I look for is an in place change of the sample values in the array. The lengths of the two sample buffers of course are considered equal.
Not to get me wrong: the cross fade doesn't work from left to write in the sample buffer, but all values of the buffer are crossfaded by crossfading the samples from sound A at all the indexes with the respective values of sound B "at once", using subsequent "steps", which are completely independent of the sample frequency to perform the cross fade, much like a line object.
Any ideas?
-- Orm
(bufferA * n) + (bufferB * (1-n)) n=a value decreasing from 1 to 0. i don't know if the result will please you... because this will still sound like a kind of "traditional" crossfade. m.
----- Original Message ----- From: "Orm Finnendahl" finnendahl@folkwang-hochschule.de To: pd-list@iem.kug.ac.at Sent: Sunday, December 01, 2002 9:09 PM Subject: [PD] crossfade of complete sample buffer
Hi everyone,
before hacking it up myself I thought, I'd ask if anything like that already is realized or could be implemented in an abstraction using standard pd objects (I could imagine it's somehow possible, but couldn't find a way).
I need to gradually transform the contents of a sample buffer from one sound to another, by crossfading all of the samples from sound A to sound B in a given time (say 2000 msecs). What I look for is an in place change of the sample values in the array. The lengths of the two sample buffers of course are considered equal.
Not to get me wrong: the cross fade doesn't work from left to write in the sample buffer, but all values of the buffer are crossfaded by crossfading the samples from sound A at all the indexes with the respective values of sound B "at once", using subsequent "steps", which are completely independent of the sample frequency to perform the cross fade, much like a line object.
Any ideas?
-- Orm
PD-list mailing list PD-list@iem.kug.ac.at http://iem.kug.ac.at/cgi-bin/mailman/listinfo/pd-list
Hi,
Am Montag, den 02. Dezember 2002 um 10:34:50 Uhr (+0100) schrieb marius schebella:
(bufferA * n) + (bufferB * (1-n)) n=a value decreasing from 1 to 0.
That's what I want to do (using a hamming window or something like that for the envelope). The question is about how to implement this in pd:
Given two buffers (A and B) i want to create a third buffer (C) with a single bang which copies all samples of A and B using the above formula on each sample at once (meaning faster than the samplerate). So what I need is some sort of a tabledump, which can be triggered by a bang. That is quite simple in high-level pd once you know for example the size of an array. But I don't know how to get that except accessing the array struct directly within a code external. Another solution would be if there was some sort of "dump" message for table objects.
Does anybody know of something like that? Maybe I'm missing something obvious.
i don't know if the result will please you... because this will still sound like a kind of "traditional" crossfade. m.
That's o.k. It's purpose is solely to avoid clicks when changing the sound of a buffer while it is being accessed by multiple granular generators in a performance. Transforming the sound of the accessed buffer gradually is the cheapest and most elegant solution.
-- Orm
if you want to do this in realtime, one possibility is you can use 2 tabplay~ objects (they send a bang if the array is played) and with each bang you can trigger the next value of your line or hamming-window using for multiplication. marius.
----- Original Message ----- From: "Orm Finnendahl" finnendahl@folkwang-hochschule.de To: "marius schebella" marius.schebella@chello.at Cc: pd-list@iem.kug.ac.at Sent: Monday, December 02, 2002 11:06 AM Subject: Re: [PD] crossfade of complete sample buffer
Hi,
Am Montag, den 02. Dezember 2002 um 10:34:50 Uhr (+0100) schrieb marius schebella:
(bufferA * n) + (bufferB * (1-n)) n=a value decreasing from 1 to 0.
That's what I want to do (using a hamming window or something like that for the envelope). The question is about how to implement this in pd:
Given two buffers (A and B) i want to create a third buffer (C) with a single bang which copies all samples of A and B using the above formula on each sample at once (meaning faster than the samplerate). So what I need is some sort of a tabledump, which can be triggered by a bang. That is quite simple in high-level pd once you know for example the size of an array. But I don't know how to get that except accessing the array struct directly within a code external. Another solution would be if there was some sort of "dump" message for table objects.
Does anybody know of something like that? Maybe I'm missing something obvious.
i don't know if the result will please you... because this will still
sound
like a kind of "traditional" crossfade. m.
That's o.k. It's purpose is solely to avoid clicks when changing the sound
of
a buffer while it is being accessed by multiple granular generators in a performance. Transforming the sound of the accessed buffer gradually is the cheapest and most elegant solution.
-- Orm
sorry, forget what i said about the tabplay, this was not correct, it was my error, because, tabplay waits until a block (usually 64 samples) is processed before starting a new loop and then you will have clicks or zeroes before the sample starts again... marius.
----- Original Message ----- From: "marius schebella" marius.schebella@chello.at To: "Orm Finnendahl" finnendahl@folkwang-hochschule.de Cc: pd-list@iem.kug.ac.at Sent: Monday, December 02, 2002 11:13 AM Subject: Re: [PD] crossfade of complete sample buffer
if you want to do this in realtime, one possibility is you can use 2 tabplay~ objects (they send a bang if the array is played)
and
with each bang you can trigger the next value of your line or
hamming-window
using for multiplication. marius.
hi Orm,
network delays...
anyway, I still do not know why not to abandon inplace tricks and use double-generator scheme instead (as marius suggests)...
Krzysztof
Orm Finnendahl wrote: ...
That's o.k. It's purpose is solely to avoid clicks when changing the sound of a buffer while it is being accessed by multiple granular generators in a performance. Transforming the sound of the accessed buffer gradually is the cheapest and most elegant solution.
Hi Krzysztof,
Am Montag, den 02. Dezember 2002 um 11:31:27 Uhr (+0100) schrieb Krzysztof Czaja:
anyway, I still do not know why not to abandon inplace tricks and use double-generator scheme instead (as marius suggests)...
It's just the cheapest way. I normally access one buffer with some 50-100 generators and a doubling of the generators would half the maximum available simultaneous voices. Your first solution with the readout of the table would work, but what is stopping the [until] object? It'd be nice, if tabread would either not output anything at all on index under- or overflow, or had a seperate second outlet to signal xflows with a bang. BTW, I think with your solution, it'd even work in place (without a third buffer), when you use a different scheme for the calculation of sample values (based on the last value at index and the goal value at index).
I'm now going to check your vex solution.
Thanks a lot, Orm
Hi Orm, i guess vasp modular provides what you need.
check out:
etc.
http://www.parasitaere-kapazitaeten.net/ext
best greetings, Thomas
----- Original Message ----- From: "Orm Finnendahl" finnendahl@folkwang-hochschule.de To: "Krzysztof Czaja" czaja@chopin.edu.pl Cc: pd-list@iem.kug.ac.at Sent: Monday, December 02, 2002 1:14 PM Subject: Re: [PD] crossfade of complete sample buffer
Hi Krzysztof,
Am Montag, den 02. Dezember 2002 um 11:31:27 Uhr (+0100) schrieb Krzysztof Czaja:
anyway, I still do not know why not to abandon inplace tricks and use double-generator scheme instead (as marius suggests)...
It's just the cheapest way. I normally access one buffer with some 50-100 generators and a doubling of the generators would half the maximum available simultaneous voices. Your first solution with the readout of the table would work, but what is stopping the [until] object? It'd be nice, if tabread would either not output anything at all on index under- or overflow, or had a seperate second outlet to signal xflows with a bang. BTW, I think with your solution, it'd even work in place (without a third buffer), when you use a different scheme for the calculation of sample values (based on the last value at index and the goal value at index).
I'm now going to check your vex solution.
Thanks a lot, Orm
PD-list mailing list PD-list@iem.kug.ac.at http://iem.kug.ac.at/cgi-bin/mailman/listinfo/pd-list
hi,
I think Orm's question was not how to do the math, but how to patch things up for inplace transformation (for whatever reason...) --
assuming sounds A and B are already stored in source arrays, and there is a separate destination array, one could just mix two [until]->[counter]->[tabread <source>] outputs into a [counter]->[tabwrite <destination>]
(driven with '0, 1 <dur>'->[line]->{do the math}->:)
or (if you happen to have vex installed) send 'gen concat <A>, multiply $1, add <B>, multiply $2' to [vex_form <destination>]
(in vex case math differs slightly)
Krzysztof
marius schebella wrote:
(bufferA * n) + (bufferB * (1-n))
...
From: "Orm Finnendahl" finnendahl@folkwang-hochschule.de
...
I need to gradually transform the contents of a sample buffer from one sound to another, by crossfading all of the samples from sound A to sound B in a given time (say 2000 msecs). What I look for is an in place change of the sample values in the array. The lengths of the two
Hi Krzysztof,
Am Montag, den 02. Dezember 2002 um 11:09:06 Uhr (+0100) schrieb Krzysztof Czaja:
or (if you happen to have vex installed) send 'gen concat <A>, multiply $1, add <B>, multiply $2' to [vex_form <destination>]
(in vex case math differs slightly)
trying your above example, I can't make it work. Clicking in one of the two message boxes of the attached patch changes buf3 temporarily to buf1, before it switches to buf2. buf3 should display buf1 on receiption of )1 0] and buf2 on receiption of )0 1], right?
I couldn't find any documentation about vex so I'm at loss here.
-- Orm
hi Orm,
that is because ((xval * 1) + yval) * 0 is 0...
As already said, in this case math differs slightly:
$1 == xgain / ygain, $2 == ygain
Check the fixed example (ignore intermediate redrawings).
Ok, there is no vex documentation -- but I guess there are no vex users out there -- just me and a few others here... The main 'vexing' library has not been released yet (wonder if it ever be, now we have vasp to play with?). I released the 'vex' part with no docs, because it seemed to me easy to use, nearly self-explanatory.
Krzysztof
Orm Finnendahl wrote: ...
trying your above example, I can't make it work. Clicking in one of the two message boxes of the attached patch changes buf3 temporarily to buf1, before it switches to buf2. buf3 should display buf1 on receiption of )1 0] and buf2 on receiption of )0 1], right?
I couldn't find any documentation about vex so I'm at loss here.
#N canvas 530 247 450 564 10; #X obj 19 522 vex_form buf3; #N canvas 0 0 450 300 graph1 0; #X array buf1 10 float 1; #A 0 0 0.542855 0.171428 0.0857141 0.0857141 -0.799997 -0.65714 -0.399998 -0.499998 -0.614283; #X coords 0 1 9 -1 200 140 1; #X restore 229 7 graph; #N canvas 0 0 450 300 graph2 0; #X array buf2 10 float 1; #A 0 0 -0.685718 -0.671432 -0.571431 0.242858 0.471431 0.600003 0.614289 0.54286 0; #X coords 0 1 9 -1 200 140 1; #X restore 229 151 graph; #N canvas 0 0 450 300 graph3 0; #X array buf3 10 float 1; #A 0 0 -0.685718 -0.671432 -0.571431 0.242858 0.471431 0.600003 0.614289 0.54286 0; #X coords 0 1 9 -1 200 140 1; #X restore 229 295 graph; #N canvas 0 0 305 364 math 0; #X obj 98 77 moses 0.5; #X obj 156 192 -; #X msg 156 156 1; #X obj 187 265 pack; #X obj 156 227 /; #X obj 181 117 t b 0; #X obj 97 192 -; #X msg 97 156 1; #X obj 61 265 pack; #X obj 61 231 /; #X obj 61 117 t 0 b 0; #X obj 61 319 outlet; #X obj 187 320 outlet; #X obj 98 33 inlet; #X connect 0 0 10 0; #X connect 0 1 5 0; #X connect 1 0 4 0; #X connect 2 0 1 0; #X connect 3 0 12 0; #X connect 4 0 3 0; #X connect 5 0 2 0; #X connect 5 1 1 1; #X connect 5 1 4 1; #X connect 5 1 3 1; #X connect 6 0 9 1; #X connect 6 0 8 1; #X connect 7 0 6 0; #X connect 8 0 11 0; #X connect 9 0 8 0; #X connect 10 0 9 0; #X connect 10 1 7 0; #X connect 10 2 6 1; #X connect 13 0 0 0; #X restore 19 432 pd math; #X obj 19 247 vsl 30 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 -1 -1 0 0; #X floatatom 19 398 5 0 0 0 - - -; #X msg 19 467 gen concat buf1 , multiply $1 , add buf2 , multiply $2; #X msg 45 493 gen concat buf2 , multiply $1 , add buf1 , multiply $2; #X connect 4 0 7 0; #X connect 4 1 8 0; #X connect 5 0 6 0; #X connect 6 0 4 0; #X connect 7 0 0 0; #X connect 8 0 0 0;
Hi Krzysztof,
Ok, there is no vex documentation -- but I guess there are no vex users out there -- just me and a few others here... The main 'vexing' library has not been released yet (wonder if it ever be, now we have vasp to play with?).
Hmmm, possibly you have better solutions for some of the problem that i encountered....
How did you deal with operations on long buffer sizes... are they granular and how did you solve the retriggering? By clock tick? I personally like the more script-like command style of your library... i'm already working how to incorporate that into vasp - most likely i'll do it via Python, for flexibility. Also, my library has hardly any functions for synthesis... i'm sure your SAOL functions are handy for a lot of things. It would be really great if a PD signal chain could be used for filling buffers faster then real-time.
best greetings, Thomas
hi Thomas,
sorry for a delay -- I have just returned from Cieszyn, after presenting Pd and cyclone to what turned out to be a gathering of polish maxers. Most of them seemed quite excited about a prospect of rendering (parts of) their stuff cross-platform, but all complained over tcl/tkish look and feel...
Thomas Grill wrote: ...
How did you deal with operations on long buffer sizes... are they granular and how did you solve the retriggering? By clock tick?
I did not deal at all -- any operation is performed in an unbounded time. That is mainly due to my old csoundish habit of first precomputing or preloading function tables, then keeping such `pool' in a more or less frozen state during performance.
What I would like to add to vexing in the first place is a sort of explicit lazy computation. But I want it simple, and it is really unlikely that vexing will ever be granular, or even threaded -- this is vasp's domain.
...
It would be really great if a PD signal chain could be used for filling buffers faster then real-time.
yes, even if it looks like a very tricky feature to design...
Krzysztof
Hi Krzysztof,
sorry for a delay -- I have just returned from Cieszyn, after presenting Pd and cyclone to what turned out to be a gathering of polish maxers.
No PD scene in Poland?
Most of them seemed quite excited about a prospect of rendering (parts of) their stuff cross-platform, but all complained over tcl/tkish look and feel...
No wonder... i'm working on these issues too, but i guess it will be bound to flext. I have had some (as i think) good ideas based on the attribute paradigm but i'm not sure if i've got the time for it in the next weeks and months...
How did you deal with operations on long buffer sizes... are they
granular
and how did you solve the retriggering? By clock tick?
I did not deal at all -- any operation is performed in an unbounded time. That is mainly due to my old csoundish habit of first precomputing or preloading function tables, then keeping such `pool' in a more or less frozen state during performance.
I see... it's the same situation for VASP@Max since i've not succeeded in implementing threading there yet. I hope to get it working soon, though.
What I would like to add to vexing in the first place is a sort of explicit lazy computation. But I want it simple, and it is really unlikely that vexing will ever be granular, or even threaded -- this is vasp's domain.
Does this mean that vexing is constrained to whole arrays? If not it would be great if there were (as already discussed some time ago) a bridge between our systems. I plan to emphasize the object-oriented behaviour of vasp references into arrays even more and it could be useful to fill work on these with your routines. I think i have to study your library a bit more.... maybe there's another gathering a few 100km's nearer to my place?
best greetings, Thomas
hi Thomas,
Thomas Grill wrote: ...
Does this mean that vexing is constrained to whole arrays?
no, there is a 'clip' message for setting an active chunk of an array -- one can dynamically change both the current 'target' array, and an offset and length of the current chunk of it.
If not it would be great if there were (as already discussed some time ago) a bridge between our systems.
seems natural -- I will try to find out how it could be done.
Krzysztof
Hi Krzysztof,
Does this mean that vexing is constrained to whole arrays?
no, there is a 'clip' message for setting an active chunk of an array -- one can dynamically change both the current 'target' array, and an offset and length of the current chunk of it.
Ok, then the connection between vex and vasp seems to be fairly easy, at least for vasp messages referencing a single buffer (there can be more).
I'll have a closer look at the vexing lib some day next week.
best greetings, Thomas