Buffer onset analysis

Is there a way to get the timing of onsets in a buffer (not in real time)?

There are a few good onset detections UGens - Coyote and Onsets come to mind. You might try the OfflineProcess quark (Quarks.install("https://github.com/scztt/OfflineProcess.quark")) as a wrapper around non-realtime processing of audio for this kind of thing:

~detectOnset = OfflineProcess();

// sig argument is the signal from your audio file, time is time in the file
	// for putTrig, you output an array with a trigger and a value
	// in this case, just output time
~detectOnset.putTrig(\onsets, {
	|sig, time| 
	var onset = Coyote.kr(sig);
	[onset, time];	
});

fork {
	~run = ~detectOnset.process("/path/to/an/audio/file.wav");
	~run.wait();
	~onsets = ~run.resultData(\onsets).postln;
}
3 Likes

I didnā€™t know about OfflineProcess, thank you!

Hi @scztt,

Iā€™m trying to adapt this code to trim the beginnings off of a batch of short files and am getting the error ā€œFile ā€˜ā€™ could not be opened: System error : No such file or directory.ā€ I think this is because Iā€™m not making my PathName legible to OfflineProcess, but am not totally sure. Any ideas?
Thanks in advance!

(
fork{

		var file, buf, detectOnset, run, startFrame;

		file = PathName("/path/to/folder/").folders[1].files[12].fullPath;

		buf = Buffer.read(s, file, bufnum: 200);

		detectOnset = OfflineProcess();

		detectOnset.putTrig(\onsets, {
			|sig, time|
			var onset = Coyote.kr(sig);
			[onset, time]
		});

		run = detectOnset.process(file);
		run.wait();
		startFrame = run.resultData(\onsets).flat[0] * SampleRate.ir;

		s.sync;

		buf.write("/path/to/new/folder/" ++ 0 ++ "/" ++ 0 ++ ".wav", "wav", "int16",  numFrames: 16000 - startFrame, startFrame: startFrame);

	};
)

Currently (AFAICS) the path to read must be a String. PathName is not allowed directly.

PathName is rather poorly supported currently. There was some talk of moving all path operations into it and making sure itā€™s allowed everywhere that a path is expected, but I donā€™t think anyone is working on that now. TL;DR my personal opinion is to avoid PathName for the time being.

You might try calling asAbsolutePath on the PathName where itā€™s used in method calls. Iā€™m not sure if that will work though.

Missed your fullPath ā€“ sorry.

What is odd to me is the '' in the error messageā€¦ Iā€™m not clear why the path isnā€™t being transmitted in the OSC message.

hjh

Ah, for some reason it doesnā€™t like having SampleRate.ir as a multiplier for startFrame. I donā€™t understand why that is, but replacing it with 44100 solved the issue.

That part of the code isnā€™t on the server, so you would do s.sampleRate for the same result.

Sam

1 Like