Как я могу генерировать сигнал и записывать с помощью NAudio одновременно?

#c# #record #naudio

#c# #запись #naudio

Вопрос:

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

Я пытался создать несколько программ для достижения этого, как показано ниже, но возникают некоторые проблемы.

Генерировать синусоидальный сигнал -> Динамик -> МИКРОФОН -> Запись (волна)

1) Выход сигнала: я использовал два выхода сигнала.

a) Для генерации сигнала

б) Записать файл wave. Создает ли это проблему?

2) Эхо-звук :

a) Наушники :

Если я использую наушники, я могу слышать чистый синусоидальный звук. Но микрофон не слышит этот звук. и тогда он просто запишет звук окружающей среды.

б) Динамик :

Если я использую динамик (ту же линию наушников, я просто добавляю усилитель и динамик), я могу слышать эхо-звук, как показано на рисунке ниже. И микрофон также записывает этот эхо-звук. Я могу предположить, что микрофон получил этот звук, и через несколько миллисекунд динамик добавляет этот звук к исходному звуку. Но я не могу понять, почему динамик добавляет этот принятый звук. Как я могу записывать без эхо-звука?

3) Время записи :

Я хочу записать 2 секунды. Затем я использовал timer и определил timer.Интервал = 2 секунды. Но реальное время записи превышает 2 секунды. некоторая задержка?

4) Время развертки :

Я определил время развертки в 2 секунды. Но в течение более чем 2 секунд синусоидальная развертка не завершена. Во время завершения (около 2,2 секунды) частота составляет 1,5 кГц. (Я определил конечную частоту = 2 кГц).

Записанный файл Echo Wave

 public partial class Form1 : Form
{
    private WaveIn recorder;
    private BufferedWaveProvider bufferedWaveProvider;
    private SavingWaveProvider savingWaveProvider;
    private WaveOut player;

    private WaveOut player_sweep;   // 190305

    public Form1()
    {
        InitializeComponent();
    }

    private void OnStartRecording_Click(object sender, EventArgs e)
    {
        // set up the recorder
        recorder = new WaveIn();
        recorder.DataAvailable  = RecorderOnDataAvailable;

        // set up our signal chain
        bufferedWaveProvider = new BufferedWaveProvider(recorder.WaveFormat);
        savingWaveProvider = new SavingWaveProvider(bufferedWaveProvider, "temp.wav");

        // set up playback
        player = new WaveOut();
        player.Init(savingWaveProvider);

        // 190305   / Signal Generator : Sine 50~2000 Hz, 2 sec
        SignalGenerator sweep_out = new SignalGenerator();
        sweep_out.Gain = 1;
        sweep_out.Frequency = 50;
        sweep_out.FrequencyEnd = 2000;
        sweep_out.SweepLengthSecs = 2;
        sweep_out.Type = SignalGeneratorType.Sweep;

        player_sweep = new WaveOut();   // 190305
        player_sweep.Init(sweep_out); // 190305

        // begin playback amp; record
        recorder.StartRecording();

        timer1.Enabled = true;

        // begin playback amp; record
        player.Play();      // Start Recording

        player_sweep.Play();    // 190305
    }

    private void RecorderOnDataAvailable(object sender, WaveInEventArgs waveInEventArgs)
    {
        bufferedWaveProvider.AddSamples(waveInEventArgs.Buffer, 0, waveInEventArgs.BytesRecorded);
    }

    private void timer1_Tick(object sender, EventArgs e)    // 190305
    {
        timer1.Enabled = false;

        player_sweep.Stop();    // 190305

        // stop playback
        player.Stop();

        // stop recording
        recorder.StopRecording();


        // finalise the WAV file
        savingWaveProvider.Dispose();

    }
}
  

Комментарии:

1. Пометка на потом. Когда я вернусь домой, я поделюсь своим решением

Ответ №1:

Я снова изучил NAudio. ( https://www.pluralsight.com/courses/audio-programming-naudio / ) И я получил решение, как показано ниже.

Моя цель: генерировать синусоидальный сигнал -> Динамик -> МИКРОФОН -> Запись (волна)

используя это, я хочу дополнительно проанализировать состояние динамика с помощью FFT.

  1. Генерировать синусоидальный сигнал:NAudio.Wave.SamplePrividers.SignalGenerator
  2. Выход динамика: NAudio.Wave.WaveOut
  3. Микрофон: NAudio.Wave.WaveIn
  4. Запись (волна): NAudio.Wave.WaveFileWriter

// Исходный код

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Diagnostics;   // for Process, Stopwatch
using NAudio.Wave;    // for WaveOut, WaveIn
using NAudio.Wave.SampleProviders;  // for SignalGenerator

namespace Speaker_Record-Wave
{
    public partial class Form1 : Form
    {
        // 0) StopWatch
        Stopwatch stopWatch;

        // 1) Signal Gen -> Speaker
        WaveOut waveOut;
        SignalGenerator signalGenerator;

        // 2) MIC -> Wave
        WaveIn waveIn;
        WaveFileWriter waveFileWriter;

        public Form1()
        {
            InitializeComponent();
        }

        private void bt_Start_Click(object sender, EventArgs e)
        {
            // 0) StopWatch
            stopWatch = new Stopwatch();
            stopWatch.Start();

            // 1) Signal Gen -> Speaker
            Start_Signal();

            // 3) Timer_Sweep
            timer_Sweep.Interval = 1500;
            timer_Sweep.Enabled = true;

            // 2) MIC -> Wave
            Start_Record();
        }

        private void timer_Sweep_Tick(object sender, EventArgs e)
        {
            // 3) Timer_Sweep
            timer_Sweep.Enabled = false;

            // 1) Signal Gen -> Speaker
            waveOut.Stop();

            // 2) MIC -> Wave
            waveIn.StopRecording();

            // 4) 공통
            waveOut.Dispose();
            waveIn.Dispose();
            waveFileWriter.Dispose();

            // 0) StopWatch
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            string es = String.Format("{0:00}:{1:00}:{2:00}:{3:00}",ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);

            tb_Result.AppendText(es   "n");
        }

        private void bt_Open_Folder_Click(object sender, EventArgs e)
        {
            Process.Start(".\");   // Open Folder
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////

        // 1) Signal Gen -> Speaker
        private void Start_Signal()
        {
            signalGenerator = new SignalGenerator();
            signalGenerator.Type = SignalGeneratorType.Sweep;
            signalGenerator.Frequency = 50;
            signalGenerator.FrequencyEnd = 5000;
            signalGenerator.SweepLengthSecs = 1.5;

            waveOut = new WaveOut();
            waveOut.DeviceNumber = 0;
            waveOut.Init(signalGenerator);
            waveOut.Play();
        }

        // 2) MIC -> Wave
        private void Start_Record()
        {
            waveIn = new WaveIn();
            waveIn.DeviceNumber = 0;
            waveIn.WaveFormat = new WaveFormat(44100, 16, 1);

            waveIn.DataAvailable  = OnDataAvailable;
            waveIn.RecordingStopped  = OnRecordingStopped;

            waveFileWriter = new WaveFileWriter("1_Recorded.wav", waveIn.WaveFormat);

            waveIn.StartRecording();
        }

        // 2) MIC -> Wave
        private void OnDataAvailable(object sender, WaveInEventArgs e)
        {
            if (waveFileWriter != null)
            {
                waveFileWriter.Write(e.Buffer, 0, e.BytesRecorded);
            }
        }

        // 2) MIC -> Wave
        private void OnRecordingStopped(object sender, StoppedEventArgs e)
        {
            waveIn.Dispose();
            waveFileWriter.Dispose();
        }
    }
}