Directing microphone input to speakers and writing a custom DSP function with CSCore library
Asked Answered
M

1

7

CSCore (https://github.com/filoe/cscore) seems to be a very good audio library for C# but it lacks documentation and good examples.

I've been playing with Bass.Net for a long time and the architecture of CSCore is not like the Bass library so it is really hard to find out the right way to do some common tasks.

I'm trying to capture microphone input from WasapiCapture device and output the recorded data to WasapiOut device but I could not succeed it.

The following is the code I could find after googling but it does not work.

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();
        }
    }
}

What I am trying to do is write an application like this one: http://www.pitchtech.ch/PitchBox/

I have my own DSP functions which I want to apply to recorded data.

Does anybody have examples of directing WasapiCapture to WasapiOut and writing a custom DSP?

Munsey answered 6/1, 2016 at 13:48 Comment(0)
L
0

I found the solution with the help of the CSCore library creator Florian Rosmann (filoe).

Here is a sample DSP class which amplifies the provided audio data.

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()
    {
    }
}

And you can use this class as in the sample below:

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();
}

This answer was posted as an edit to the question Directing microphone input to speakers and writing a custom DSP function with CSCore library by the OP Ahmet Uzun under CC BY-SA 3.0.

Longlimbed answered 3/12, 2022 at 12:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.