record and play multiple LiSa objects on multiple channels
Hi chuckers, Kassen:
Fortunately that's not correct. You can use quite a few, if you like; LiSa a => dac; LiSa b => dac; //etc
If this gave you trouble there is likely something else that went wrong. If you send a (minimal) example that demonstrates the trouble you had we can look at it and try to help.
ok, I tried again to do the following (as a beginning): - record stereo sound - play it back in loops - save it in parallel ---------------------------------------- I tried many variations and until now didn't find a way to do this all together. Please use a fast panning stereo sound for all examples (e.g. one panning cycle in 1 second). I could simulate this in chuck, but then this would make everything less clear. Let's start with a first problem. LiSa as you said above can be instantiated multiple times, you are right, this works (and there are examples for that). The chuck crashes I mentioned in a former mail can be reduced to the following code: LiSa looper; // this works: adc => looper => dac; adc.chan(0) => looper.chan(0) => dac.chan(0); adc.chan(1) => looper.chan(1) => dac.chan(1); when running on chuck 1.2.0.8 (which was my first contact with chuck). Now I compiled 1.2.1.4-dev-2 (from the posted svn repo), which doesn't crash, "fine" you say. ---------------------------------------- So next thing coming to mind is: 2000::ms => dur record_time; //1 => int nchannels; 2 => int nchannels; LiSa looper; record_time => looper.duration; for(0 => int c; c < nchannels; c++) { adc.chan(c) => looper.chan(c) => dac.chan(c); } adc => dac; <<<"record", "">>>; 1 => looper.record; record_time => now; 0 => looper.record; adc =< dac; <<<"play", "">>>; looper.play(1); looper.loop(1); //for(0 => int c; c < nchannels; c++) { looper.chan(c) => dac.chan(c); } // go while( true ){ 1000::ms => now; } this seems to record only one channel which is played on both dac channels. ---------------------------------------- Ok, lets try another one, multiple LiSa objects connected to the adc/dac channels: 20::ms => dur crossfade; 2000::ms => dur record_time; fun void loop_sampler(int c) { LiSa looper; adc.chan(c) => looper => dac.chan(c); adc.chan(c) => dac.chan(c); record_time => looper.duration; <<<"record", c>>>; 1 => looper.record; record_time => now; 0 => looper.record; adc.chan(c) =< dac.chan(c); <<<"play", c>>>; looper.play(1); looper.loop(1); looper => dac.chan(c); 2 * record_time => now; } spork ~ loop_sampler(0); spork ~ loop_sampler(1); // go while( true ){ 1000::ms => now; } surprisingly, this doesn't play back anything in chuck 1.2.1.4-dev-2. I checked the general logic by simply replacing all occurencies of ".chan(c)" with nothing in the editor, which works, but is mono. But in chuck 1.2.0.8 it works unchanged!
haven't time to look closely at this, but a couple things: * LiSa is mono internally; you can't chuck to separate internal channels. it can do multichannel output, but it's not perfect. * multichannel in ChucK is a bit dodgy at the moment, at least with LiSa dt On Apr 8, 2011, at 6:24 PM, Harald Gutsche wrote:
Hi chuckers,
Kassen:
Fortunately that's not correct. You can use quite a few, if you like; LiSa a => dac; LiSa b => dac; //etc
If this gave you trouble there is likely something else that went wrong. If you send a (minimal) example that demonstrates the trouble you had we can look at it and try to help.
ok, I tried again to do the following (as a beginning):
- record stereo sound - play it back in loops - save it in parallel
----------------------------------------
I tried many variations and until now didn't find a way to do this all together. Please use a fast panning stereo sound for all examples (e.g. one panning cycle in 1 second). I could simulate this in chuck, but then this would make everything less clear.
Let's start with a first problem. LiSa as you said above can be instantiated multiple times, you are right, this works (and there are examples for that). The chuck crashes I mentioned in a former mail can be reduced to the following code:
LiSa looper; // this works: adc => looper => dac; adc.chan(0) => looper.chan(0) => dac.chan(0); adc.chan(1) => looper.chan(1) => dac.chan(1);
when running on chuck 1.2.0.8 (which was my first contact with chuck). Now I compiled 1.2.1.4-dev-2 (from the posted svn repo), which doesn't crash, "fine" you say.
----------------------------------------
So next thing coming to mind is:
2000::ms => dur record_time; //1 => int nchannels; 2 => int nchannels;
LiSa looper;
record_time => looper.duration;
for(0 => int c; c < nchannels; c++) { adc.chan(c) => looper.chan(c) => dac.chan(c); }
adc => dac;
<<<"record", "">>>; 1 => looper.record; record_time => now; 0 => looper.record;
adc =< dac;
<<<"play", "">>>; looper.play(1); looper.loop(1); //for(0 => int c; c < nchannels; c++) { looper.chan(c) => dac.chan(c); }
// go while( true ){ 1000::ms => now; }
this seems to record only one channel which is played on both dac channels.
----------------------------------------
Ok, lets try another one, multiple LiSa objects connected to the adc/dac channels:
20::ms => dur crossfade; 2000::ms => dur record_time;
fun void loop_sampler(int c) { LiSa looper; adc.chan(c) => looper => dac.chan(c); adc.chan(c) => dac.chan(c);
record_time => looper.duration;
<<<"record", c>>>; 1 => looper.record; record_time => now; 0 => looper.record;
adc.chan(c) =< dac.chan(c);
<<<"play", c>>>; looper.play(1); looper.loop(1); looper => dac.chan(c);
2 * record_time => now; }
spork ~ loop_sampler(0); spork ~ loop_sampler(1);
// go while( true ){ 1000::ms => now; }
surprisingly, this doesn't play back anything in chuck 1.2.1.4-dev-2. I checked the general logic by simply replacing all occurencies of ".chan(c)" with nothing in the editor, which works, but is mono.
But in chuck 1.2.0.8 it works unchanged! _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
I continued my tests...adding chuck-1.2.1.3 from miniAudicle-0.2.0 to the candidates. result: connections like adc.chan(c) => looper => dac.chan(c); work in 1.2.0.8 and 1.2.1.3 but not in 1.2.1.4-dev-2 When further analysing, I find that adc.chan(0) => LiSa looper => dac works, but adc => LiSa looper => dac.chan(0); fails. I also noticed that the play rate 2 in the following script works only in 1.2.0.8, is this intentionally?: 2000::ms => dur duration; adc => LiSa looper => dac; adc => dac; duration => looper.duration; looper.recRamp( 20::ms ); <<<"recording...">>>; looper.record(1); duration => now; looper.record(0); adc =< dac; <<<"playing...">>>; looper.play(1); looper.loop(1); looper.rate(2); duration => now;
Harald;
On 9 April 2011 15:44, Harald Gutsche
I continued my tests...adding chuck-1.2.1.3 from miniAudicle-0.2.0 to the candidates.
Cool. Testing is good.
adc => LiSa looper => dac.chan(0);
fails.
That's a bug in 1.2.1.4 then, that should work. What OS are you on? It could be a RtAudio issue. Do you know by any chance whether that beta already switched to the new RtAudio?
I also noticed that the play rate 2 in the following script works only in 1.2.0.8, is this intentionally?:;
looper.rate(2);
If you mean that line then you might want to try rate(2.0) to force it setting the rate, instead of getting the rate of the default (first) voice. I think that might make a difference. LiSa's functions are rather overloaded which can cause some confusion with implied casting. Yours, Kas.
adc => LiSa looper => dac.chan(0);
fails.
That's a bug in 1.2.1.4 then, that should work. What OS are you on?
linux and jack
It could be a RtAudio issue.
rtaudio.h tells me // RtAudio: Version 3.0.2 (14 October 2005) seems to be old :-) I would assume the bug is in LiSa and/or multichannel code, because it depends on the way it is connected, remember this works: LiSa looper => dac; chuck's multichannel code seems to have some problems anyway.
looper.rate(2);
on further testing I found it's because the parameter should be a float (as you also suggested). Sorry, I was fooled by the fact, that 1.2.0.8 worked.
If you mean that line then you might want to try rate(2.0) to force it setting the rate, instead of getting the rate of the default (first) voice. I think that might make a difference. LiSa's functions are rather overloaded which can cause some confusion with implied casting.
indeed... Do you mean the function is overloaded with a function rate(int x) ? if so what is the purpose of x? Or will a rate(2) be delegated to rate()?
Harald;
That's a bug in 1.2.1.4 then, that should work. What OS are you on?
linux and jack
Strange, so far most multi-channel issues have involved the plan (non-ASIO) Windows drivers.
seems to be old :-)
Indeed. I hope that'll be fixed with the upcoming update.
I would assume the bug is in LiSa and/or multichannel code, because it depends on the way it is connected, remember this works:
LiSa looper => dac;
Could you try this; SinOsc s => dac.chan(0); ..? That should tell us whether it's the UGen or the dac that causes the issue.
chuck's multichannel code seems to have some problems anyway.
Yes, stereo is half implemented, I think really only pan2 and maybe a sample player are true stereo. My gut feeling says this is something else though.
looper.rate(2);
on further testing I found it's because the parameter should be a float (as you also suggested). Sorry, I was fooled by the fact, that 1.2.0.8 worked.
I ran into the same thing once, took me a whole afternoon of muttering non-polite things to find.
indeed... Do you mean the function is overloaded with a function rate(int x) ? if so what is the purpose of x? Or will a rate(2) be delegated to rate()?
Well... LiSa has a lot of voices for playback (see the explanation in the /examples/special/readme_lisa2.ck (or similar) file. To set the loop-end of voice 3 to a second; my_lisa.loopEnd(3 , second); //simple, right? Now we try to get it instead; my_lisa.loopEnd(3); //should now return a second If we want to set the first voice we can omit the voice command for convenience; my_lisa.loopEnd(second); //no need to deal with voices if we only need one. Here it is all quite clear, however, you can imagine that getting voice 3(int)'s rate and setting the first voice to a rate of 3.0(float) may look very similar. This is what you ran into and this is where the problem came from. This is uniform with other ChucK functions where dropping the parameter turns it into a "get" function, like; <<< my_sinosc.freq() >>>; LiSa is merely a bit more extensive than most UGens so now that LiSa became uniform with the rest after version 1.2.0.8 we got this chance for some confusion. IMHO the current situation is consistent and powerful, but I agree that it can be a bit tricky. Hope this clarifies, Kas.
Kassen,
I would assume the bug is in LiSa and/or multichannel code, because it depends on the way it is connected, remember this works:
LiSa looper => dac;
Could you try this;
SinOsc s => dac.chan(0);
yes, SinOsc s; s => dac.chan(0); 1000::ms => now; s =< dac.chan(0); s => dac.chan(1); 1000::ms => now; s =< dac.chan(1); 1000::ms => now; adc.chan(0) => dac.chan(0); 1000::ms => now; adc.chan(0) =< dac.chan(0); adc.chan(1) => dac.chan(1); 1000::ms => now; adc.chan(1) =< dac.chan(1); 1000::ms => now; works correctly on all three versions, as you see also adc.chan(0) => dac.chan(0) works .
..? That should tell us whether it's the UGen or the dac that causes the issue.
I think it's more complicated. When I tried to hack cuck's source code (which was around 1.2.1.3), I had no problems to understand adc and dac, as these ugens are unbuffered. Those simply copy a single sample from in to out. Pan2 and Mix2 are the same and use ugen's gain I got confused when looking at sndbuf's code. lisa should be similar. How is the multichannel code supposed to work? LiSaMulti_tick didn't change from 1.2.1.3 to current, so the problem must be elsewhere.
chuck's multichannel code seems to have some problems anyway. Yes, stereo is half implemented, I think really only pan2 and maybe a sample player are true stereo. My gut feeling says this is something else though.
yes, e.g. simply using if( !type_engine_import_ugen_begin( env, "Gain", "UGen_Stereo", env->global(), NULL, NULL, NULL, NULL, 2, 2 ) ) return FALSE; // end import if( !type_engine_import_class_end( env ) ) return FALSE; somewhere would make a gain stereo. Note that only the 2, 2 and the UGen_Stereo make the difference. Also from my first impressions, LiSa, sndbuf etc. don't use UGen_Multi or UGen_Stereo. So for such things they seem to be missing features. I think, one problem is that the number of channels is an attribute of a type. Most things in chuck are dynamic, so making the number of channels fixed when creating the type object doesn't make sense to me.
Well... LiSa has a lot of voices for playback (see the explanation in the /examples/special/readme_lisa2.ck (or similar) file. To set the loop-end of voice 3 to a second;
ok, the voices are a special thing, I didn't take them into account. C++'s polymorphic functions are often a problematic concept. Perhaps rateVoice would be a better name. Or e.g. my_lisa.voice(v).rate(2.0) would make it more clear.
from. This is uniform with other ChucK functions where dropping the parameter turns it into a "get" function, like;
<<< my_sinosc.freq() >>>;
I think this type of polymorphic functions is generally ok. But mixing another polymorphic kind is not. I think, different types of numbers should be considered similar, especially when automatic conversions exist.
Hope this clarifies,
yes, thanks btw. should I've written some of the low level developer topics to chuck-dev? I wrote it here, because chuck-dev seems to be dead. Where do the devs meet?
Harald; works correctly on all three versions, as you see also adc.chan(0) =>
dac.chan(0) works .
Ok, so then it's a LiSa issue and hopefully Dan will have a moment to look into it. I think Dan was experimenting with multi-channel looping and this seems to be a side-effect of that. I got confused when looking at sndbuf's code. lisa should be similar.
How is the multichannel code supposed to work? LiSaMulti_tick didn't change from 1.2.1.3 to current, so the problem must be elsewhere.
Hmmmm. I think LiSa is quite independent of SndBuf and is instead based on a Max/Msp tool. somewhere would make a gain stereo. Note that only the 2, 2 and the
UGen_Stereo make the difference. Also from my first impressions, LiSa, sndbuf etc. don't use UGen_Multi or UGen_Stereo. So for such things they seem to be missing features. I think, one problem is that the number of channels is an attribute of a type. Most things in chuck are dynamic, so making the number of channels fixed when creating the type object doesn't make sense to me.
Yes, that sounds sensible to me. ok, the voices are a special thing, I didn't take them into account.
LiSa is really way more involved than the rest, more powerful but also a bit more tricky to understand.
C++'s polymorphic functions are often a problematic concept. Perhaps rateVoice would be a better name. Or e.g. my_lisa.voice(v).rate(2.0) would make it more clear.
Yes, but at the expense of uniformity. Personally I'm very much in favour of keeping things uniform as that means there are less surprises and there is less to learn. I can see how this would be a topic for debate though.
btw. should I've written some of the low level developer topics to chuck-dev? I wrote it here, because chuck-dev seems to be dead. Where do the devs meet?
I feel all of this should be fine here. The dev-list is where the dev discussion "should" go but for some reason it isn't. I don't know. :-) Yours, Kas.
If any UGen is placed after lisa.chan(0), lisa.pan will not behave predictably in stereo. You'll need separate UGens to follow LiSa. Something like: lisa.chan(i) => gain[i] => dac.right and so forth. *********** Van Stiefel Director, Center for Music Technology West Chester University Assistant Professor, Department of Theory and Composition Swope Music Building College of Visual and Performing Arts West Chester, PA 19383 ________________________________ From: chuck-users-bounces@lists.cs.princeton.edu [chuck-users-bounces@lists.cs.princeton.edu] on behalf of Kassen [signal.automatique@gmail.com] Sent: Sunday, April 10, 2011 9:04 AM To: ChucK Users Mailing List Subject: Re: [chuck-users] record and play multiple LiSa objects on multiple channels Harald; works correctly on all three versions, as you see also adc.chan(0) => dac.chan(0) works . Ok, so then it's a LiSa issue and hopefully Dan will have a moment to look into it. I think Dan was experimenting with multi-channel looping and this seems to be a side-effect of that. I got confused when looking at sndbuf's code. lisa should be similar. How is the multichannel code supposed to work? LiSaMulti_tick didn't change from 1.2.1.3 to current, so the problem must be elsewhere. Hmmmm. I think LiSa is quite independent of SndBuf and is instead based on a Max/Msp tool. somewhere would make a gain stereo. Note that only the 2, 2 and the UGen_Stereo make the difference. Also from my first impressions, LiSa, sndbuf etc. don't use UGen_Multi or UGen_Stereo. So for such things they seem to be missing features. I think, one problem is that the number of channels is an attribute of a type. Most things in chuck are dynamic, so making the number of channels fixed when creating the type object doesn't make sense to me. Yes, that sounds sensible to me. ok, the voices are a special thing, I didn't take them into account. LiSa is really way more involved than the rest, more powerful but also a bit more tricky to understand. C++'s polymorphic functions are often a problematic concept. Perhaps rateVoice would be a better name. Or e.g. my_lisa.voice(v).rate(2.0) would make it more clear. Yes, but at the expense of uniformity. Personally I'm very much in favour of keeping things uniform as that means there are less surprises and there is less to learn. I can see how this would be a topic for debate though. btw. should I've written some of the low level developer topics to chuck-dev? I wrote it here, because chuck-dev seems to be dead. Where do the devs meet? I feel all of this should be fine here. The dev-list is where the dev discussion "should" go but for some reason it isn't. I don't know. :-) Yours, Kas.
2011/4/10 Stiefel, Van
If any UGen is placed after lisa.chan(0), lisa.pan will not behave predictably in stereo.
Wait! Since when has LiSa had .chan(n) and .pan member functions? What do they do? Why wasn't this send to the LiSa Fanclub Newsletter? This sounds very exciting. Kas.
it doesn't all work properly yet, hence nothing about it... some general chuck multichannel issues need to be resolved... On Apr 10, 2011, at 4:14 PM, Kassen wrote:
2011/4/10 Stiefel, Van
If any UGen is placed after lisa.chan(0), lisa.pan will not behave predictably in stereo. Wait! Since when has LiSa had .chan(n) and .pan member functions? What do they do? Why wasn't this send to the LiSa Fanclub Newsletter? This sounds very exciting.
Kas. _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Kas (this is your name, right?),
ok, the voices are a special thing, I didn't take them into account.
LiSa is really way more involved than the rest, more powerful but also a bit more tricky to understand.
I first learned about LiSa as a recorder. Which is why I didn't expect things like the voices. Then I learned that LiSa is more a flexible sample player than a recorder. Currently I am re-visiting the WvOut and WaveLoop ugens. At the beginning when I didn't know much of chuck I made a silly mistake, which made me think I couldn't use them for my purpose. But now I found that they work well for me. LiSa is very nice for playing the same sample in multiple ways (different frequency etc.), but for my project it is a little oversized.
C++'s polymorphic functions are often a problematic concept. Perhaps rateVoice would be a better name. Or e.g. my_lisa.voice(v).rate(2.0) would make it more clear.
Yes, but at the expense of uniformity.
hmm, I don't think. Lisa's voices are special, no other ugens have them, right? Looking at lisa's concept there wouldn't be a rate() or rate(float), these are shortcuts for rate(0) or rate(0, float). So the problem is generated by two kinds of polymorphism.
Personally I'm very much in favour of keeping things uniform as that means there are less surprises and there is less to learn.
I agree...but then the shortcut isn't really needed.
I feel all of this should be fine here. The dev-list is where the dev discussion "should" go but for some reason it isn't. I don't know. :-)
ok, better some traffic, than none :-) what do others think? Are you bothered by such discussions?
Harald, Kas (this is your name, right?),
Sure. My full first name is "Kassen", and signing as "Kas" seems nicely informal.
I first learned about LiSa as a recorder. Which is why I didn't expect things like the voices. Then I learned that LiSa is more a flexible sample player than a recorder.
Yes, it stands for LIve SAmpling. You can look at it as a looper (as in guitar loopers) or a simple sampler or a granulation tool. The technique is a fairly classical computer music one.
Currently I am re-visiting the WvOut and WaveLoop ugens. At the beginning when I didn't know much of chuck I made a silly mistake, which made me think I couldn't use them for my purpose. But now I found that they work well for me. LiSa is very nice for playing the same sample in multiple ways (different frequency etc.), but for my project it is a little oversized.
I think so, yes.
hmm, I don't think. Lisa's voices are special, no other ugens have them, right?
As I see it the core "special" thing here is UGen member functions taking two parameters and the extra convenience trick of being allowed to not specify the voice if you only need the first. As I see it the confusion arises from permitting that shortcut. Maybe that was a dubious choice but the convenience might be worth it? I don't know.
I agree...but then the shortcut isn't really needed.
No, not "needed" as such, but after writing some pages of code that makes ChucK look like a "scripting extension to LiSa" you come to appreciate it. :-) You do have a point and as I mentioned; I ran into it too, once. It's a hard to detect mistake. One big question here is that I can't see a alternative that would be clearly better in all ways yet not break existing code. Tricky stuff. Yours, Kas.
Sure. My full first name is "Kassen", and signing as "Kas" seems nicely informal.
ok, how should *I* call you ? :-) I tend to use Kas, because you're nice and this feels like a nick name
You do have a point and as I mentioned; I ran into it too, once. It's a hard to detect mistake. One big question here is that I can't see a alternative that would be clearly better in all ways yet not break existing code. Tricky stuff.
I will never make this mistake again (I hope), so it's not for me, but for the next users falling into the trap :-) at least it would be nice to document it
participants (5)
-
Daniel Trueman
-
Daniel Trueman
-
Harald Gutsche
-
Kassen
-
Stiefel, Van