zorgas
zorgas

Reputation: 31

Save to audio file with OpenAL

I am using OpenTK, more precisely OpenAL. I am able to capture the sound from the mic, but then I want to save the data to a WAVE file.

I found a example how to write a wave file and the result is almost working.

I believe my file header is correct, but I have some doubt of the correct way to write the buffer data to the file.

I first tried recording with this settings:

Playing the file was just some noise

I changed to a mono setting (1 channel). This time I was able to reproduce the audio, but it was played 2 times faster

Is it possible that I should first transform the data from ALC.CaptureSamples before writing them directly to the stream ?

To add some code, first I have the capture samples, that I think work correctly (I got from the TestUnit from OpenAL repo):

int totalSamples = 0;
while (totalSamples < buffer.Length && !_cancellationToken.IsCancellationRequested)
{
  int samplesAvailable = ALC.GetInteger(_captureDevice, AlcGetInteger.CaptureSamples);
  if (samplesAvailable < 512) continue;
  int samplesToRead = Math.Min(samplesAvailable, buffer.Length - totalSamples);
  ALC.CaptureSamples(_captureDevice, ref buffer[totalSamples], samplesToRead);
  totalSamples += samplesToRead;
  spinWait.SpinOnce();
}

And then I write to the stream simply:

// headers writing...
// ...
sw.Write(buffer, 0, totalSamples);

I don't find any sample about OpenAL and file writing...
Is everything correct ?
Am I missing some steps ?

Upvotes: 1

Views: 109

Answers (1)

zorgas
zorgas

Reputation: 31

OK @fdcpp gave me an hint with not full samples being written. So to make it working, for a mono 16bit sound, the buffer should be ushort and not byte type.

There are some missing knowledge about sound audio specs from my side 😔

So the specific parts of code are:

// Capture the device
_captureDevice = ALC.CaptureOpenDevice(null, 44100, ALFormat.Mono16, 1024);
...
// Start recording
var buffer = new ushort[44100 * 16];
...
// Writing data
ushort bytePerBloc = 1 * (16 / 8);
using (MemoryStream memoryStream = new())
using (BinaryWriter sw = new(memoryStream))
{
  sw.Write(['R', 'I', 'F', 'F']);
  sw.Write(totalSamples * bytePerBloc + 36);
  ...
  sw.Write(['d', 'a', 't', 'a']);
  sw.Write(totalSamples * bytePerBloc); // size of buffer

  for (int i = 0; i < totalSamples; i++)
  {
    sw.Write(buffer[i]);
  }
...
}

And now it's working.

Next step to try the same with stereo 16bits 😅

Upvotes: 1

Related Questions