Направление микрофонного ввода на динамики и написание пользовательской функции DSP с библиотекой CSCore

CSCore ( https://github.com/filoe/cscore), кажется, очень хорошая аудио библиотека для C#, но ей не хватает документации и хороших примеров.

Я давно играю с Bass.Net, и архитектура CSCore не похожа на библиотеку Bass, поэтому очень сложно найти правильный способ решения некоторых общих задач.

Я пытаюсь захватить вход микрофона с устройства WasapiCapture и вывести записанные данные на устройство WasapiOut, но мне это не удалось.

Ниже приведен код, который я смог найти после поиска в Google, но он не работает.

        MMDeviceEnumerator deviceEnum = new MMDeviceEnumerator();
        MMDeviceCollection devices = deviceEnum.EnumAudioEndpoints(DataFlow.Capture, DeviceState.Active);

        using (var capture = new WasapiCapture())
        {
            capture.Device = deviceEnum.GetDefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia);
            capture.Initialize();

            using (var source = new SoundInSource(capture))
            {
                using (var soundOut = new WasapiOut())
                {
                    capture.Start();

                    soundOut.Device = deviceEnum.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
                    soundOut.Initialize(source);
                    soundOut.Play();

                }
            }
        }

То, что я пытаюсь сделать, это написать приложение, подобное этому: http://www.pitchtech.ch/PitchBox/

У меня есть свои собственные функции DSP, которые я хочу применить к записанным данным.

У кого-нибудь есть примеры направления WasapiCapture в WasapiOut и написания собственного DSP?

РЕДАКТИРОВАТЬ:

Я нашел решение с помощью создателя библиотеки CSCore Флориана Росмана (filoe).

Вот пример класса DSP, который усиливает предоставленные аудиоданные.

class DSPGain: ISampleSource
{
    ISampleSource _source;
    public DSPGain(ISampleSource source)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        _source = source;
    }
    public int Read(float[] buffer, int offset, int count)
    {
        float gainAmplification = (float)(Math.Pow(10.0, GainDB / 20.0));
        int samples = _source.Read(buffer, offset, count);
        for (int i = offset; i < offset + samples; i++)
        {
            buffer[i] = Math.Max(Math.Min(buffer[i] * gainAmplification, 1), -1);
        }
        return samples;
    }

    public float GainDB { get; set; }

    public bool CanSeek
    {
        get { return _source.CanSeek; }
    }

    public WaveFormat WaveFormat
    {
        get { return _source.WaveFormat; }
    }

    public long Position
    {
        get
        {
            return _source.Position;
        }
        set
        {
            _source.Position = value;
        }
    }

    public long Length
    {
        get { return _source.Length; }
    }

    public void Dispose()
    {
    }
}

И вы можете использовать этот класс как в примере ниже:

WasapiCapture waveIn;
WasapiOut soundOut;
DSPGain gain;
private void StartFullDuplex()
{
    try
    {
        MMDeviceEnumerator deviceEnum = new MMDeviceEnumerator();
        MMDeviceCollection devices = deviceEnum.EnumAudioEndpoints(DataFlow.Capture, DeviceState.Active);

        waveIn = new WasapiCapture(false, AudioClientShareMode.Exclusive, 5);
        waveIn.Device = deviceEnum.GetDefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia);
        waveIn.Initialize();
        waveIn.Start();


        var source = new SoundInSource(waveIn) { FillWithZeros = true };
        soundOut = new WasapiOut(false, AudioClientShareMode.Exclusive, 5);
        soundOut.Device = deviceEnum.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);

        gain = new DSPGain(source.ToSampleSource());
        gain.GainDB = 5;

        soundOut.Initialize(gain.ToWaveSource(16));
        soundOut.Play();
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception in StartFullDuplex: " + ex.Message);
    }

}

private void StopFullDuplex()
{
    if (soundOut != null) soundOut.Dispose();
    if (waveIn != null) waveIn.Dispose();
}

1 ответ

Я нашел решение с помощью создателя библиотеки CSCore Флориана Росманна (filoe).

Вот пример класса DSP, который усиливает предоставленные аудиоданные.

      class DSPGain: ISampleSource
{
    ISampleSource _source;
    public DSPGain(ISampleSource source)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        _source = source;
    }
    public int Read(float[] buffer, int offset, int count)
    {
        float gainAmplification = (float)(Math.Pow(10.0, GainDB / 20.0));
        int samples = _source.Read(buffer, offset, count);
        for (int i = offset; i < offset + samples; i++)
        {
            buffer[i] = Math.Max(Math.Min(buffer[i] * gainAmplification, 1), -1);
        }
        return samples;
    }

    public float GainDB { get; set; }

    public bool CanSeek
    {
        get { return _source.CanSeek; }
    }

    public WaveFormat WaveFormat
    {
        get { return _source.WaveFormat; }
    }

    public long Position
    {
        get
        {
            return _source.Position;
        }
        set
        {
            _source.Position = value;
        }
    }

    public long Length
    {
        get { return _source.Length; }
    }

    public void Dispose()
    {
    }
}

И вы можете использовать этот класс, как в примере ниже:

      WasapiCapture waveIn;
WasapiOut soundOut;
DSPGain gain;
private void StartFullDuplex()
{
    try
    {
        MMDeviceEnumerator deviceEnum = new MMDeviceEnumerator();
        MMDeviceCollection devices = deviceEnum.EnumAudioEndpoints(DataFlow.Capture, DeviceState.Active);

        waveIn = new WasapiCapture(false, AudioClientShareMode.Exclusive, 5);
        waveIn.Device = deviceEnum.GetDefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia);
        waveIn.Initialize();
        waveIn.Start();


        var source = new SoundInSource(waveIn) { FillWithZeros = true };
        soundOut = new WasapiOut(false, AudioClientShareMode.Exclusive, 5);
        soundOut.Device = deviceEnum.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);

        gain = new DSPGain(source.ToSampleSource());
        gain.GainDB = 5;

        soundOut.Initialize(gain.ToWaveSource(16));
        soundOut.Play();
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception in StartFullDuplex: " + ex.Message);
    }

}

private void StopFullDuplex()
{
    if (soundOut != null) soundOut.Dispose();
    if (waveIn != null) waveIn.Dispose();
}

Этот ответ был опубликован как редактирование вопроса Направление входа микрофона на динамики и написание пользовательской функции DSP с библиотекой CSCore OP user5413816 под CC BY-SA 3.0.

Другие вопросы по тегам