SlimDX는 Windows의 모든 버전 (x86 또는 x64)에서 작동해야하며 SlimDX는 대부분의 기능과 유연성을 제공하므로 권장합니다. 그러나 완전한 완전한 코드 샘플이 없기 때문에 시작하고 실행하는 것은 고통입니다.
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<NotificationPosition> 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<SampleDataEventArgs> 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<NotificationPosition>();
for (int i = 0; i < 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 < 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 < 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;
}
}
}
}
: 여기
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...
}
가 SlimDX 래퍼 클래스의 소스입니다 : 나는 그것과 같이 호출 할 수 있도록 불구하고 그것의 사용을 단순화하는 래퍼 클래스를 썼다 (나는 Win7에 64에이 코드를 테스트)
대기 시간을 최소화하기 위해 완전히 멀티 스레드입니다. 원래는 실시간 신호 처리 분석 도구로 작성했으며 짧은 대신 float 출력을 사용했지만 요청한 용도에 맞게 코드 샘플을 수정했습니다.빈도 데이터가 필요한 경우 좋은 C# FFT 라이브러리에 http://www.mathdotnet.com/Neodym.aspx 또는 http://www.exocortex.org/dsp/을 사용합니다.
DirectX DirectSound를 사용해 보셨습니까? – JYelton
프로그램을 "Any CPU"에서 "32 bit only"로 설정해 보았습니까? 대부분의 프로그램은 64 비트 모드에서 많은 이익을 얻지 못합니다. – CodesInChaos
나는 그것을 벌써 시도했다. 그러나 지금까지 어떤 운도 가지지 않고있다. 어떤 간단한 directSound 예제도 찾지 못했습니다. 나는 또한 SlimDX를 시도했지만, 모든 예제를 통해 항상 문제가 있음을 알 수 있습니다. 필자의 경우에는 동적 업데이트 (초당 몇 번 샘플링)로 정수 값이 필요합니다. 누구나 그런 경험이 있습니까? 어떤 도움을 주셔서 감사합니다. – Marian