Search code examples
c#audionaudio

Playing multiple MP3s in Sync using NAudio in C#


I have 4 mono MP3s recorded simultaneously of 4 speakers (persons) having a conversation. Although each person has their own microphone and dominates the audio in each track there is substantial bleed that even if off by 50 to 100 msec you can notice it on play back.

At the moment with my first attempt using NAudio Library to build a windows app, it is very bad with over 500msec in some cases.

I have achieve a semi-passable result it with WMPLib, and although it works better the playback still not perfect.

I also want to use some of the other abilities of the NAudio Library, so it is my preferred option.

Below is my attempt at it. Although it does play the 4 files the timing is totally off.

Thank you.

using NAudio.Wave;
using NAudio_Test.Properties;
using System;
using System.Windows.Forms;


namespace NAudio_Test
{

    public partial class Form1 : Form
    {
        public WaveOutEvent outputDevice1;
        public WaveOutEvent outputDevice2;
        public WaveOutEvent outputDevice3;
        public WaveOutEvent outputDevice4;
        public AudioFileReader audioFile1;
        public AudioFileReader audioFile2;
        public AudioFileReader audioFile3;
        public AudioFileReader audioFile4;

        public Form1()
        {
            InitializeComponent();

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            lbDirectory.Text = Settings.Default.StartingDirectory;
            lbFile.Text = Settings.Default.File;


        }


        private void btnStop_Click(object sender, EventArgs e)
        {
            outputDevice1?.Stop();
            outputDevice2?.Stop();
        }

        private void OnPlaybackStopped(object sender, StoppedEventArgs args)
        {
            outputDevice1?.Dispose();
            outputDevice1 = null;
            outputDevice2?.Dispose();
            outputDevice2 = null;
            outputDevice3?.Dispose();
            outputDevice3 = null;
            outputDevice4?.Dispose();
            outputDevice4 = null;


            audioFile1?.Dispose();
            audioFile2?.Dispose();
            audioFile3?.Dispose();
            audioFile4?.Dispose();
            audioFile1 = null;
            audioFile2 = null;
            audioFile3 = null;
            audioFile4 = null;
        }

        private void btnPlay_Click(object sender, EventArgs e)
        {
            if (outputDevice1 == null)
            {
                outputDevice1 = new WaveOutEvent();
                outputDevice1.PlaybackStopped += OnPlaybackStopped;

            }
            if (outputDevice2 == null)
            {
                outputDevice2 = new WaveOutEvent();
                outputDevice2.PlaybackStopped += OnPlaybackStopped;

            }
            if (outputDevice3 == null)
            {
                outputDevice3 = new WaveOutEvent();
                outputDevice3.PlaybackStopped += OnPlaybackStopped;

            }
            if (outputDevice4 == null)
            {
                outputDevice4 = new WaveOutEvent();
                outputDevice4.PlaybackStopped += OnPlaybackStopped;

            }
            if (audioFile1 == null)
            {
                string mp3file1 = lbDirectory.Text + "\\" + lbFile.Text + "_1.mp3";
                Console.WriteLine(mp3file1);
                audioFile1 = new AudioFileReader(mp3file1);
                outputDevice1.Init(audioFile1);
            }
            if (audioFile2 == null)
            {
                string mp3file2 = lbDirectory.Text + "\\" + lbFile.Text + "_2.mp3";
                Console.WriteLine(mp3file2);
                audioFile2 = new AudioFileReader(mp3file2);
                outputDevice2.Init(audioFile2);
            }
            if (audioFile3 == null)
            {
                string mp3file3 = lbDirectory.Text + "\\" + lbFile.Text + "_3.mp3";
                Console.WriteLine(mp3file3);
                audioFile3 = new AudioFileReader(mp3file3);
                outputDevice3.Init(audioFile2);
            }
            if (audioFile4 == null)
            {
                string mp3file4 = lbDirectory.Text + "\\" + lbFile.Text + "_4.mp3";
                Console.WriteLine(mp3file4);
                audioFile4 = new AudioFileReader(mp3file4);
                outputDevice4.Init(audioFile2);
            }

            outputDevice1.Play();
            outputDevice2.Play();
            outputDevice3.Play();
            outputDevice4.Play();
        }
    }
}


Solution

  • Just found MixingWaveProvider32 that does the job.

        public WaveOut outputDevice1;
        public MixingWaveProvider32 waveProvider;
        public AudioFileReader audioFile1;
        public AudioFileReader audioFile2;
        public AudioFileReader audioFile3;
        public AudioFileReader audioFile4;
    

    and in the play button

        private void btnPlay_Click(object sender, EventArgs e)
        {
            string file1 = lbDirectory.Text + "\\" + lbFile.Text + "_1.mp3";
            string file2 = lbDirectory.Text + "\\" + lbFile.Text + "_2.mp3";
            string file3 = lbDirectory.Text + "\\" + lbFile.Text + "_3.mp3";
            string file4 = lbDirectory.Text + "\\" + lbFile.Text + "_4.mp3";
            Console.WriteLine(file1);
            Console.WriteLine(file2);
            Console.WriteLine(file3);
            Console.WriteLine(file4);
    
            audioFile1 = new AudioFileReader(file1);
            audioFile2 = new AudioFileReader(file2);
            audioFile3 = new AudioFileReader(file3);
            audioFile4 = new AudioFileReader(file4);
    
            waveProvider = new MixingWaveProvider32(new IWaveProvider[] { audioFile1, audioFile2, audioFile3, audioFile4 });
            outputDevice1 = new WaveOut();
            outputDevice1.Init(waveProvider);
            outputDevice1.Play();
        }