2012-03-07 10 views
6

Tutto il giorno cercavo qualche tutorial o parte di codice, "solo" per riprodurre l'onda sin sin per il tempo "infinito". So che sembra un po 'pazzo.Riproduzione sinusoidale per ora sconosciuta

Ma io voglio essere in grado di cambiare la frequenza del tono nel tempo, ad esempio - aumentarlo. Immagina che io voglia suonare il tono A, e aumentarlo a C in "+5" passi di frenquenza ogni 3ms (è davvero solo un esempio), non voglio avere posti liberi, fermare il tono.

È possibile? Oppure puoi aiutarmi?

risposta

5

biblioteca Usa NAudio per l'uscita audio.

prendere appunti fornitore onda:

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

} 

gioco inizio:

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

aggiungere nuove note:

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

ps questo codice è solo un'idea. per davvero usando aggiungi mt-locking etc

+0

Funziona molto bene per avviare una sequenza di note. , aggiungendo più note alla coda dopo che la "melodia" iniziale ha terminato, non funziona correttamente. Dovresti aspettarti che la nuova nota inizi immediatamente. Ciò può essere ottenuto con il codice precedente inserendo un reset del contatore del campione in statement if (Notes.Count == 0) restituisce null;, .. il mio codice è ora: if (Notes.Count == 0) {sample = 0; return null;}. In questo caso, la nota successiva inizierà immediatamente, anche se viene lanciato pochi secondi dopo. Inoltre, il suffisso (;;) non è necessario in NextNote. – Goodies

1

uso NAudio e 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

grazie ... L'ho provato, ma se sto provando a cambiare frequenza e ha smesso di suonare per poco tempo. Quello di cui ho bisogno è forse avere una funzione per suonare array semplici, in ciclo, ad esempio un ciclo è 5ms (il ritardo di 5ms per me è sufficiente) e alla fine di ogni ciclo controlla bufferArray per un nuovo "tono" per giocare ... e in un'altra discussione per aggiungere dopo qualche tempo un nuovo "tono" ... – eCorke

+0

ma non so come suonarlo .. e non ho trovato nessuna soluzione :( – eCorke