Hi I have (and have had for as long as I can remember) problems with SndBuf. I'm pretty sure the trouble is when loading a sample, then there will most often be a small but very noticeable hickup. It's quite bad with larger samples but also there with even small samples. Generally; the larger the sample, the greater the hickup. The problem seems to be gone or almost gone when the sample has already been loaded once, but this might be due to caching in the underlying os. I've tested with both alsa and jack, and all kinds of combinations of buffersizes and what have you, but although the problem seems the vary a bit (in an unpredictable pattern) it's always there. I also tested both syntaxes ("sample" => s.read and s.read("sample")), however only with wav files. I also tried both in miniAudicle and commandline chuck. Needless to say this makes SndBuf useless on my system :-( Is this a result of me doing something wrong or a bug in chuck? In any case is there anything I can do to remedy this right now? If it's a bug, I'd be most happy to help in any way I can with getting it fixed as soon as the developers time permits. BTW: This is under linux (debian/stable) on a IBM T41, 1.6Ghz, 1G ram and 7200 RPM HD. The system is running with a realtime patched kernel and is capable of playing back 20+ tracks in ardour with effects + various soft synths running along in realtime without a single xrun or glitch. Here's a simple example of something that shows the problem: http://atte.dk/download/sndbuf_test.tgz. First run shaker.ck, then after a while add substitution.ck (a beat => big hickup) or sd.ck (a snare drum => small hickup). -- peace, love & harmony Atte http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions
Hey Atte,
This is a known issue-- by default, SndBuf reads the entire file
immediately when you specify the file path. Due to ChucK's
strong-timing, this will stop audio processing until the file has
finished loading from the disk into memory, which is typically long
enough to underflow the audio buffer and cause audible hiccuping.
Probably the best solution is to use the .chunks parameter-- you can
use this to load audio frames on demand instead of all at once. E.g.
SndBuf b;
1024 => b.chunks;
"cowbell.wav" => b.read;
will specify that the file is read 1024 frames at a time when those
frames are needed, instead of all at once. See
http://chuck.cs.princeton.edu/doc/program/ugen_full.html#sndbuf
for more details. You might need to experiment with different values
for .chunks, but that should be able to make the hiccuping go away.
spencer
Quoting Atte André Jensen
Hi
I have (and have had for as long as I can remember) problems with SndBuf. I'm pretty sure the trouble is when loading a sample, then there will most often be a small but very noticeable hickup. It's quite bad with larger samples but also there with even small samples. Generally; the larger the sample, the greater the hickup.
The problem seems to be gone or almost gone when the sample has already been loaded once, but this might be due to caching in the underlying os.
I've tested with both alsa and jack, and all kinds of combinations of buffersizes and what have you, but although the problem seems the vary a bit (in an unpredictable pattern) it's always there. I also tested both syntaxes ("sample" => s.read and s.read("sample")), however only with wav files. I also tried both in miniAudicle and commandline chuck.
Needless to say this makes SndBuf useless on my system :-(
Is this a result of me doing something wrong or a bug in chuck? In any case is there anything I can do to remedy this right now? If it's a bug, I'd be most happy to help in any way I can with getting it fixed as soon as the developers time permits.
BTW: This is under linux (debian/stable) on a IBM T41, 1.6Ghz, 1G ram and 7200 RPM HD. The system is running with a realtime patched kernel and is capable of playing back 20+ tracks in ardour with effects + various soft synths running along in realtime without a single xrun or glitch.
Here's a simple example of something that shows the problem: http://atte.dk/download/sndbuf_test.tgz. First run shaker.ck, then after a while add substitution.ck (a beat => big hickup) or sd.ck (a snare drum => small hickup).
-- peace, love & harmony Atte
http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
hi all
SndBuf b; 1024 => b.chunks; "cowbell.wav" => b.read; aah, that's a great hint spencer.
on windows it also helps when you increase the latency. which isn't that great at all, but helped me avoiding the glitches. let's have a look how much i can decrease the latency now with this setting :-)) thanks /moudi
-----Ursprüngliche Nachricht----- Von: chuck-users-bounces@lists.cs.princeton.edu [mailto:chuck-users-bounces@lists.cs.princeton.edu] Im Auftrag von ssalazar@CS.Princeton.EDU Gesendet: Dienstag, 12. Juni 2007 22:36 An: chuck-users@lists.cs.princeton.edu Betreff: Re: [chuck-users] SndBuf causes hickup
Hey Atte, This is a known issue-- by default, SndBuf reads the entire file immediately when you specify the file path. Due to ChucK's strong-timing, this will stop audio processing until the file has finished loading from the disk into memory, which is typically long enough to underflow the audio buffer and cause audible hiccuping. Probably the best solution is to use the .chunks parameter-- you can use this to load audio frames on demand instead of all at once. E.g.
SndBuf b; 1024 => b.chunks; "cowbell.wav" => b.read;
will specify that the file is read 1024 frames at a time when those frames are needed, instead of all at once. See http://chuck.cs.princeton.edu/doc/program/ugen_full.html#sndbuf for more details. You might need to experiment with different values for .chunks, but that should be able to make the hiccuping go away.
spencer
Quoting Atte André Jensen
: Hi
I have (and have had for as long as I can remember) problems with SndBuf. I'm pretty sure the trouble is when loading a sample, then there will most often be a small but very noticeable hickup. It's quite bad with larger samples but also there with even small samples. Generally; the larger the sample, the greater the hickup.
The problem seems to be gone or almost gone when the sample has already been loaded once, but this might be due to caching in the underlying os.
I've tested with both alsa and jack, and all kinds of combinations of buffersizes and what have you, but although the problem seems the vary a bit (in an unpredictable pattern) it's always there. I also tested both syntaxes ("sample" => s.read and s.read("sample")), however only with wav files. I also tried both in miniAudicle and commandline chuck.
Needless to say this makes SndBuf useless on my system :-(
Is this a result of me doing something wrong or a bug in chuck? In any case is there anything I can do to remedy this right now? If it's a bug, I'd be most happy to help in any way I can with getting it fixed as soon as the developers time permits.
BTW: This is under linux (debian/stable) on a IBM T41, 1.6Ghz, 1G ram and 7200 RPM HD. The system is running with a realtime patched kernel and is capable of playing back 20+ tracks in ardour with effects + various soft synths running along in realtime without a single xrun or glitch.
Here's a simple example of something that shows the problem: http://atte.dk/download/sndbuf_test.tgz. First run shaker.ck, then after a while add substitution.ck (a beat => big hickup) or sd.ck (a snare drum => small hickup).
-- peace, love & harmony Atte
http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
ssalazar@CS.Princeton.EDU wrote:
SndBuf b; 1024 => b.chunks; "cowbell.wav" => b.read;
Is there any greater truth hidden in the fact that you don't connect b to dac above?
You might need to experiment with different values for .chunks, but that should be able to make the hiccuping go away.
Thanks for the great explanation, it all makes very much sense. However I'm still not able to even notice any difference (I tried with 256, 512, 1024 and 2048) from not using chunks. And I did remember to but the =>.chunks before the load... Where to go from here? -- peace, love & harmony Atte http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions
Quoting Atte André Jensen
Is there any greater truth hidden in the fact that you don't connect b to dac above?
Nope.
Where to go from here?
Hmm, thats surprising... the backup solution is to load all of the SndBuf's that you could possibly need in advance, before the your patches do any actual synthesis. That way there can't be any hiccuping because there is nothing to hiccup. This is pretty easy in a single file program-- just load the SndBufs before you advance time. For ChucK programs that involve multiple ChucK files going in and out of the virtual machine and loading different WAV files, you could probably create some public class with an array of static SndBufs that get loaded at the very beginning. Then, instead of creating SndBufs on the fly, just access the public class static members. This should cover a lot of potential usages of SndBuf, but definitely not all of them. spencer
-- peace, love & harmony Atte
http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
ssalazar@CS.Princeton.EDU wrote:
Hmm, thats surprising...
I tried more values of chunks and have some improvement at 16 => chunks. Will report back after more testing. -- peace, love & harmony Atte http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions
Atte André Jensen wrote:
I tried more values of chunks and have some improvement at 16 => chunks. Will report back after more testing.
I didn't try the preloading suggestion yet, but I suspect it will work, although it's a little clumsy. However I still didn't manage to get consistently satisfactory results with chunks. But now I'm wondering how SndBuf is performing for other people esp on osx or windows? Is it only on linux something is wrong? Actually my logic tells me chunks is not doing anything. Setting it low (like 4) should read 4 frames (whatever that is) every time it's needed, that is 4 frames have been played back. So it's very surprising to me that the hickup is when at the read() and not distributed throughout the first playback of the file... I'll see if I can find the time to dig into the source tonight... -- peace, love & harmony Atte http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions
Here's what I do when using SndBuf:. This is just a quick and dirty copypasta of a random old project, so replace the files with any random percussive sounds you have, and something interesting should arise. :P I commented the important parts. // load the samples into a SndBuf array. SndBuf a[7]; "pan01.wav" => a[0].read; "pan02.wav" => a[1].read; "pan03.wav" => a[2].read; "pan04.wav" => a[3].read; "pan05.wav" => a[4].read; "pan06.wav" => a[5].read; "pan07.wav" => a[6].read; PRCRev rvb; .2 => rvb.mix; PitShift pt; .9 => pt.mix; 1 => pt.shift; // quickly set all to their last sample and initialize each processing path. // this keeps the samples from playing immediately when opened. for( 1 => int i; i < a.cap(); i++ ){ a[i].samples() => a[i].pos; a[i] => pt => rvb => dac; } // set pos of sample to 0 to play it. fun void plyy(int d){ 0 => a[d].pos; } fun void ply(int d, float r){ for(0 => int i; i < (r $ int); i++){ spork ~ plyy(d); (a[d].samples() / (r $ float))::samp => now; } } SinOsc lfo; .1 => lfo.freq; lfo => blackhole; Chorus ch; .1 => ch.modFreq; .5 => ch.modDepth; .2 => ch.mix; SawOsc lead1 => ADSR le => ch => rvb => dac; .3 => lead1.gain; le.set(50::ms, 200::ms, .5, 500::ms); 1 => float m; while(1){ Std.mtof(Std.rand2(30,40)) => lead1.freq; le.keyOn(); spork ~ ply(6,2*m); 400::ms => now; spork ~ ply(5,2*m); spork ~ ply(1,1*m); 350::ms => now; spork ~ ply(3,2*m); spork ~ ply(5,1*m); le.keyOff(); 400::ms => now; Std.mtof(Std.rand2(30,40)) => lead1.freq; le.keyOn(); spork ~ ply(2,2*m); spork ~ ply(4,2*m); 400::ms => now; le.keyOff(); lfo.last()/10 + pt.shift() => pt.shift; // 0.5 +=> m; <<< m >>>; } -Drew Atte André Jensen wrote:
Atte André Jensen wrote:
I tried more values of chunks and have some improvement at 16 => chunks. Will report back after more testing.
I didn't try the preloading suggestion yet, but I suspect it will work, although it's a little clumsy. However I still didn't manage to get consistently satisfactory results with chunks.
But now I'm wondering how SndBuf is performing for other people esp on osx or windows? Is it only on linux something is wrong? Actually my logic tells me chunks is not doing anything. Setting it low (like 4) should read 4 frames (whatever that is) every time it's needed, that is 4 frames have been played back. So it's very surprising to me that the hickup is when at the read() and not distributed throughout the first playback of the file...
I'll see if I can find the time to dig into the source tonight...
Drew Jaworski wrote:
Here's what I do when using SndBuf:. This is just a quick and dirty copypasta of a random old project, so replace the files with any random percussive sounds you have, and something interesting should arise. :P
I'm still not able to get satisfying results. With something similar to your example I use about 25% for miniAudicle without doing anything (except having the samples loaded). Might be because I have the SndBuf's connected to dac. This is getting too complicated for me. However a friendly geek from my local LAU suggested "cat *.wav > /dev/null". This *really* works. I just did a small test, but it seems I can now use SndBuf with jack latency at 4.6ms (maybe lower didn't try) without a glitch. A no .chunks, or nothting, just regular =>load, =>pos. And I can of course cat to /dev/null while miniAudicle is running without disrupting the playback either! I realize and appreciate the decision about not caring too much about performance in chuck, but would you say that not being able to use SndBuf in the ways I tried is acceptable performance? Would you (the developers) consider looking at SndBuf implementation, esp under linux, again to see if everything is like it should be? Please :-) Anyways, if my trick proves to work as well as my tests suggests, I'll keep on using it until chuck gets better SndBuf performance. It seems cleaner, doesn't require extra chuck code to be written or concepts to be considered and it doesn't interfer with other aspects of chucks performance. I hope this helps others in similar situations :-) -- peace, love & harmony Atte http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions
this is true: if you just connect the SndBufs to the dac as you need them and disconnect them when not using them they go to sleep and don't hog the cpu.... dt On Jun 14, 2007, at 2:42 PM, Atte André Jensen wrote:
I'm still not able to get satisfying results. With something similar to your example I use about 25% for miniAudicle without doing anything (except having the samples loaded). Might be because I have the SndBuf's connected to dac. This is getting too complicated for me.
Atte André Jensen wrote:
Drew Jaworski wrote:
Here's what I do when using SndBuf:. This is just a quick and dirty copypasta of a random old project, so replace the files with any random percussive sounds you have, and something interesting should arise. :P
I'm still not able to get satisfying results. With something similar to your example I use about 25% for miniAudicle without doing anything (except having the samples loaded). Might be because I have the SndBuf's connected to dac. This is getting too complicated for me.
However a friendly geek from my local LAU suggested [...]
Just another friendly, geeeky, explanation of what you're seeing -- when you cat everything to /dev/null, that effectively puts all of those samples into memory. The operating system has to read all of the files, even to write their contents to a fake device, and they stay in a special place in memory called disk cache until that memory is needed for something else. However, that's not connected to CPU performance; it's much more connected to hard drive speed and more specifically how the OS prioritizes different operations and how much of the file system information it keeps in memory. The first time that you open those files, the hard disk has to spin up, figure out where those files are, open them and start reading data. Many file systems on Linux typically, for things not in the previously mentioned disk cache, are pretty slow doing that. If you think about what's physically happening (a motor starting, a robotic arm moving to the right place). Pretty good average latency for "seek time" on a hard drive, not counting OS overhead, is about 10 ms -- which is notably longer than 4 or 5 that you're trying to achieve -- and that's per file. Solving that either means pre-fetching those files into memory (either explicitly by the user or automatically or using a trick like the "cat" above). Pre-allocating buffers before the sound starts, or in a background shred should do the trick. Unfortunately predicting which samples are about to be played is a bit trickier for ChucK than say in a sequencer and even the sequencer that I use (Live) has a button for explicitly placing samples in RAM. -Scott
Scott Wheeler wrote:
Just another friendly, geeeky, explanation of what you're seeing -- when you cat everything to /dev/null, that effectively puts all of those samples into memory.
Yes, I'm aware of that :-)
However, that's not connected to CPU performance; it's much more connected to hard drive speed and more specifically how the OS prioritizes different operations and how much of the file system information it keeps in memory.
I know that, too. My point is just my system seems fast enought, I can do 20+ tracks in ardour (which admittedly knows which samples should be played in advance). And my HD is performing ok: ajstrup:~# hdparm -t /dev/hda4 /dev/hda4: Timing buffered disk reads: 122 MB in 3.01 seconds = 40.47 MB/sec It would be nice if chuck had a way of filling a SndBuf in the background, it should be finished when it's ready but should cause no hickups, and an a possibly with an ability to check at any given time if the reading has been completed. -- peace, love & harmony Atte http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions
chuck-users-bounces@lists.cs.princeton.edu mailto:chuck-users-bounces@lists.cs.princeton.edu per conto di Atte André Jensen
It would be nice if chuck had a way of filling a SndBuf in the background, it should be finished when it's ready but should cause no hickups, and an a possibly with an ability to check at any given time if the reading has been completed.
This doesn't seem a practical suggestion: what's the benefit of knowing that when a SndBuf needs to be played it isn't ready and buffer hiccup is likely? Deciding to play something else instead of a SndBuf that is late is a significant complication (particularly bad for live coding) and a compromise of the original idea for purely technical reasons (bad for music); it might be a suitable and interesting technique for some of your projects but it cannot be considered a general solution. What could be acceptable is a way to ask for bulk loading of a sample but promise ChucK that we aren't going to play it before a specified time; this added flexibility would allow sensible scheduling, e.g. the earliest deadline first algorithm, with the effect of limiting hiccups to occasional combinations of slow disks (not the software's fault) and unreasonable requests (also not the software's fault). Regards, Lorenzo Gatti
Gatti Lorenzo wrote:
This doesn't seem a practical suggestion: what's the benefit of knowing that when a SndBuf needs to be played it isn't ready and buffer hiccup is likely? Deciding to play something else instead of a SndBuf that is late is a significant complication (particularly bad for live coding) and a compromise of the original idea for purely technical reasons (bad for music); it might be a suitable and interesting technique for some of your projects but it cannot be considered a general solution.
Point taken. I was just trying to think out loud.
What could be acceptable is a way to ask for bulk loading of a sample but promise ChucK that we aren't going to play it before a specified time;
Sounds sane. Basically I guess I'd be happy with anything that'll allow me to play samples a little bit better than today :-) -- peace, love & harmony Atte http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions
Hi Atte and all! It's about time SndBuf gets another look - we are definitely aware of the performance limitations of SndBuf - the current workaround (if it's fits your needs) is to read in most of the SndBuf at startup, and then, as Dan suggested, connect/disconnect the necessary SndBuf when needed. Optimizing SndBuf performance is on the high priority list. We hope to have a better answer for ya soon. Best, Ge! On Jun 15, 2007, at 1:36 AM, Atte André Jensen wrote:
Scott Wheeler wrote:
Just another friendly, geeeky, explanation of what you're seeing -- when you cat everything to /dev/null, that effectively puts all of those samples into memory.
Yes, I'm aware of that :-)
However, that's not connected to CPU performance; it's much more connected to hard drive speed and more specifically how the OS prioritizes different operations and how much of the file system information it keeps in memory.
I know that, too. My point is just my system seems fast enought, I can do 20+ tracks in ardour (which admittedly knows which samples should be played in advance). And my HD is performing ok:
ajstrup:~# hdparm -t /dev/hda4 /dev/hda4: Timing buffered disk reads: 122 MB in 3.01 seconds = 40.47 MB/sec
It would be nice if chuck had a way of filling a SndBuf in the background, it should be finished when it's ready but should cause no hickups, and an a possibly with an ability to check at any given time if the reading has been completed.
-- peace, love & harmony Atte
http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://atte.dk/compositions _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
participants (8)
-
Atte André Jensen
-
Daniel Trueman
-
Drew Jaworski
-
Gatti Lorenzo
-
Ge Wang
-
Leuthold Dominik
-
Scott Wheeler
-
ssalazar@CS.Princeton.EDU