2012-03-07 19 views
6

Cały dzień szukałem poradnika lub fragmentu kodu, "po prostu", aby zagrać prostą falę grzechu dla czasu "nieskończoności". Wiem, że to trochę szalone.Odtwarzanie fali sinusoidalnej dla czasu nieokreślonego

Ale chcę być w stanie zmienić częstotliwość dźwięku w czasie, na przykład - zwiększyć. Wyobraź sobie, że chcę odtwarzać dźwięk A i zwiększać go do C w krokach "+5" co 3 ms (to naprawdę tylko przykład), nie chcę mieć wolnych miejsc, zatrzymać dźwięk.

Czy to możliwe? Czy możesz mi pomóc?

Odpowiedz

5

Zastosowanie NAudio biblioteka dla wyjścia audio.

robić notatki dostawcy fali:

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); 

} 

początek Play:

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(); 

dodać nowe nuty:

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

ps ten kod jest tylko pomysł. do rzeczywistego użytku dodaj mt-locking etc

+0

Działa bardzo dobrze, aby uruchomić sekwencję nut. , dodanie kolejnych notatek do kolejki po zakończeniu początkowej "melodii" nie działa poprawnie, możesz oczekiwać natychmiastowego rozpoczęcia nowej notatki, co można osiągnąć za pomocą powyższego kodu, wstawiając reset licznika próbki w instrukcji if (Notes.Count == 0) return null;, ... mój kod jest teraz: if (Notes.Count == 0) {sample = 0; return null;}. W takim przypadku następna notatka rozpocznie się natychmiast, także jeśli jest uruchamiany kilka sekund później, a także dla (;;) nie jest potrzebny w NextNote. – Goodies

1

użycie NAudio i 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

dziękuję ... Próbowałem, ale jeśli próbuję zmienić częstotliwość i przestał grać na krótki czas. To, czego potrzebuję, to być może mieć jedną funkcję do gry w prostą tablicę, w cyklu, na przykład jeden cykl to 5ms (5ms opóźnienia dla mnie wystarcza) i na koniec każdego cyklu sprawdź bufferArray dla nowego "tonu" do gry ... i w innym wątku, aby dodać po pewnym czasie nowy "ton" ... – eCorke

+0

, ale nie wiem, jak go odtworzyć .. i nie znalazłem żadnego rozwiązania :( – eCorke

Powiązane problemy