How to Record silence without MIC - c#

I have a desktop application in C# that records audio from MIC using NAudio library. The application starts recording from default input device if MIC is connected to the system. The output wave file is saved.
I want to record silent to the output file if MIC is not connected, How can I feed a dummy MIC or virtual MIC to starts recording from if real mic is not connected.
Thanks
Here's the Code:
class AudioRecorder
{
private WaveIn waveIn = null;
private WaveFileWriter waveWriter = null;
public AudioRecorder()
{
if (WaveIn.DeviceCount > 0) //Means there is a mic
{
waveIn = new WaveIn();
waveIn.DeviceNumber = 0; //default device
waveIn.DataAvailable += WaveIn_DataAvailable;
}
else
{
//I want to add the virtual mic that will send only silent signal
}
}
public void Start()
{
waveIn.StartRecording();
}
public void Stop()
{
waveIn.StopRecording();
}
private void WaveIn_DataAvailable(object sender, WaveInEventArgs e)
{
if (waveWriter == null)
waveWriter = new WaveFileWriter("output.wav", new WaveFormat(44100, 2));
waveWriter.Write(e.Buffer, 0, e.BytesRecorded);
}
}

Related

MediaRecorder doesn't start in android xamarin

I am developing an app where i can upload videos of upto 2 mins per user.
I want the user to record a video and upload it to the server.I am able to do it with intent but not with media recorder.
The requirement is to not allow user to preview the video and instead record it and when user stops recording, upload the video to server.
(Is it possible to not allow the playback of the recorded video in VIDEO_CAPTURE intent ???)
I am trying to record a video with media recorder. But it throws an exception at MediaRecorder.Start()
Here's the code : -
//Class level variables
Camera PhoneCamera;
VideoView VideoRecorderView;
MediaRecorder VideoRecorder;
Button BtnRecordVideo;
// I start a video recording on click of the button
void RecordVideoWithCustomRecorder(object sender,EventArgs e){
//TODO : Create a custom layout for recording video in one shot and then uplaoding it to kaltura server
if (IsRecording) {
VideoRecorder.Stop ();
ReleaseMediaRecorder ();
PhoneCamera.Lock ();
(sender as Button).SetBackgroundResource (Resource.Drawable.record_red);
StopTimer ();
//UploadVideo
byte[] getBytes = System.IO.File.ReadAllBytes (RecorderFile._file.AbsolutePath);
UploadVideoToKaltura (getBytes);
IsRecording = false;
} else {
ReleaseCamera ();
if (PrepareVideoRecorder ()) {
//System.Threading.Thread.Sleep (1000); i tried putting this, but it won't work
VideoRecorder.Start ();//I get an exception here - not sure why
RunOnUiThread (() => {
(sender as Button).SetBackgroundResource (Resource.Drawable.record_stop);
initTimer2 ();
IsRecording = true;
});
} else {
ReleaseMediaRecorder ();
RunOnUiThread (() => {
AlertDialogManager.ShowDialogWithSingleButton(this,"Video Error","Can't record the video now. Exit the camera and try recording again.","Exit Camera",(()=>{
this.Finish();
}));
});
}
}
}
//Here's the code to prepare the media recorder
bool PrepareVideoRecorder(){
PhoneCamera = IsFrontCameraAvailable ? Camera.Open (1) : Camera.Open ();
VideoRecorder = new MediaRecorder ();
//Unlock & set camera to media recorder
PhoneCamera.Unlock ();
VideoRecorder.SetCamera (PhoneCamera);
//Set Source - Video and audio
VideoRecorder.SetAudioSource (AudioSource.Camcorder);
VideoRecorder.SetVideoSource (VideoSource.Camera);
//set Camcorder profile
VideoRecorder.SetProfile(CamcorderProfile.Get(CamcorderQuality.High));
//set output file
RecorderFile._file = new File(RecorderFile._dir, String.Format("vm_movie_{0}.mp4", Guid.NewGuid()));
VideoRecorder.SetOutputFile (RecorderFile._file.AbsolutePath);
//set preview display
VideoRecorder.SetPreviewDisplay (VideoRecorderView.Holder.Surface);
//Prepare media recorder
VideoRecorder.SetMaxDuration (12000);
try{
VideoRecorder.Prepare();
}catch(Exception ex){
Utils.WriteDebugInfo ("Excepion -PrepareVideoRecorder: " + ex.Message);
return false;
}
return true;
}
//Release Media Recorder
private void ReleaseMediaRecorder(){
if (VideoRecorder != null) {
VideoRecorder.Reset(); // clear recorder configuration
VideoRecorder.Release(); // release the recorder object
VideoRecorder = null;
PhoneCamera.Lock(); // lock camera for later use
}
}
//Release Camers
private void ReleaseCamera(){
if (PhoneCamera != null){
PhoneCamera.Release ();
// release the camera for other applications
PhoneCamera = null;
}
}
//Creating app specific diary for videos
private void CreateDirectoryForVideos()
{
RecorderFile._dir = new File(Environment.GetExternalStoragePublicDirectory(Environment.DirectoryPictures),"VirtualMentorVideos");
if (!RecorderFile._dir.Exists())
{
RecorderFile._dir.Mkdirs();
}
}

System audio to Skype using Naudio

I've been at this for a while, but made no progress. So this is my last resort!
I am trying to send the system-audio (the audio I hear in my headphones) to Skype (making the persons in my call hear what I hear basically). And I thought I would do this using the Skype4comlib and naudio.
What I've done is to create a class which uses the WasapiLoopbackCapture and WaveFileWriter to write temporary data to a .wav file, and redirect audio using the SkypeSystemAudio.set_InputDevice method. But when I'm talking to somebody and I try to start recording, the person doesn't hear me anymore. I just go completely quiet and no sound is being played to the person.
I thought it would be best if I posted the whole class since it's easier to understand everything.
public class SkypeSystemAudio
{
public NAudio.Wave.WasapiLoopbackCapture capture;
NAudio.CoreAudioApi.MMDevice device;
NAudio.Wave.WaveFileWriter writer;
private Call CurrentCall = null;
private Skype SkypeApplet;
private const int SkypeProtocol = 9;
private bool IsRecording = false;
public string tempfilepath = System.IO.Directory.GetCurrentDirectory() + #"\temp.wav";
#region Public
public void Initialize()
{
device = NAudio.Wave.WasapiLoopbackCapture.GetDefaultLoopbackCaptureDevice();
Init();
}
public void Initialize(NAudio.CoreAudioApi.MMDevice device)
{
this.device = device;
Init();
}
public void StartRecording()
{
capture.StartRecording();
if (CurrentCall != null)
{
CurrentCall.set_OutputDevice(TCallIoDeviceType.callIoDeviceTypeFile, tempfilepath);
IsRecording = true;
}
}
public void StopRecording()
{
capture.StopRecording();
if (CurrentCall != null)
{
CurrentCall.set_OutputDevice(TCallIoDeviceType.callIoDeviceTypeFile, "");
}
}
#endregion
private void Init()
{
capture = new WasapiLoopbackCapture(device);
capture.ShareMode = NAudio.CoreAudioApi.AudioClientShareMode.Shared;
capture.DataAvailable += capture_DataAvailable;
capture.RecordingStopped += capture_RecordingStopped;
WaveFormat format = new WaveFormat(16000, 1); // skype wants 16 Bit samples, 16khz, mono WAV file
//tried using the standard waveformat in the device object too. Didn't work though.
writer = new WaveFileWriter(tempfilepath, format );
SkypeApplet = new Skype();
SkypeApplet.Attach(SkypeProtocol, true);
SkypeApplet.CallStatus += SkypeApplet_CallStatus;
}
void SkypeApplet_CallStatus(Call pCall, TCallStatus Status)
{
if (Status == TCallStatus.clsRinging)
{
CurrentCall = pCall;
pCall.Answer();
}
}
void capture_DataAvailable(object sender, WaveInEventArgs e)
{
if (writer != null)
writer.Write(e.Buffer, 0, e.BytesRecorded);
}
void capture_RecordingStopped(object sender, StoppedEventArgs e)
{
IsRecording = false;
}
}
Does anyone know why this isn't working? I have no clues anymore what to do next.
Any help will greatly appreciated!
I have actually done some something similar, but not using Skype4COM.
What I did was using "Virtual Cables" just like Sebastian L suggested, this way you can control whats going in and out off skype, the downside is that you need to install the virtual cables and configure Skype to use them.
The cables will appear in audio devices as standard input/output.
I have used these cables VAC and VB cable
Hope it helps.

Convert WasapiLoopbackCapture wav audio stream to MP3 file

I am able to capture system audio which is generated by speaker with the help of WasapiLoopbackCapture (naudio). but the problem is it capture wav file and size of wav file very large (almost 10 to 15 MB/Min). I have to capture 2-3 hour audio and this will be too high.
I m looking for a solution that will convert wav stream which is capture by WasapiLoopbackCapture convert to MP3 and then save this to disk. I try a loat with LAME.exe or other solution but not get success. Any working code.
Here is My Code:
private void button1_Click(object sender, EventArgs e){
LoopbackRecorder obj = new LoopbackRecorder();
string a = textBox1.Text;
obj.StartRecording(#"e:\aman.mp3");
}
public class LoopbackRecorder
{
private IWaveIn _waveIn;
private Mp3WaveFormat _mp3format;
private WaveFormat _wavFormat;
private WaveFileWriter _writer;
private bool _isRecording = false;
/// <summary>
/// Constructor
/// </summary>
public LoopbackRecorder()
{
}
/// <summary>
/// Starts the recording.
/// </summary>
/// <param name="fileName"></param>
public void StartRecording(string fileName)
{
// If we are currently record then go ahead and exit out.
if (_isRecording == true)
{
return;
}
_fileName = fileName;
_waveIn = new WasapiLoopbackCapture();
// _waveIn.WaveFormat = new WaveFormat(16000, 16 , 2);
_writer = new WaveFileWriter(fileName, _waveIn.WaveFormat);
_waveIn.DataAvailable += OnDataAvailable;
// _waveIn.RecordingStopped += OnRecordingStopped;
_waveIn.StartRecording();
_isRecording = true;
}
private void OnDataAvailable(object sender, WaveInEventArgs waveInEventArgs)
{
if (_writer == null)
{
_writer = new WaveFileWriter(#"e:\aman.mp3", _waveIn.WaveFormat);
}
_writer.Write(waveInEventArgs.Buffer, 0, waveInEventArgs.BytesRecorded);
byte[] by= Float32toInt16(waveInEventArgs.Buffer, 0, waveInEventArgs.BytesRecorded);
}
private string _fileName = "";
/// <summary>
/// The name of the file that was set when StartRecording was called. E.g. the current file being written to.
/// </summary>
public string FileName
{
get
{
return _fileName;
}
}
}
Here's an example of using NAudio.Lame (in a console application) to capture data from sound card loopback and write direct to an MP3 file:
using System;
using NAudio.Lame;
using NAudio.Wave;
namespace MP3Rec
{
class Program
{
static LameMP3FileWriter wri;
static bool stopped = false;
static void Main(string[] args)
{
// Start recording from loopback
IWaveIn waveIn = new WasapiLoopbackCapture();
waveIn.DataAvailable += waveIn_DataAvailable;
waveIn.RecordingStopped += waveIn_RecordingStopped;
// Setup MP3 writer to output at 32kbit/sec (~2 minutes per MB)
wri = new LameMP3FileWriter( #"C:\temp\test_output.mp3", waveIn.WaveFormat, 32 );
waveIn.StartRecording();
stopped = false;
// Keep recording until Escape key pressed
while (!stopped)
{
if (Console.KeyAvailable)
{
var key = Console.ReadKey(true);
if (key != null && key.Key == ConsoleKey.Escape)
waveIn.StopRecording();
}
else
System.Threading.Thread.Sleep(50);
}
// flush output to finish MP3 file correctly
wri.Flush();
// Dispose of objects
waveIn.Dispose();
wri.Dispose();
}
static void waveIn_RecordingStopped(object sender, StoppedEventArgs e)
{
// signal that recording has finished
stopped = true;
}
static void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
// write recorded data to MP3 writer
if (wri != null)
wri.Write(e.Buffer, 0, e.BytesRecorded);
}
}
}
At the moment the NAudio.Lame package on NuGet is compiled for x86 only, so make sure your application is set to target that platform.
To convert the audio to MP3 on the fly, one of the easiest ways is to use the command line options that let you pass audio into LAME.exe via stdin. I describe how to do that in this article.
You may also be interested that Corey Murtagh has created a LAME package for NAudio. I haven't tried it myself, but it looks like it should also do the job. Documentation is here.

naudio record sound from microphone then save

I'm having some issues with naudio and saving sound recordings. The code I currently have works to the point where it saves the wav file, but when I open it up, Windows Media Player returns an error: "Windows Media Player encountered a problem while playing the file"
I have two buttons, a "Record" button, which turns into the stop button after it's pressed. And I have a "Save" button which when clicked, saves the recording to sample.wav.
NAudio.Wave.WaveIn sourceStream = null;
NAudio.Wave.DirectSoundOut waveOut = null;
NAudio.Wave.WaveFileWriter waveWriter = null;
private void recordButton_Click(object sender, EventArgs e)
{
int deviceNumber = sourceList.SelectedItems[0].Index;
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = deviceNumber;
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(deviceNumber).Channels);
NAudio.Wave.WaveInProvider waveIn = new NAudio.Wave.WaveInProvider(sourceStream);
waveOut = new NAudio.Wave.DirectSoundOut();
waveOut.Init(waveIn);
sourceStream.StartRecording();
waveOut.Play();
recordButton.Visible = false;
stopRecord.Visible = true;
}
private void saveResponse_Click(object sender, EventArgs e)
{
int deviceNumber = sourceList.SelectedItems[0].Index;
string saveLocation = "c:\\wav\\sample.wav";
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = deviceNumber;
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(deviceNumber).Channels);
sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(sourceStream_DataAvailable);
waveWriter = new NAudio.Wave.WaveFileWriter(saveLocation, sourceStream.WaveFormat);
sourceStream.StartRecording();
MessageBox.Show("Recording successfully saved.");
}
private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
{
if (waveWriter == null) return;
waveWriter.WriteData(e.Buffer, 0, e.BytesRecorded);
waveWriter.Flush();
}
private void stopRecord_Click(object sender, EventArgs e)
{
if (waveOut != null)
{
waveOut.Stop();
waveOut.Dispose();
waveOut = null;
}
if (sourceStream != null)
{
sourceStream.StopRecording();
sourceStream.Dispose();
sourceStream = null;
}
if (waveWriter != null)
{
waveWriter.Dispose();
waveWriter = null;
}
recordButton.Visible = true;
stopRecord.Visible = false;
saveResponse.Enabled = true;
}
Your recordButton_Click code isn't recording, it's piping data from a WaveIn to a WaveOut, which will play the data coming from your source (microphone) directly to the output (speakers). It doesn't retain that data for later use, it just pipes it from one to the other. If you want to subsequently save that data to disk, you need to buffer it yourself.
The saveResponse_Click on the other hand is starting the direct recording of data from the microphone to a wave file on disk. If you click your Save Response button, wait for a bit, then click your Stop button, you should get a recorded wave file.
If you want to record directly to disk, this is fine. If you want to record to memory, then optionally write to disk, then you need to save the data as it comes in. Perhaps use a memory stream to hold the data while recording, then write that to the WaveFileWriter when it comes time to save the file.
Here's the code I used for testing direct recording to a wave file on disk:
public WaveIn waveSource = null;
public WaveFileWriter waveFile = null;
private void StartBtn_Click(object sender, EventArgs e)
{
StartBtn.Enabled = false;
StopBtn.Enabled = true;
waveSource = new WaveIn();
waveSource.WaveFormat = new WaveFormat(44100, 1);
waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);
waveFile = new WaveFileWriter(#"C:\Temp\Test0001.wav", waveSource.WaveFormat);
waveSource.StartRecording();
}
private void StopBtn_Click(object sender, EventArgs e)
{
StopBtn.Enabled = false;
waveSource.StopRecording();
}
void waveSource_DataAvailable(object sender, WaveInEventArgs e)
{
if (waveFile != null)
{
waveFile.Write(e.Buffer, 0, e.BytesRecorded);
waveFile.Flush();
}
}
void waveSource_RecordingStopped(object sender, StoppedEventArgs e)
{
if (waveSource != null)
{
waveSource.Dispose();
waveSource = null;
}
if (waveFile != null)
{
waveFile.Dispose();
waveFile = null;
}
StartBtn.Enabled = true;
}

Record continuously 5min (x-minutes) of video with Microsoft Expression Encoder

My Software is to record continuously 5min of video.
Example: the software should start the recording on program-start and hold continuously 5min of video in buffer. When I stop the recording the last 5min of recording should save to disk
private void CaptureMoni()
{
try
{
Rectangle _screenRectangle = Screen.PrimaryScreen.Bounds;
_screenCaptureJob = new ScreenCaptureJob();
_screenCaptureJob.CaptureRectangle = _screenRectangle;
_screenCaptureJob.ShowFlashingBoundary = true;
_screenCaptureJob.ScreenCaptureVideoProfile.FrameRate = 20;
_screenCaptureJob.CaptureMouseCursor = true;
_screenCaptureJob.OutputScreenCaptureFileName = string.Format(#"C:\test.wmv");
if (File.Exists(_screenCaptureJob.OutputScreenCaptureFileName))
{
File.Delete(_screenCaptureJob.OutputScreenCaptureFileName);
}
_screenCaptureJob.Start();
}
catch(Exception e) { }
}
something like that:
private void SaveRecord(int cntMinutes)
{
try
{
_screenCaptureJob.Stop();
// something like that
_screenCaptureJob.SaveLastXMinutes(cntMinutes);
}
catch(Exception e) { }
}

Categories

Resources