2012-03-07 26 views
6

पूरे दिन मैं कुछ ट्यूटोरियल या कोड का टुकड़ा ढूंढ रहा था, "बस" "अनंत" समय के लिए सरल पाप लहर खेलने के लिए। मुझे पता है कि यह थोड़ा पागल लगता है।uknown समय के लिए साइन लहर बजाना

लेकिन मैं समय में स्वर की आवृत्ति को बदलने में सक्षम होना चाहता हूं, उदाहरण के लिए - इसे बढ़ाएं। कल्पना कीजिए कि मैं टोन ए खेलना चाहता हूं, और प्रत्येक 3ms (यह वास्तव में केवल उदाहरण है) में "+5" फ्रेक्वेंसी चरणों में सी को बढ़ाता है, मुफ्त स्थान नहीं लेना चाहते हैं, स्वर को रोकना चाहते हैं।

क्या यह संभव है? या आप मेरी मदद कर सकते हैं?

उत्तर

5

ऑडियो आउटपुट के लिए उपयोग NAudio पुस्तकालय।

class NotesWaveProvider : WaveProvider32 
{ 
    public NotesWaveProvider(Queue<Note> notes) 
    { 
     this.Notes = notes; 
    } 
    public readonly Queue<Note> Notes; 
    int sample = 0; 

    Note NextNote() 
    { 
     for (; ;) 
     { 
      if (Notes.Count == 0) 
       return null; 
      var note = Notes.Peek(); 
      if (sample < note.Duration.TotalSeconds * WaveFormat.SampleRate) 
       return note; 

      Notes.Dequeue(); 
      sample = 0; 
     } 

    } 
    public override int Read(float[] buffer, int offset, int sampleCount) 
    { 
     int sampleRate = WaveFormat.SampleRate; 
     for (int n = 0; n < sampleCount; n++) 
     { 
      var note = NextNote(); 
      if (note == null) 
       buffer[n + offset] = 0; 
      else 
       buffer[n + offset] = (float)(note.Amplitude * Math.Sin((2 * Math.PI * sample * note.Frequency)/sampleRate)); 
      sample++; 
     } 
     return sampleCount; 
    } 
} 
class Note 
{ 
    public float Frequency; 
    public float Amplitude = 1.0f; 
    public TimeSpan Duration = TimeSpan.FromMilliseconds(50); 

} 

शुरू खेलने:

WaveOut waveOut; 
this.Notes = new Queue<Note>(new[] { new Note { Frequency = 1000 }, new Note { Frequency = 1100 } }); 
var waveProvider = new NotesWaveProvider(Notes); 
waveProvider.SetWaveFormat(16000, 1); // 16kHz mono  

waveOut = new WaveOut(); 
waveOut.Init(waveProvider); 
waveOut.Play(); 

नया नोट जोड़ने:

void Timer_Tick(...) 
{ 
if (Notes.Count < 10) 
    Notes.Add(new Note{Frecuency = 900}); 
} 

ps इस कोड को केवल विचार है

नोटों लहर प्रदाता बनाएं। वास्तविक एमटी-लॉकिंग आदि का उपयोग करके

+0

नोट्स का अनुक्रम लॉन्च करने के लिए बहुत अच्छा काम करता है। हालांकि प्रारंभिक "मेलोडी" समाप्त होने के बाद कतार में और नोट्स जोड़ना ठीक से काम नहीं करता है। आप नए नोट को तुरंत शुरू करने की उम्मीद करेंगे। इसे नमूना काउंटर के रीसेट को सम्मिलित करके उपरोक्त कोड के साथ हासिल किया जा सकता है यदि (नोट्स। गणना == 0) शून्य वापस लौटें;, .. मेरा कोड अब है: यदि (नोट्स। गणना == 0) {नमूना = 0; वापसी शून्य;}। इस मामले में, अगला नोट तुरंत शुरू होगा, भले ही इसे कुछ सेकंड बाद लॉन्च किया गया है। इसके अलावा, नेक्स्ट नोट में के लिए (;;) की आवश्यकता नहीं है। – Goodies

1

उपयोग NAudio और SineWaveProvider32: http://mark-dot-net.blogspot.com/2009/10/playback-of-sine-wave-in-naudio.html

private WaveOut waveOut; 

private void button1_Click(object sender, EventArgs e) 
{ 
    StartStopSineWave(); 
} 

private void StartStopSineWave() 
{ 
    if (waveOut == null) 
    { 
    var sineWaveProvider = new SineWaveProvider32(); 
    sineWaveProvider.SetWaveFormat(16000, 1); // 16kHz mono 
    sineWaveProvider.Frequency = 1000; 
    sineWaveProvider.Amplitude = 0.25f; 
    waveOut = new WaveOut(); 
    waveOut.Init(sineWaveProvider); 
    waveOut.Play(); 
    } 
    else 
    { 
    waveOut.Stop(); 
    waveOut.Dispose(); 
    waveOut = null; 
    } 
} 
+0

धन्यवाद ... मैंने कोशिश की, लेकिन अगर मैं आवृत्ति बदलने की कोशिश कर रहा हूं और यह कम समय के लिए खेलना बंद कर रहा है। मुझे जो चाहिए वह शायद चक्र में सरल सरणी खेलने के लिए एक समारोह हो सकता है, उदाहरण के लिए एक चक्र 5 एमएमएस (मेरे लिए 5 एमएमएस देरी पर्याप्त है) और प्रत्येक चक्र के अंत में चेक बफर आरे खेलने के लिए नए "स्वर" के लिए ... और कुछ अन्य थ्रेड में कुछ नया "टोन" जोड़ने के लिए ... – eCorke

+0

लेकिन मुझे नहीं पता कि इसे कैसे खेलें .. और कोई समाधान नहीं मिला है :( – eCorke