i just want to hear what i say to microphone using NAudio and this is my code so far but the problem is i can't hear anything. any help would be appreciated.
public partial class frmMain : Form
{
private WaveIn waveIn; // Gets an audio from microphone
private WaveOut waveOut; // Sends audio to speaker
private BufferedWaveProvider waveProvider; // Gets an audio from stream
public frmMain()
{
InitializeComponent();
}
private void frmMain_Load(object sender, EventArgs e)
{
waveOut = new WaveOut();
waveIn = new WaveIn();
waveProvider = new BufferedWaveProvider(waveIn.WaveFormat);
waveOut.Init(waveProvider);
waveIn.DataAvailable += waveIn_DataAvailable;
waveOut.Play();
}
private void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
waveProvider.Read(e.Buffer, 0, e.BytesRecorded);
}
private void btnStop_Click(object sender, EventArgs e)
{
waveIn.StopRecording();
waveIn.Dispose();
}
private void btnStart_Click(object sender, EventArgs e)
{
waveIn.StartRecording();
}
}
i will use this scenario in network programming on which i send the data from microphone to the socket then on the client side the BufferedWaveProvider will read the data then send it to the speaker. Please put also some comment if what is the better way to do it.
TIA
Sample code as promised. Code is for a form with two buttons (named StartBtn and StopBtn).
public partial class Form1 : Form
{
private WaveIn waveIn = null;
private BufferedWaveProvider waveProvider = null;
private WaveOut waveOut = null;
public Form1()
{
InitializeComponent();
}
private void StartBtn_Click(object sender, EventArgs e)
{
if (waveIn != null)
return;
// create wave input from mic
waveIn = new WaveIn(this.Handle);
waveIn.BufferMilliseconds = 25;
waveIn.RecordingStopped += waveIn_RecordingStopped;
waveIn.DataAvailable += waveIn_DataAvailable;
// create wave provider
waveProvider = new BufferedWaveProvider(waveIn.WaveFormat);
// create wave output to speakers
waveOut = new WaveOut();
waveOut.DesiredLatency = 100;
waveOut.Init(waveProvider);
waveOut.PlaybackStopped += wavePlayer_PlaybackStopped;
// start recording and playback
waveIn.StartRecording();
waveOut.Play();
}
void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
// add received data to waveProvider buffer
if (waveProvider != null)
waveProvider.AddSamples(e.Buffer, 0, e.BytesRecorded);
}
private void StopBtn_Click(object sender, EventArgs e)
{
if (waveIn != null)
waveIn.StopRecording();
}
void waveIn_RecordingStopped(object sender, StoppedEventArgs e)
{
// stop playback
if (waveOut != null)
waveOut.Stop();
// dispose of wave input
if (waveIn != null)
{
waveIn.Dispose();
waveIn = null;
}
// drop wave provider
waveProvider = null;
}
void wavePlayer_PlaybackStopped(object sender, StoppedEventArgs e)
{
// stop recording
if (waveIn != null)
waveIn.StopRecording();
// dispose of wave output
if (waveOut != null)
{
waveOut.Dispose();
waveOut = null;
}
}
}
Note especially the waveIn.BufferMilliseconds and waveOut.DesiredLatency settings to reduce the lag times.
For compressing the data for network transmission I suggest using a different library to process the data blocks. You might need to tune the BufferMilliseconds value to reduce the overheads and get better compression ratios.
The Opus Codec looks like a reasonable option, with Opus.NET for C#.
Related
I'm in making barcode scanner but "VideoCaptureDevice can't pick up any objects" ?
I'm using AForge video and ZXing in visual studio 2019 C#
I want it to be able to scan barcodes from my laptop webcam.
I tried running it with the problem but in my combobox where are supposed to be cameras available for use but they are none. I even tried activating the webcam before opening up the program.
code:
FilterInfoCollection FilterInfoCollection;
VideoCaptureDevice VideoCaptureDevice;
private void Form1_Load(object sender, EventArgs e)
{
FilterInfoCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo device in FilterInfoCollection)
comboBox1.Items.Add(device.Name);
comboBox1.SelectedIndex = 0;
}
private void button1_Click(object sender, EventArgs e)
{
VideoCaptureDevice = new VideoCaptureDevice(FilterInfoCollection[comboBox1.SelectedIndex].MonikerString);
VideoCaptureDevice.NewFrame += VideoCaptureDevice_NewFrame;
VideoCaptureDevice.Start();
}
private void VideoCaptureDevice_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap bitmap = (Bitmap)eventArgs.Frame.Clone();
BarcodeReader reader = new BarcodeReader();
var result = reader.Decode(bitmap);
if (result != null)
{
textBox1.Invoke(new MethodInvoker(delegate ()
{
textBox1.Text = result.ToString();
}));
}
pictureBox1.Image = bitmap;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (VideoCaptureDevice != null)
{
if (VideoCaptureDevice.IsRunning)
VideoCaptureDevice.Stop();
}
}
}
}
With this code i can play video files from my hard disk and show the video in pictureBox1. But i wonder how can i save all the frames of the video to images files on the hard disk ? While playing the video or without playing i need somehow to extract the frames and save them.
This is my used code so far:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
IGraphBuilder m_graphBuilder = null;
IMediaControl m_mediaCtrl = null;
IMediaEventEx m_mediaEvt = null;
IMediaPosition m_mediaPos = null;
IMediaSeeking m_mediaSeeking = null;
public Form1()
{
InitializeComponent();
}
void InitInterfaces()
{
try
{
m_graphBuilder = (IGraphBuilder)new FilterGraph();
m_mediaCtrl = (IMediaControl)m_graphBuilder;
m_mediaEvt = (IMediaEventEx)m_graphBuilder;
m_mediaPos = (IMediaPosition)m_graphBuilder;
m_mediaSeeking = (IMediaSeeking)m_graphBuilder;
}
catch (Exception)
{
MessageBox.Show("Couldn't start directshow graph");
}
}
void CloseInterfaces()
{
if (m_mediaCtrl != null)
{
m_mediaCtrl.StopWhenReady();
}
m_mediaCtrl = null;
m_mediaEvt = null;
m_mediaPos = null;
m_mediaSeeking = null;
if (m_graphBuilder != null)
Marshal.ReleaseComObject(this.m_graphBuilder);
m_graphBuilder = null;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void SetuupVideoRenderer()
{
IBaseFilter vmrFilter = null;
vmrFilter = (IBaseFilter)new VideoMixingRenderer();
m_graphBuilder.AddFilter(vmrFilter, "Video Renderer");
IVMRFilterConfig FilterConfig = (IVMRFilterConfig)vmrFilter;
FilterConfig.SetRenderingMode(VMRMode.Windowless);
IVMRWindowlessControl windowlessCtrl = (IVMRWindowlessControl)vmrFilter;
windowlessCtrl.SetVideoClippingWindow(this.pictureBox1.Handle);
windowlessCtrl.SetVideoPosition(null, DsRect.FromRectangle(pictureBox1.ClientRectangle));
windowlessCtrl.SetAspectRatioMode(VMRAspectRatioMode.LetterBox);
}
private void buttonLoad_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "All Files (*.*)|*.*|mp4 (*.mp4)|*.mp4|mov (*.mov)|*.mov||";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
CloseInterfaces();
InitInterfaces();
SetuupVideoRenderer();
m_graphBuilder.RenderFile(openFileDialog1.FileName, null);
textBoxDur.Text = ( getDuration() * 0.0000001).ToString();
m_mediaCtrl.Run();
timer1.Enabled = true;
}
}
private void GetPosition(out long CurrentPos,out long StopPos)
{
m_mediaSeeking.GetPositions(out CurrentPos, out StopPos);
}
private long getDuration()
{
long duration;
m_mediaSeeking.GetDuration(out duration);
return duration;
}
private void SetPos(double fPos)
{
DsLong startPosition = (DsLong)(10000000 * fPos);
m_mediaSeeking.SetPositions(startPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);
}
private void buttonPause_Click(object sender, EventArgs e)
{
m_mediaCtrl.Pause();
}
private void buttonPlay_Click(object sender, EventArgs e)
{
m_mediaCtrl.Run();
}
private void OnVideoCompleted()
{
MessageBox.Show("Video Playback Completed");
}
private void timer1_Tick(object sender, EventArgs e)
{
long iCurPos, iStopPos;
GetPosition(out iCurPos, out iStopPos);
if (iCurPos >= iStopPos)
{
timer1.Enabled = false;
OnVideoCompleted();
return;
}
textBoxCurPos.Text = (iCurPos * 0.0000001 ).ToString();
}
private void buttonGo_Click(object sender, EventArgs e)
{
SetPos(Convert.ToDouble(textBoxNewPos.Text));
timer1.Enabled = true;
}
}
}
I think this is excatly what you are looking for:
extract frames of a video
Have a look as well at this SO question and the links provided on this webpage.
The easiest way to do it is indeed using an FFMPEG, since its alredy includes some of the most common codecs (if you dont mind extra 30+Mb added to your app). As for wrappers, i used AForge wrapper in the past and really liked it, because of how simple it is to work with. Here is an example from its docs:
// create instance of video reader
VideoFileReader reader = new VideoFileReader();
// open video file
reader.Open( "test.avi");
// read 100 video frames out of it
for ( int i = 0; i < 100; i++)
{
Bitmap videoFrame = reader.ReadVideoFrame();
videoFrame.Save(i + ".bmp")
// dispose the frame when it is no longer required
videoFrame.Dispose( );
}
reader.Close();
I am trying to attach USB device used for tele calling which have pnp sound controller for mic and speaker. Now i have two speaker and two mic for input output as shown in image below.. Now my motive is to transfer audio stream from system mic to usb mic and from usb speaker to system speaker.
I tried to solve this issue with virtual cable software but with this i need to depend on third party. What can be the possible solution that can attained using c#.
I don't have knowledge about this, so don't know how to start. After googling i found
CS Core
N Audio
Can help me i don't know how.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
List<NAudio.Wave.WaveInCapabilities> sources = new List<NAudio.Wave.WaveInCapabilities>();
for (int i = 0; i < NAudio.Wave.WaveIn.DeviceCount; i++)
{
sources.Add(NAudio.Wave.WaveIn.GetCapabilities(i));
}
sourceList.Items.Clear();
foreach (var source in sources)
{
ListViewItem item = new ListViewItem(source.ProductName);
item.SubItems.Add(new ListViewItem.ListViewSubItem(item, source.Channels.ToString()));
sourceList.Items.Add(item);
}
}
NAudio.Wave.WaveIn sourceStream,sourceStream1 = null;
NAudio.Wave.DirectSoundOut waveOut = null;
private void button2_Click(object sender, EventArgs e)
{
if (sourceList.SelectedItems.Count == 0) return;
int deviceNumber = sourceList.SelectedItems[0].Index;
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = 0;
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(deviceNumber).Channels);
NAudio.Wave.WaveInProvider waveIn = new NAudio.Wave.WaveInProvider(sourceStream1);
sourceStream.
waveOut = new NAudio.Wave.DirectSoundOut();
waveOut.Init(waveIn);
sourceStream1.StartRecording();
waveOut.Play();
}
private void button3_Click(object sender, EventArgs e)
{
if (waveOut != null)
{
waveOut.Stop();
waveOut.Dispose();
waveOut = null;
}
if (sourceStream != null)
{
sourceStream.StopRecording();
sourceStream.Dispose();
sourceStream = null;
}
}
private void button4_Click(object sender, EventArgs e)
{
button3_Click(sender, e);
this.Close();
}
}
Using this code i can send mic audio to speaker but how can i implement my task using this.
Actually there is no way to do this without writing any custom driver. You can not render audio data to a input device. Input devices are meant to read data from. Output devices (speakers) are meant to write data to.
There are programs like virtual audio cable, which are using custom drivers to bypass these limitations.
I am new to coding in c#. I am building an application to detect the speech and automatically record it. All the information available is based on windows speech recognition engine but my requirement is, the program should detect the speech and record it.
after recording that file is used for processing using hidden markov model(HMM).
namespace Application
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button_1_Click(object sender, EventArgs e)
{
List<NAudio.Wave.WaveInCapabilities> sources = new List<NAudio.Wave.WaveInCapabilities>();
for (int i = 0; i < NAudio.Wave.WaveIn.DeviceCount; i++)
{
sources.Add(NAudio.Wave.WaveIn.GetCapabilities(i));
}
sourceList.Items.Clear();
foreach (var source in sources)
{
ListViewItem item = new ListViewItem(source.ProductName);
item.SubItems.Add(new ListViewItem.ListViewSubItem(item, source.Channels.ToString()));
sourceList.Items.Add(item);
}
}
NAudio.Wave.WaveIn sourceStream = null;
NAudio.Wave.DirectSoundOut waveOut = null;
NAudio.Wave.WaveFileWriter waveWriter = null;
private void button_2_click(object sender, MouseEventArgs e)
{
if (sourceList.SelectedItems.Count == 0) return;
int deviceNumber = sourceList.SelectedItems[0].Index;
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = deviceNumber;
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(16000, NAudio.Wave.WaveIn.GetCapabilities(deviceNumber).Channels);
sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(sourceStream_DataAvailable);
waveWriter = new NAudio.Wave.WaveFileWriter("test.wav", sourceStream.WaveFormat);
sourceStream.StartRecording();
}
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 button_3_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;
}
speechprocessing.Model_test.speech();
}
private void button4_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
this suits my requirement but it has two button to initiate and terminate the recording process which is not under my requirement..
the program should be running and when the speech is detected it must be recorded and further processed. the words which it should detect is also not too much only a few set of words for which we have made the models using hidden markov model..
so please help me out from this problem.
I was trying to develop a Voice recorder in C#. I have tried many ways, like NAudio, DirectX, Microsoft.Xna.Framework.Audio, etc.
Everything gives the same result. After we stop the recording, the output file mp3/wav get saved.
The mp3/wav file get created at the beginning itself (without and content - 0 bytes)
I am trying to create an application which can save audio live/simultaneously.
private void StartRecording() {
this.WaveSource = new WaveInEvent { WaveFormat = new WaveFormat(44100, 1) };
this.WaveSource.DataAvailable += this.WaveSourceDataAvailable;
this.WaveSource.RecordingStopped += this.WaveSourceRecordingStopped;
this.WaveFile = new WaveFileWriter(#"C:\Sample.wav", this.WaveSource.WaveFormat);
this.WaveSource.StartRecording();
}
private void StopRecording() {
this.WaveSource.StopRecording();
}
void WaveSourceDataAvailable(object sender, WaveInEventArgs e) {
if (this.WaveFile != null) {
this.WaveFile.Write(e.Buffer, 0, e.BytesRecorded);
this.WaveFile.Flush();
}
}
void WaveSourceRecordingStopped(object sender, StoppedEventArgs e) {
if (this.WaveSource != null) {
this.WaveSource.Dispose();
this.WaveSource = null;
}
if (this.WaveFile != null) {
this.WaveFile.Dispose();
this.WaveFile = null;
}
}
I have solved the problem with NAudio library itself.
Few modification to the existing code.
public class Recorder {
WaveIn sourceStream;
WaveFileWriter waveWriter;
readonly String FilePath;
readonly String FileName;
readonly int InputDeviceIndex;
public Recorder(int inputDeviceIndex, String filePath, String fileName) {
InitializeComponent();
this.InputDeviceIndex = inputDeviceIndex;
this.FileName = fileName;
this.FilePath = filePath;
}
public void StartRecording(object sender, EventArgs e) {
sourceStream = new WaveIn {
DeviceNumber = this.InputDeviceIndex,
WaveFormat =
new WaveFormat(44100, WaveIn.GetCapabilities(this.InputDeviceIndex).Channels)
};
sourceStream.DataAvailable += this.SourceStreamDataAvailable;
if (!Directory.Exists(FilePath)) {
Directory.CreateDirectory(FilePath);
}
waveWriter = new WaveFileWriter(FilePath + FileName, sourceStream.WaveFormat);
sourceStream.StartRecording();
}
public void SourceStreamDataAvailable(object sender, WaveInEventArgs e) {
if (waveWriter == null) return;
waveWriter.Write(e.Buffer, 0, e.BytesRecorded);
waveWriter.Flush();
}
private void RecordEnd(object sender, EventArgs e) {
if (sourceStream != null) {
sourceStream.StopRecording();
sourceStream.Dispose();
sourceStream = null;
}
if (this.waveWriter == null) {
return;
}
this.waveWriter.Dispose();
this.waveWriter = null;
recordEndButton.Enabled = false;
Application.Exit();
Environment.Exit(0);
}
}
You can do this with DirectShow.
Take a look at Microsoft's documentation and the project's code samples to learn the best way to configure it according to your needs.
Wanna try to BASS NET?
There is a complete code for you task How to record sound and encode it to mp3? (C#!)