has anyone found a way to display a waveform with sfplay yet?
i know this has come up before, but i can't find a satisfying answer at the moment
i'm looking for a way to reliably display my soundfiles while using sfplay~ to play them from disk
as i write here
https://cycling74.com/forums/playback-stutters-while-loading-soundfiles-into-buffer
the groove~/waveform~ combination isn't working so well for me with long, high-resolution soundfiles; the playback starts stuttering or max 6 actually crashes.
in live performance, i rely heavily on the visual feedback of seeing where i am in a soundfile at the moment, and which transient events are coming up next etc.
i've been able to make elapsed/remaining time counters and a progress bar to use with sfplay~, but have had little luck with actually displaying the sounds the past few months
any tips would be highly appreciated, thanks in advance!
What I do is creating in advance a short buffer (1500ms) for each soundfile. To do that, I read the file (much) faster and record the result in a buffer. It looks quite nice.
Then I use sfplay~'s position output to control buffer~'s cursor position.
Here is the patch, which is used in a much bigger patch. It needs 2 arguments (I use 1500 and 1500, in ms, but you may need to tweak that, depending on your hard drive). The message create audiofilepath buffername will fill the buffer with a waveform of the audio file.
Comments are welcome, as I'm not sure it's really reliable!
Here is an *old* patch I posted ... in 2006 (!) in this thread :
https://cycling74.com/forums/displaying-a-waveform-in-a-lcd-bennies/
very similar to Patrick's patch : it creates a buffer~ 50 times smaller than the original sound file.
enjoy
M
hi patrick and mathieu,
thank you very much for the help and the example patches!
patrick, in case you have time to answer a few questions that come up for me when i try your patch:
-where do the two arguments (1500 and 1500) go? i tried putting them in the loadmess objects.
-and the "create audiofilepath buffername" message, where should i send that? i tried sending a message like that into the inlet on the top.
-the [/] and [if] objects are giving me "inlet: wrong message or type" errors
so at the moment, i can't get it to work, but i must admit there are several objects in the patch that i don't fully understand. maybe i'll do better tomorrow morning after some coffee..
mathieu,
your patch is actually pretty much what i've been using the past few years, you're probably where i got the idea from in the first place! thank you for that.
do you happen to know why, most of the time, only the beginning of the waveform is shown?
i don't get any error messages, and your patch is very clear, but unfortunately, most of the time, the waveform won't fully load, and only the first few seconds are shown.
see the attached screenshots.
i'm using 24/96 wav files, mono at the moment, of a few minutes long, on a macbook pro with max 6.
thanks again!
your sfplay~ stops playing probably because your HD is too slow (playing 24/96 wav at 50x speed requires very fast access)
you can try increasing sfplay~ disk buffer size (2nd arg) (Patrick's patch uses 26208000 )
or slow down the playback speed.
...or buy a SSD ;-)
mathieU
you were right! i've increased the sfplay~ disk buffer size to 40.320.000 (it needs multiples of 20160) and for the moment, the patch is displaying any soundfile i'm throwing at it, including half-hour long 24/96 stereo files..
my next machine will be ssd based, but for now this is great, and if it stops working i'll know what to tweak.
thanks again for the very helpful and clear example!
Save the patch I sent before as "waveformAF".
Save the following code as "bufferRuler.js"
// bufferRuler
// Patrick Delges
// Centre Henri Pousseur
// 20130415
mgraphics.init();
mgraphics.relative_coords = 0;
mgraphics.autofill = 0;
var dis_width = mgraphics.size[0]; // size of the jsui
var dis_height = mgraphics.size[1]; //
var bgcolor = [.75, .54, 1.]; // default background color
var theDuration = 0; // size of the buffer (ms)
var intervalWidth = dis_width; // interval (in pixel) between increments
var minuteIncrement = 1; // duration (in minutes) between increments
/*
bufferRulerInstantiate = 0;
function loadbang()
{
if (!bufferRulerInstantiate)
post ("bufferRuler by pdelges@crfmw.be - Centre Henri Pousseur 2013\n");
bufferRulerInstantiate = 1;
}
*/
function bang()
{
mgraphics.redraw();
}
function paint()
{
dis_width = mgraphics.size[0];
dis_height = mgraphics.size[1];
// see https://cycling74.com/forums/onresize-when-a-jsui-in-resized-in-presentation-mode
// the size will be updated both in Patching & Presentation mode
// and in all views.
computeIntervals ();
with (mgraphics)
{
set_source_rgb(bgcolor);
rectangle (0, 0, dis_width, dis_height);
fill();
select_font_face("Arial");
set_font_size(10);
set_line_width (1);
for (x_pos = 0, minute = 0; x_pos = 60000)
{
minuteWidth = dis_width / (theDuration / 60000);
intervalWidth = minuteWidth;
//post ("->" + minuteIncrement + ", " + minuteWidth + "\n");
while (intervalWidth < 25)
{
minuteIncrement++;
intervalWidth += minuteWidth;
}
mgraphics.redraw();
}
else
intervalWidth = dis_width;
}
function labelbgcolor(R, G, B)
{
bgcolor = [R, G, B];
mgraphics.redraw();
}
Then savevand open this patch:
The Javascript UI draws a ruler you can put over the waveform~ ruler.
The difference with Mathieu is that in his solution, the files are always read 50x faster, so if it does work for one file, it will probably work for others.
In my solution, the speed depends on the length of the file, ther idea is to have buffers of constant length (1500 in the example). If it doesn't work, then the buffer size should be increased.
If the file is too short, then it's simply imported.
hi patrick,
thank you very much for the additional info!
i will dive deeper into your patch the coming days and report back - very interesting to have several different approaches to look into.
i would just use a parallel buffer~ with waveform~ as display ...
Hey Patrick,
your js code returns several compile errors after copy pasting. It might be that the forum formatting breaks some characters... (like the "" for instance, which are the same i guess originally, but interpreted by js as 'illegal character'. I have another error after :
jsui: bufferRuler.js: Javascript SyntaxError: missing ; after for-loop condition, line 57
). Could you please maybe upload the thing in a zipped format ?...
no worries, thanks a lot !
I agree Roman's solution may not be optimal (RAM and time wise)
But using a short buffer~ (1500ms in my case), it's not an inefficient solution at all. And you get some UI consistency with buffers.
Using filein is of course an option, but I'm quite happy so far with the way I did it. And I don't have to worry about all audio file formats sfplay~ supports. Call this laziness if you want.
And As I know how to read RIFF files, I really prefer to learn something else :-)
p
Hey Karaokaze, i have to say that here i fully agree wiht Patrick Delges. A 1500 ms buffer is worth ?... maybe 1.5 Mo ? (hah Max has made me too lazy to even calculate this. Or is it because i'm lazy that i use Max ? ;) ) and given our 4Go ram machines it's not much, nearly nothing, and it is a great way to avoid inconveniences that doing it the "clean" way would lead to, as Patrick explained (using waveform~ conveniences and implementing exotic formats). Also, it is more than likely than one would not need a lot of those buffers at once, hence the little embarassment caused by the memory occupation.
In the case you need a lot (i mean hundreds) of those waveforms displayed at once, then, yes, it would be a good idea to begin doing an external.
:)
Hi karaokaze, your tip and info is very interesting, I've tryed your solution but I can only visualize the first chunks of an aif file (the words FORM AIFF and COMM), but I cannot figure out how to extract the audio data from the file using the obj filein. Please can you help with a normal abstraction?
Thanks a lot
Italo
Hi Raja! WOW, Many thanks for your additional infos! Will study it!
This is my test patch:
Hi Rja_....many many thanks!!! That's abolutely interessant. What I'm searching for in this moment, is a way to extrapolate bitwise a writed audio smpte stream (the 80 bits to convert in h:m:s.f), and as just explained, the way to display a waveform without using the buffer or plot way in MaxMSP.
At this moment I'm not able to write a js or mxj patch, or to build a external in C or C++, so I have to learn before how to do it with abstractions...and I'm not so young to learn all that stuff in little time.
Grazie mille!
Italo
(
'karaokaze' is another one of my mischievous accounts >8D
:
i knew there was something fishy with that Karaokaze guy ! )