noob123
noob123

Reputation: 69

Audio Stream from Sound Card to Byte Array in C#

I am trying to get the audio from the sound card and write the audio data to the byte array.

So far, I could manage these: Get the audio, save the file in wav format, get byte array from the wav file.

But, I need to get the byte array from a live audio [simultaneously], not from a saved file. So, how can I do that? I read some documentation but could not find a specific implementation.

public partial class Form1 : Form
{
    [DllImport("winmm.dll")]
    private static extern long mciSendString(string command, StringBuilder retstrign, int Returnlength, IntPtr callback);
    public Form1()
    {
        InitializeComponent();
        mciSendString("open new Type waveaudio alias recsound", null, 0, IntPtr.Zero);
        button1.Click += new EventHandler(this.button1_Click);

    }

    private void button1_Click(object sender, EventArgs e)
    {
        //    throw new NotImplementedException();
        mciSendString("record recsound", null, 0, IntPtr.Zero);
        button2.Click += new EventHandler(this.button2_Click);

    }

    private void button2_Click(object sender, EventArgs e)
    {
        string filename = @"C:\Users\seymk\Downloads\BackwardsApp-master\test.wav";
        
        //throw new NotImplementedException();
        mciSendString(@"save recsound C:\Users\seymk\Downloads\BackwardsApp-master\test.wav", null, 0, IntPtr.Zero);
        mciSendString("close recsound", null, 0, IntPtr.Zero);

        //ReadWav(filename, out float[] L, out float[] R);

        using (WaveFileReader reader = new WaveFileReader("filename"))
        {
            Assert.AreEqual(16, reader.WaveFormat.BitsPerSample, "Only works with 16 bit audio");
            byte[] buffer = new byte[reader.Length];
            int read = reader.Read(buffer, 0, buffer.Length);
            short[] sampleBuffer = new short[read / 2];
            Buffer.BlockCopy(buffer, 0, sampleBuffer, 0, read);
        }
    }
}

UPDATE

Below, I can record and listen to the audio simultaneously. I still couldn't figure out how to get the byte array at the same time.

Because when I try to get the byte array from the wav file, since it is still being processed, I get the error that the file is in usage by other applications.

public partial class Form1 : Form
    {
        private WaveIn recorder;
        private BufferedWaveProvider bufferedWaveProvider;
        private SavingWaveProvider savingWaveProvider;
        private WaveOut player;
        private string filename = @"C:\Users\seymk\Downloads\BackwardsApp-master\test.wav";
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click_1(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, filename);

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

            // begin playback & record
            player.Play();         
            recorder.StartRecording();

        }
        private void button2_Click_1(object sender, EventArgs e)
        {
            // stop recording
            recorder.StopRecording();
            // stop playback
            player.Stop();
            // finalise the WAV file
            savingWaveProvider.Dispose();
        }

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

public class SavingWaveProvider : IWaveProvider, IDisposable
{
    private readonly IWaveProvider sourceWaveProvider;
    private readonly WaveFileWriter writer;
    private bool isWriterDisposed;

    public SavingWaveProvider(IWaveProvider sourceWaveProvider, string wavFilePath)
    {
        this.sourceWaveProvider = sourceWaveProvider;
        writer = new WaveFileWriter(wavFilePath, sourceWaveProvider.WaveFormat);
    }

    public int Read(byte[] buffer, int offset, int count)
    {
        var read = sourceWaveProvider.Read(buffer, offset, count);
        if (count > 0 && !isWriterDisposed)
        {
            writer.Write(buffer, offset, read);
        }
        if (count == 0)
        {
            Dispose(); // auto-dispose in case users forget
        }
        return read;
    }

    public WaveFormat WaveFormat { get { return sourceWaveProvider.WaveFormat; } }

    public void Dispose()
    {
        if (!isWriterDisposed)
        {
            isWriterDisposed = true;
            writer.Dispose();
        }
    }
}

Upvotes: 1

Views: 974

Answers (0)

Related Questions