Захват аудио из WasapiLoopbackCapture и преобразование в muLaw

Я записываю звук с помощью WasapiLoopbackCapture

- format        = IeeeFloat
- SampleRate    = 48000
- BitsPerSample = 32

Мне нужно преобразовать это в muLaw (8 кГц, 8 бит, моно) — в конечном итоге оно будет отправлено на телефон через SIP-транкинг. Я пробовал сотни образцов (большинство из них с NAudio) и решений, но до сих пор не знаю, как это сделать...


person KBoek    schedule 12.01.2018    source источник


Ответы (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(), данные проходят через все эти фильтры.

person devlord    schedule 17.01.2018
comment
Это похоже на некоторую ценную информацию, к сожалению, в ней есть большой пробел в том, что такое пользовательский IWaveProvider... Насколько я понимаю, С# должен быть чем-то вроде этого? gist.github.com/programmin1/c011dba09ac7d30f734926b074863167 Однако, если код чтения является примером, который вы ему даете не будет компилироваться. - person NoBugs; 02.11.2019
comment
Я дошел до этого, но я не уверен, что делает MuLawEncoder или что он делает с int16s в этом ответе? stackoverflow.com/questions/58678228/ - person NoBugs; 03.11.2019