FluidBufSTFT windowsizes above 1024 don't work

Hi,

in the example below i get a message like:

File '/tmp/-977233400' could not be opened: Format not recognised.

if i use a power of 2 greater than 1024.
256, 512, 1024 work fine, but 2048, 4096 etc. give the above message when i execute the last line.

(
b = { PinkNoise.ar }.asBuffer(1);
m = Buffer.new;
p = Buffer.new;
)

(
fork{
	var wsize = 2048; 
	FluidBufSTFT.process(s,source:b,magnitude:m,phase:p,windowSize: wsize).wait;
	"Done".postln;
}
)

m.loadToFloatArray(action: {|x| x.size.postln})

I am using the beta2, SuperCollider 3.11.2, operating system UbuntuStudio 21.04

Welcome @vmx and thanks for the report. I can reproduce on Mac OS. The problem seems to be that Buffer#write is failing to produce a file. Streaming with

m.getToFloatArray(action: {|x| x.size.postln})

works for me, but with load, I get the same error and the tmp file is missing.

It could be that there’s a maximum channel count in the scsynth file writing that gets exceeded for FFT sizes > 1024. I’ll make an issue on Github and have a closer look when I can.

Issue at

This turns out to be a (hard) limit in libsndfile, so I don’t think there’s any prospect of getting loadToFloatArray to work when the Buffer has > 1024 channels. The immediate workaround would be to use getToFloatArray, and stream in chunks if needed (which is fiddly, I know).

Medium-term, there might be a way of enabling an alternative file format for Buffers that are more matrix-like by adding a new scsynth cmd and a corresponding method to sclang Buffer. If anyone has Opinions on what such a file format might usefully be, then do offer suggestions (or PRs :grin:)

When we decided on the interface I’m pretty certain we checked that it works… what we didn’t check are the Buffer class limitation when importing back to the language indeed!

@spluta has proposed a workaround which is good: using another file format to do the tmp file, as sort of better loadToFloatArray . If you feel like a bandit, you can change line 282 of Buffer.sc, which is what I’ll do right now to check it quickly. Stay tuned!

ok a few bad news, in order:

  1. not a problem on Linux but on Mac one shouldn’t change the internals of a signed app :smiley:

  2. even just trying to save via m.write("/tmp/testwav.wav", "W64", "float") SC is not happy with the number of channels…

  3. so I went in the SC source code to check and indeed @weefuzzy was right as always: it depends on libsndfile…

  4. so I went on the libsndfile API ref page and found this sentence:

Note: The libsndfile library will reject values ​​for samplerate field that are greater than 655350 and values ​​for field channels that are greater than 1024. These values ​​represent the maximum theoretical limit and may be less for specific formats.

So this is a hardwired scsynth limitation.

  1. To be complete, I made a quick test in Max. I was able to write it, and check its specs with afinfo and Reaper. Indeed the libsndfile-based sndfile-info recognised the header of 1025 channels but calls it an error.

So our options are, in order of dreaming to gaffataping:

  1. we lobby libsndfile to remove that limitation
  2. we lobby sc to use another sound file i/o library
  3. we think hard and might be able to find a workaround Buffer’s native i/o to the language
  4. we use our amazing FluidBufCompose and import it in batches of ‘only’ 1024 channels. Since scsynth is able to deal with large channel count, one could query the channel count and copy to a temp buffer…

But I think I have another idea, stay tuned!

ok my ‘good idea’ didn’t work. So plan #4 above, i.e. splitting with BufCompose to go around sc limitation is your best bet for now.

I hope this help!

Thanks for the thorough investigation of the issue! Using getToFloatArray instead of loadToFloatArray works out nice for me.

2 Likes