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