2012-03-07 14 views
6

Todo el día estaba buscando algún tutorial o fragmento de código, "solo" para reproducir la onda sinusoidal simple para el tiempo "infinito". Sé que suena un poco loco.Reproducción de ondas sinusoidales durante el tiempo desconocido

Pero quiero poder cambiar la frecuencia del tono en el tiempo, por ejemplo, aumentarlo. Imagine que quiero reproducir el tono A, y aumentarlo a C en pasos de frecuencia "+5" cada 3ms (es solo el ejemplo), no quiero tener lugares libres, detener el tono.

¿Es posible? ¿O puedes ayudarme?

Respuesta

5

biblioteca Uso NAudio para la salida de audio.

Tome notas proveedor de 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); 

} 

reproducción de inicio:

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

añadir nuevas notas:

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

ps este código es la idea única. de verdad usando add mt-locking etc

+0

Funciona muy bien para lanzar una secuencia de notas. , agregar más notas a la cola después de que la "melodía" inicial haya finalizado no funciona correctamente. Es de esperar que la nueva nota comience inmediatamente. Esto se puede lograr con el código anterior insertando un reinicio del contador de muestras en el enunciado if (Notes.Count == 0) return null; ... mi código es ahora: if (Notes.Count == 0) {sample = 0; return null;}. En este caso, la siguiente nota comenzará inmediatamente, también si se inicia unos segundos más tarde. Además, el para (;;) no es necesario en NextNote. – Goodies

1

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

gracias ... Lo intenté, pero si estoy tratando de cambiar la frecuencia y dejó de jugar durante un tiempo corto. Lo que necesito es tal vez tener una función para jugar una matriz simple, en ciclo, por ejemplo, un ciclo es de 5 ms (una demora de 5 ms es suficiente) y al final de cada ciclo verificar la matrizArray para obtener un nuevo "tono" ... y en otro hilo para agregar después de un tiempo nuevo "tono" ... – eCorke

+0

pero no sé cómo reproducirlo ... y no he encontrado ninguna solución :( – eCorke

Cuestiones relacionadas