Directing microphone input to speakers and writing a custom DSP function with CSCore library
<p>CSCore (<a href="https://github.com/filoe/cscore" rel="nofollow noreferrer">https://github.com/filoe/cscore</a>) seems to be a very good audio library for C# but it lacks documentation and good examples.</p>

<p>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.</p>

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

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

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

<p>What I am trying to do is write an application like this one:
<a href="http://www.pitchtech.ch/PitchBox/" rel="nofollow noreferrer">http://www.pitchtech.ch/PitchBox/</a></p>

<p>I have my own DSP functions which I want to apply to recorded data.</p>

<p>Does anybody have examples of directing WasapiCapture to WasapiOut and writing a custom DSP?</p>

<p>EDIT:</p>

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

<p>Here is a sample DSP class which amplifies the provided audio data.</p>

<pre><code>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 &lt; 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()
    {
    }
}
</code></pre>

<p>And you can use this class as in the sample below:</p>

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