I've already purchased the PluralSight course for NAudio and i'm working through a lot of the videos.
I'm trying to figure out how to do the following: Record all microphones and all speakers into one MP3.
So far I have the following code:
using NAudio.CoreAudioApi;
using NAudio.Wave;
using NAudio.Wave.SampleProviders;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AudioTest1 {
public class AudioDevice {
public MMDevice Device { get; set; }
public bool IsSelected { get; set; }
public string FriendlyName { get; set; }
private IWaveIn __Capture;
public IWaveIn Capture {
get {
return __Capture;
}
set {
if(__Capture != null) {
__Capture.DataAvailable -= this.__Capture_DataAvailable;
}
__Capture = value;
if (__Capture != null) {
__Capture.DataAvailable += this.__Capture_DataAvailable;
}
}
}
private void __Capture_DataAvailable(object sender, WaveInEventArgs e) {
if(Buffer != null) {
Buffer.AddSamples(e.Buffer, 0, e.BytesRecorded);
}
}
public IWaveProvider Provider { get; set; }
public BufferedWaveProvider Buffer { get; set; }
public IWaveProvider Output { get; set; }
}
public class MainWindowDataModel {
public ObservableCollection<AudioDevice> AudioDevices { get; private set; } = new ObservableCollection<AudioDevice>();
public WaveFormat Format = new WaveFormat(16000, 8, 1);
public MainWindowDataModel(){
using (var Enumerator = new MMDeviceEnumerator()) {
var Devices = Enumerator.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active).ToList();
foreach(var Device in Devices) {
Device.AudioEndpointVolume.Mute = false;
var Capture =
Device.DataFlow == DataFlow.Capture
? new WasapiCapture(Device)
: new WasapiLoopbackCapture(Device)
;
var Provider = new WaveInProvider(Capture);
var Silence = new SilenceProvider(Capture.WaveFormat);
var Buffer = new BufferedWaveProvider(Capture.WaveFormat);
var Output = Device.DataFlow == DataFlow.Capture
? new MixingWaveProvider32(new IWaveProvider[] { Provider })
: new MixingWaveProvider32(new IWaveProvider[] { Silence, Buffer })
;
AudioDevices.Add(new AudioDevice() {
Device = Device,
IsSelected = true,
FriendlyName = Device.FriendlyName,
Capture = Capture,
Provider = Provider,
Buffer = Buffer,
Output = Output,
});
Capture.StartRecording();
}
var C = new MixingSampleProvider(from x in AudioDevices select x.Output.ToSampleProvider());
//C.AddMixerInput(new SignalGenerator());
WaveFileWriter.CreateWaveFile(@"C:\Test2.wav", C.Take(TimeSpan.FromSeconds(5)).ToWaveProvider());
}
}
}
}
When I try to create the wave file, the function seems to return immediately instead of waiting for the 5 seconds to pass. What is the best way for me to record this audio together?
Mixing audio on the fly as you record it is actually quite tricky, as buffers arrive at different times from each recording device, and may not be the same duration. Also, if recording did not start at the same time or there are dropouts there are potential synchronization issues to resolve.
The easiest solution I usually recommend is that people record each microphone to a temporary file, and then mix them afterwards.
If you did want to mix them on the fly, then I'd use something like a BufferedWaveProvider
storing audio from each recording device. Whenever a new recorded buffer of audio comes in, it gets written to the appropriate BufferedWaveProvider
. Then, once all the BufferedWaveProviders
have more than a certain threshold of audio in them, mix that amount of audio into the target file.