Воспроизведение синусоиды в течение неизвестного времени - PullRequest
5 голосов
/ 07 марта 2012

Целый день я искал какой-то учебник или фрагмент кода, «просто», чтобы играть в простую волну греха для времени «бесконечности». Я знаю, это звучит немного безумно.

Но я хочу иметь возможность изменять частоту тона, например, увеличивать ее. Представьте, что я хочу воспроизвести тон A и увеличить его до C с шагом частоты +5 каждые 3 мс (на самом деле это просто пример), не хочу иметь свободные места, остановите тон.

Возможно ли это? Или ты можешь мне помочь?

Ответы [ 2 ]

5 голосов
/ 07 марта 2012

Используйте библиотеку 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-блокировки и т. д.

1 голос
/ 07 марта 2012

используйте NAudio и SineWaveProvider32: http://mark -dot-net.blogspot.com / 2009/10 / воспроизведение синусоиды в 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;
  }
}
...