【问题标题】:Playing sine wave for unknown time播放未知时间的正弦波
【发布时间】:2012-03-07 01:43:34
【问题描述】:

我整天都在寻找一些教程或一段代码,“只是”在“无限”时间内播放简单的罪波。我知道这听起来有点疯狂。

但我希望能够及时改变音调的频率,例如 - 增加它。 想象一下,我想播放 A 音,每 3ms 以“+5”个频率步进将其增加到 C(这只是示例),不想有空闲位置,停止音调。

有可能吗?或者你能帮帮我吗?

【问题讨论】:

    标签: c# audio wave trigonometry


    【解决方案1】:

    使用 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 此代码仅供参考。真正使用添加 mt-locking 等

    【讨论】:

    • 非常适合启动一系列笔记。但是,在初始“旋律”完成后将更多音符添加到队列中无法正常工作。您希望新笔记立即开始。这可以通过在语句 if (Notes.Count == 0) return null;,.. 我的代码现在是: if (Notes.Count==0) { sample=0 ;返回空值; }。在这种情况下,下一个音符将立即开始,即使它在几秒钟后启动。此外,NextNote 中不需要 for (;;)。
    【解决方案2】:

    使用 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;
      }
    }
    

    【讨论】:

    • 谢谢...我试过了,但如果我想改变频率,它会在短时间内停止播放。我需要的可能是有一个循环播放简单数组的功能,例如一个循环是 5ms(对我来说 5ms 延迟就足够了),并且在每个循环结束时检查 bufferArray 以播放新的“音调”......并在另一个线程中添加一段时间后新的“音调”......
    • 但我不知道怎么玩..也没有找到任何解决方案:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-28
    • 2011-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多