Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I recommend SlimDX since it should work on just about any version of windows (x86 or x64) and provides the most features and flexibility. However, it is a pain to get up and running since there are no good complete code samples. I wrote a wrapper class to simplify its usage though so it can be called like this (I tested this code on Win7 x64):</p> <pre><code> public void CaptureAudio() { using (var source = new SoundCardSource()) { source.SampleRateKHz = 44.1; source.SampleDataReady += this.OnSampleDataReady; source.Start(); // Capture 5 seconds of audio... Thread.Sleep(5000); source.Stop(); } } private void OnSampleDataReady(object sender, SampleDataEventArgs e) { // Do something with e.Data short array on separate thread... } </code></pre> <p>Here is the source for the SlimDX wrapper class:</p> <pre><code>using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using SlimDX.DirectSound; using SlimDX.Multimedia; public class SampleDataEventArgs : EventArgs { public SampleDataEventArgs(short[] data) { this.Data = data; } public short[] Data { get; private set; } } public class SoundCardSource : IDisposable { private volatile bool running; private int bufferSize; private CaptureBuffer buffer; private CaptureBufferDescription bufferDescription; private DirectSoundCapture captureDevice; private WaveFormat waveFormat; private Thread captureThread; private List&lt;NotificationPosition&gt; notifications; private int bufferPortionCount; private int bufferPortionSize; private WaitHandle[] waitHandles; private double sampleRate; public SoundCardSource() { this.waveFormat = new WaveFormat(); this.SampleRateKHz = 44.1; this.bufferSize = 2048; } public event EventHandler&lt;SampleDataEventArgs&gt; SampleDataReady = delegate { }; public double SampleRateKHz { get { return this.sampleRate; } set { this.sampleRate = value; if (this.running) { this.Restart(); } } } public void Start() { if (this.running) { throw new InvalidOperationException(); } if (this.captureDevice == null) { this.captureDevice = new DirectSoundCapture(); } this.waveFormat.FormatTag = WaveFormatTag.Pcm; // Change to WaveFormatTag.IeeeFloat for float this.waveFormat.BitsPerSample = 16; // Set this to 32 for float this.waveFormat.BlockAlignment = (short)(waveFormat.BitsPerSample / 8); this.waveFormat.Channels = 1; this.waveFormat.SamplesPerSecond = (int)(this.SampleRateKHz * 1000D); this.waveFormat.AverageBytesPerSecond = this.waveFormat.SamplesPerSecond * this.waveFormat.BlockAlignment * this.waveFormat.Channels; this.bufferPortionCount = 2; this.bufferDescription.BufferBytes = this.bufferSize * sizeof(short) * bufferPortionCount; this.bufferDescription.Format = this.waveFormat; this.bufferDescription.WaveMapped = false; this.buffer = new CaptureBuffer(this.captureDevice, this.bufferDescription); this.bufferPortionSize = this.buffer.SizeInBytes / this.bufferPortionCount; this.notifications = new List&lt;NotificationPosition&gt;(); for (int i = 0; i &lt; this.bufferPortionCount; i++) { NotificationPosition notification = new NotificationPosition(); notification.Offset = this.bufferPortionCount - 1 + (bufferPortionSize * i); notification.Event = new AutoResetEvent(false); this.notifications.Add(notification); } this.buffer.SetNotificationPositions(this.notifications.ToArray()); this.waitHandles = new WaitHandle[this.notifications.Count]; for (int i = 0; i &lt; this.notifications.Count; i++) { this.waitHandles[i] = this.notifications[i].Event; } this.captureThread = new Thread(new ThreadStart(this.CaptureThread)); this.captureThread.IsBackground = true; this.running = true; this.captureThread.Start(); } public void Stop() { this.running = false; if (this.captureThread != null) { this.captureThread.Join(); this.captureThread = null; } if (this.buffer != null) { this.buffer.Dispose(); this.buffer = null; } if (this.notifications != null) { for (int i = 0; i &lt; this.notifications.Count; i++) { this.notifications[i].Event.Close(); } this.notifications.Clear(); this.notifications = null; } } public void Restart() { this.Stop(); this.Start(); } private void CaptureThread() { int bufferPortionSamples = this.bufferPortionSize / sizeof(float); // Buffer type must match this.waveFormat.FormatTag and this.waveFormat.BitsPerSample short[] bufferPortion = new short[bufferPortionSamples]; int bufferPortionIndex; this.buffer.Start(true); while (this.running) { bufferPortionIndex = WaitHandle.WaitAny(this.waitHandles); this.buffer.Read( bufferPortion, 0, bufferPortionSamples, bufferPortionSize * Math.Abs((bufferPortionIndex - 1) % bufferPortionCount)); this.SampleDataReady(this, new SampleDataEventArgs(bufferPortion)); } this.buffer.Stop(); } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { this.Stop(); if (this.captureDevice != null) { this.captureDevice.Dispose(); this.captureDevice = null; } } } } </code></pre> <p>It's fully multi-threaded to minimize latency. I originally wrote it for a real-time signal processing analysis tool and used float output instead of short but I modified the code sample to match your requested usage. If you need frequency data I would use <a href="http://www.mathdotnet.com/Neodym.aspx" rel="nofollow">http://www.mathdotnet.com/Neodym.aspx</a> or <a href="http://www.exocortex.org/dsp/" rel="nofollow">http://www.exocortex.org/dsp/</a> for a good C# FFT library. </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload