Much faster channelPeaks client-side

If you’ve used SoundFile.channelPeaks you’ve probably discovered how slow it is. It seems it’s so slow because it’s a sclang loop.

I found a much quicker way to do the same using Signal.peak which has an underlying primitive (C++) implementation. The only slight inconvenience is that peak only works on a single channel data. Signal in general didn’t seem to get much love as it doesn’t really have a concept of channels. And it’s not feasible to load just one channel of a file on the client. While Buffer has readChannel there’s no equivalent on the client.

But it turns out that even copying arrays as slices is much faster (probably done as a primitive) than any sclang loop. So something like

f = SoundFile.openRead(...) // stereo file here
z = Signal.newClear(f.numFrames * f.numChannels)
f.readData(z)
z.peak // single value (largest amp of both channels)

z.numChannels // 1
z.numChannels = 2 // can't set though!!

z[0, 2..].peak // works fast and per left channel!
z[1, 3..].peak // ibid, right

is approximately an order of magnitude faster than f.channelPeaks.

4 Likes

@Avid_Reader, the SignalBox quark includes a method to read a single channel of a soundfile into a Signal, which could be helpful.

If you have a look at the source code you can see we’re using SoundFile under the hood.

Given the performance noted, there could be an argument to refactor SoundFile.channelPeaks

1 Like