2012-03-07 40 views
6

Cả ngày, tôi đang tìm kiếm một số hướng dẫn hoặc đoạn mã, "chỉ" để phát sóng tội lỗi đơn giản cho thời gian "vô cùng". Tôi biết nghe có vẻ hơi điên rồ.Chơi sóng sin trong thời gian uknown

Nhưng tôi muốn có thể thay đổi tần số của giai điệu trong thời gian, ví dụ - tăng nó. Hãy tưởng tượng rằng tôi muốn phát giai điệu A và tăng nó lên C trong các bước "3" không đổi mỗi 3ms (thực sự chỉ là ví dụ), không muốn có địa điểm miễn phí, dừng âm báo.

Có thể không? Hay bạn có thể giúp tôi?

Trả lời

5

Sử dụng NAudio thư viện cho đầu ra âm thanh.

Hãy ghi chú cung cấp sóng:

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

} 

bắt đầu chơi:

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

thêm ghi chú mới:

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

ps mã này chỉ là ý tưởng. cho thực tế sử dụng thêm mt-khóa vv

+0

Hoạt động rất tốt đẹp để khởi động một chuỗi các ghi chú. , thêm nhiều ghi chú vào hàng đợi sau khi "giai điệu" ban đầu đã hoàn thành không hoạt động đúng cách. Bạn có thể nhận được ghi chú mới để bắt đầu ngay lập tức. Notes.Count == 0) trả về null;, .. mã của tôi bây giờ là: if (Notes.Count == 0) {sample = 0; return null;}. Trong trường hợp này, ghi chú tiếp theo sẽ bắt đầu ngay lập tức, nếu nó được đưa ra một vài giây sau đó, vì vậy, (for;;) là không cần thiết trong NextNote. – Goodies

1

NAudio sử dụng và 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

cảm ơn ... Tôi đã thử nó, nhưng nếu tôi đang cố gắng để thay đổi tần số và nó ngừng chơi trong thời gian ngắn. Những gì tôi cần là có thể có một chức năng để chơi mảng đơn giản, trong chu kỳ, ví dụ một chu kỳ là 5ms (5ms trì hoãn cho tôi là đủ) và vào cuối mỗi chu kỳ kiểm tra bufferArray cho "giai điệu" mới để chơi ... và trong một chủ đề để thêm sau một thời gian mới "giai điệu" ... – eCorke

+0

nhưng tôi không biết làm thế nào để chơi nó .. và đã không tìm thấy bất kỳ giải pháp: ( – eCorke

Các vấn đề liên quan