Reputation: 31
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
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