2010-12-27 11 views
10

में लाइव माइक्रोफोन आयाम माप मैं सरल समाधान की तलाश में हूं जो सी # में माइक्रोफोन इनपुट का पूर्णांक मान वापस कर देगा। मैं पहले से नेट पर उपलब्ध नमूने की जांच कर रहा था, लेकिन उनमें से कोई भी x64 वातावरण में काम नहीं किया। (वीएस -2008 + डब्ल्यू 7 एक्स 64)।सी #

क्या कोई आसान समाधान है जो सी # में माइक्रोफोन इनपुट के आयाम (या आवृत्ति) के मूल्य को वापस कर देगा?

मैंने परिणामों के बिना NAudio की कोशिश की और यह: http://www.codeproject.com/KB/audio-video/cswavrec.aspx?msg=2155497 भाग्य के बिना।

+0

क्या आपने डायरेक्टएक्स डायरेक्टसाउंड की कोशिश की है? – JYelton

+0

क्या आपने अपना प्रोग्राम "किसी भी CPU" से "32 बिट केवल" में सेट करने का प्रयास किया है? अधिकांश कार्यक्रम 64 बिट मोड में चलाने से ज्यादा लाभ नहीं उठाते हैं। – CodesInChaos

+0

मैंने पहले से ही कोशिश की, लेकिन अब तक कोई भाग्य नहीं है। किसी भी सरल प्रत्यक्ष ध्वनि उदाहरण भी नहीं मिला है। मैंने स्लिम डीएक्स की भी कोशिश की, लेकिन ऐसा लगता है कि उन सभी उदाहरणों के साथ हमेशा कुछ परेशानी होती है। मेरे मामले में मुझे गतिशील अद्यतन के साथ पूर्णांक मूल्य की आवश्यकता है (नमूना प्रति सेकंड कुछ बार)। किसी के पास इसका कुछ अनुभव है? किसी भी मदद के लिए धन्यवाद। – Marian

उत्तर

2

मुझे लगता है कि जाने के लिए सबसे आसान मार्ग पुराने विंडोज मल्टीमीडिया एपीआई का उपयोग करना है क्योंकि यह वास्तव में सीधे आगे है। http://msdn.microsoft.com/en-us/library/dd743586(v=VS.85).aspx

तुम क्या है कि आप एक इनपुट डिवाइस पाने के लिए waveInOpen समारोह का उपयोग करें:

यहाँ MSDN के लिए लिंक है। यह पता लगाने के लिए कि आप किस डिवाइस का उपयोग करना चाहते हैं, सभी उपकरणों को गिनती नहीं करते हैं लेकिन आप उनमें से प्रत्येक और एक से पूछ सकते हैं। waveInGetNumDevs पर कॉल करके स्थापित डिवाइसों की संख्या लौटा दी गई है। फिर आप प्रत्येक डिवाइस के लिए waveInGetDevCaps पर कॉल कर सकते हैं और उन गुणों का निरीक्षण कर सकते हैं।

जब आपके डिवाइस को आप संभालते हैं तो डेटा के छोटे हिस्से प्राप्त करने के लिए बार-बार waveInAddBuffer पर कॉल करें। waveInOpen के दौरान निर्दिष्ट प्रारूप के आधार पर बाइट कच्चे ऑडियो डेटा का प्रतिनिधित्व करते हैं। कुछ आवृत्ति पर 8 या 16-बिट हस्ताक्षरित या unisnged नमूना में आयाम।

फिर आप सिग्नल को सुचारू बनाने के लिए रोलिंग औसत लागू कर सकते हैं और बस इसे प्रिंट कर सकते हैं।

सी # में एक ध्वनि एपीआई नहीं है जो मुझे पता है, तो आप क्या करते हैं कि आप Win32 API फ़ंक्शंस प्राप्त करने के लिए पी/Invoke का उपयोग करते हैं। यह काफी सीधे आगे है, आपको केवल Win32 शीर्षकों के छोटे संस्करणों को पोर्ट करने की आवश्यकता है ताकि उन्हें सी # से सीधे कॉल किया जा सके।

यदि आप अधिक कट्टर हैं तो आप सी ++/सीएलआई में एक रैपर लाइब्रेरी लिख सकते हैं। यह किसी विचार का बुरा नहीं है क्योंकि यह आपको मौजूदा विंडोज सी/सी ++ हेडर फाइलों का उपयोग करने देता है और सी ++ और प्रबंधित कोड को घुमावदार तरीकों से मिलाता है। बस अप्रबंधित संसाधनों से सावधान रहें और आपके पास किसी भी समय एक बहुत ही शक्तिशाली इंटरेबिलिटी लाइब्रेरी होगी।

लेकिन विंडोज विस्टा से शुरू होने वाले अधिक उन्नत ऑडियो एपीआई भी हैं, विंडोज कोर ऑडियो घटक जो लाइन के साथ और अधिक दिलचस्प हो सकते हैं। लेकिन मूल I/O ऑपरेशन के लिए विंडोज मल्टीमीडिया फ़ंक्शंस आपको तेज़ी से ले जाएगा।

मैंने सरल सॉफ़्टवेयर सिंथेसाइज़र बनाने के दौरान इन कार्यों का उपयोग कई अवसरों पर किया है। अफसोस की बात है कि कोड लंबा चला गया है।

1

मैं स्लिम डीएक्स की अनुशंसा करता हूं क्योंकि इसे विंडोज़ (x86 या x64) के किसी भी संस्करण पर काम करना चाहिए और सबसे अधिक सुविधाएं और लचीलापन प्रदान करता है। हालांकि, यह उठने और चलने का दर्द है क्योंकि कोई अच्छा पूर्ण कोड नमूने नहीं हैं।

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 x64 पर इस कोड का परीक्षण)

विलंबता को कम करने के लिए यह पूरी तरह बहु-थ्रेडेड है। मैंने मूल रूप से इसे रीयल-टाइम सिग्नल प्रोसेसिंग विश्लेषण टूल के लिए लिखा था और छोटे के बजाए फ्लोट आउटपुट का इस्तेमाल किया था, लेकिन मैंने आपके अनुरोधित उपयोग से मेल खाने के लिए कोड नमूना संशोधित किया था।यदि आपको आवृत्ति डेटा की आवश्यकता है तो मैं एक अच्छी सी # एफएफटी लाइब्रेरी के लिए http://www.mathdotnet.com/Neodym.aspx या http://www.exocortex.org/dsp/ का उपयोग करूंगा।