How to write multi-dimensional FloatArray to SoundFile

I use SuperCollider to write data directly into SoundFiles. The usual process is to get the data into a FloatArray, and then write that into the SoundFile (I don’t worry about the numbers being over 1 below -1, because afterwards I open it in a sound editor and Normalize/DC Offset).

Here’s the example, reduced to the parts I am unable to get to work. The resulting SoundFile should have [1,4,7] in the first channel, [2,5,8] in the second, etc.

a = [ [ 1, 4, 7 ], [ 2, 5, 8 ], [ 3, 6, 9 ] ].asFloat;
b = a.as(FloatArray); //fails
b = Array.fill(3, {|i| a[i].as(FloatArray)});  //works, but then doesn't work when writing to a SoundFile

f = SoundFile.new.headerFormat_("AIFF").sampleFormat_("float").numChannels_(3);
f.openWrite("/Users/Me/Downloads/snippet.aif");
f.writeData(b);
f.close

a.as(FloatArray) gives me the error: ERROR: Primitive ‘_ArrayAdd’ failed. Wrong type.

so I tried to make an Array of FloatArrays, b = Array.fill(3, {|i| a[i].as(FloatArray)}) which works, but SoundFIle doesn’t like it, giving the error: ERROR: Primitive ‘_SFWrite’ failed. Wrong type.

b = a.at(0).as(FloatArray) works, and I can write to a SoundFile with it (just change numChannels =1)

How do I write this multichannel array of numbers into a SoundFile? It doesn’t seem possible to make a multidimension FloatArray, and an Array of FloatArrays also doesn’t work.

-Andy

b = a.lace(3 * 3).as(FloatArray);  // channels * frames

Now b is ready to write into the sound file.

hjh

That just gives me a single FloatArray with all three arrays combined. I’m trying to make a multi-channel SoundFIle, each array is a separate channel, and so I need to write multiple FloatArrays.
Channel 1 = [1,4,7]
Channel 2 = [2,5,8]
Channel 3 = [3,6,9]

an Array of FloatArrays doesn’t work, and it seems like a FloatArray containing three FloatArrays isn’t allowed.
I can do each channel separately and combine them later in an external sound editor, but it would be much more convenient if I can do it in SuperCollider.
I’m using rather large data sets, and each data value becomes a new sample. 44,100 rows of data will give me 1 second of audio, etc. The resulting audio files are several minutes long, and it takes the computer ten or fifteen minutes for each data file.
In my above example (Channel 1 = [1,4,7]), the resulting file would be 3 samples long for instance.

A sound file is always a single stream of numbers.

When it’s multichannel, the channels are interleaved:

  • frame 0 channel 0
  • frame 0 channel 1
  • frame 0 channel 2
  • frame 1 channel 0
  • frame 1 channel 1
  • frame 1 channel 2
  • etc

The formula I gave you puts the numbers in that order.

You cannot write any type of multidimensional array to a soundfile. You can specify the number of channels before opening the file for writing, and write a flat, interleaved series of sample values.

hjh

This is very interesting; I did not know that about multichannels being interleaved. Of course I’ve heard of “interleaved PCM” etc but only now am I connecting it with writing a soundfile in Supercollider.
This actually saves me a few steps, because this particular data comes already interleaved and I had been seperating it into different arrays doing .clump(3).fold
Thank you, your help is much appreciated!