Захват аудио из WasapiLoopbackCapture и преобразование в muLaw
Я записываю аудио с помощью WasapiLoopbackCapture
- format = IeeeFloat - SampleRate = 48000 - BitsPerSample = 32
Мне нужно преобразовать это в muLaw (8 кГц, 8 бит, моно) - в конце концов он будет отправлен на телефон через SIP-транкинг. Я пробовал сотни образцов (большинство из них с NAudio) и решений, но до сих пор не знаю, как это сделать...
1 ответ
Инструменты Mu-Law в NAudio ограничены, так что вам, возможно, придется свернуть свои собственные.
Вам нужно будет создать цепочку IWaveProvider
фильтры для преобразования в моно, изменения битрейта и битовой глубины.
waveBuffer = new BufferedWaveProvider(waveIn.WaveFormat);
waveBuffer.DiscardOnBufferOverflow = true;
waveBuffer.ReadFully = false; // leave a buffer?
sampleStream = new WaveToSampleProvider(waveBuffer);
// Stereo to mono
monoStream = new StereoToMonoSampleProvider(sampleStream)
{
LeftVolume = 1f,
RightVolume = 1f
};
// Downsample to 8000
resamplingProvider = new WdlResamplingSampleProvider(monoStream, 8000);
// Convert to 16-bit in order to use ACM or MuLaw tools.
ieeeToPcm = new SampleToWaveProvider16(resamplingProvider);
Затем создайте пользовательский IWaveProvider для следующего шага.
// In MuLawConversionProvider
public int Read(byte[] destinationBuffer, int offset, int readingCount)
{
// Source buffer has twice as many items as the output array.
var sizeOfPcmBuffer = readingCount * 2;
_sourceBuffer = BufferHelpers.Ensure(_sourceBuffer, sizeOfPcmBuffer);
var sourceBytesRead = _sourceProvider.Read(_sourceBuffer, offset * 2, sizeOfPcmBuffer);
var samplesRead = sourceBytesRead / 2;
var outIndex = 0;
for (var n = 0; n < sizeOfPcmBuffer; n += 2)
{
destinationBuffer[outIndex++] = MuLawEncoder.LinearToMuLawSample(BitConverter.ToInt16(_sourceBuffer, offset + n));
}
return samplesRead * 2;
}
Новый провайдер может быть отправлен напрямую в WaveOut
outputStream = new MuLawConversionProvider(ieeeToPcm);
waveOut.Init(outputStream);
waveOut.Play();
Эти фильтры остаются на месте с BufferedWaveProvider в качестве "корня". Всякий раз, когда вы звоните BufferedWaveProvider.AddSamples()
данные пройдут через все эти фильтры.