I am using NAudio in my project to record sounds from the microphone. I want to convert the sounds to a byte array and then play them back. I am not using windows Forms instead i am doing it in a console application.
//get all the devices that can record audio
private List<WaveInCapabilities> sources = new List<WaveInCapabilities>();
private List<string> Devices = new List<string>();
private List<string> Channels = new List<string>();
public void GetMicDevices()
{
//get the capabilities of all the devices
for(int i = 0; i < WaveIn.DeviceCount; i++)
{
sources.Add(WaveIn.GetCapabilities(i));
}
foreach(var i in sources)
{
Devices.Add(i.ProductName);
Channels.Add(i.Channels.ToString());
}
}
private WaveInEvent source = null;
public void StartMic()
{
//set the device number
int DeviceNum = 0;
source = new WaveInEvent();
//set the device number
source.DeviceNumber = DeviceNum;
//create the waveFormat num of channels for the device
source.WaveFormat = new WaveFormat(44100, WaveIn.GetCapabilities(DeviceNum).Channels);
//start the mic
source.StartRecording();
}
//convert the sound into a byte array
//play the sound from the byte array
I've made some changes to your code and mostly used a memory stream, a Source_DataAvailable event
here is the full working code :
using NAudio.Utils;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
private static List<WaveInCapabilities> sources = new List<WaveInCapabilities>();
private static List<string> Devices = new List<string>();
private static List<string> Channels = new List<string>();
static WaveInEvent source;
static WaveOut _waveOut;
static WaveFileWriter writer;
static Stream memoryStream;
static WaveFormat _waveFormat;
static void Main(string[] args)
{
if (memoryStream == null)
memoryStream = new MemoryStream();
GetMicDevices();
StartMic();
}
/// <summary>
/// get all the devices that can record audio
/// </summary>
public static void GetMicDevices()
{
//get the capabilities of all the devices
for (int i = 0; i < WaveIn.DeviceCount; i++)
{
sources.Add(WaveIn.GetCapabilities(i));
}
foreach (var i in sources)
{
Devices.Add(i.ProductName);
Channels.Add(i.Channels.ToString());
}
}
public static void StartMic()
{
//set the device number
int DeviceNum = 0;
source = new WaveInEvent();
source.DataAvailable += Source_DataAvailable;
source.RecordingStopped += Source_RecordingStopped;
//set the device number
source.DeviceNumber = DeviceNum;
//create the waveFormat num of channels for the device
_waveFormat= new WaveFormat(44100, WaveIn.GetCapabilities(DeviceNum).Channels);
source.WaveFormat = _waveFormat;
writer = new WaveFileWriter(new IgnoreDisposeStream(memoryStream), _waveFormat);
//start the mic
Console.WriteLine("Start Rec");
source.StartRecording();
//record for 3 seconds
Thread.Sleep(3000);
//stop the mic
source.StopRecording();
Console.WriteLine("End Rec");
//play test
Console.WriteLine("Play test");
//play the sound from the byte array
IWaveProvider provider = new RawSourceWaveStream(
memoryStream, _waveFormat);
_waveOut = new WaveOut();
_waveOut.Init(provider);
_waveOut.Play();
Console.WriteLine("Press a key to exit");
Console.ReadKey();
}
private static void Source_RecordingStopped(object sender, StoppedEventArgs e)
{
source.Dispose();
source = null;
if (writer != null)
{
writer.Close();
writer = null;
}
}
private static void Source_DataAvailable(object sender, WaveInEventArgs e)
{ //convert the sound into a byte array
writer.Write(e.Buffer, 0, e.BytesRecorded);
}
}
}
Related
I am trying to record audio stream from a microphone to file (wav format).
By default, the file is recorded in stereo, the IEEE Float codec, but I need to record audio in PCM-format (16 kHz, Mono)
Where should this format be used in this program code?
(variable need_wave_format)
The project uses NuGet CSCore.
Link to this sample project:
https://github.com/LordKmon/CsCoreRecordProblem
Code from winform:
public partial class Form1 : Form
{
private WasapiCapture m_SoundKeeper;
private IWriteable m_Writer;
private IWaveSource m_FinalSource;
public Form1()
{
InitializeComponent();
}
private void btn_StartRecord_Click(object sender, EventArgs event_args)
{
//Find and set Device (microphone)
MMDevice selected_device = null;
using (var deviceEnumerator = new MMDeviceEnumerator())
using (var deviceCollection = deviceEnumerator.EnumAudioEndpoints(DataFlow.Capture, DeviceState.Active))
{
selected_device = deviceCollection[0];
}
// Format that I needed
WaveFormat need_wave_format = new WaveFormat(16000, 16, 1, AudioEncoding.Pcm);
// Start record
m_SoundKeeper = new WasapiCapture();
m_SoundKeeper.Device = selected_device;
m_SoundKeeper.Initialize();
var soundInSource = new SoundInSource(m_SoundKeeper);
var singleBlockNotificationStream = new SingleBlockNotificationStream(soundInSource.ToSampleSource());
m_FinalSource = singleBlockNotificationStream.ToWaveSource();
m_Writer = new WaveWriter("output.wav", m_FinalSource.WaveFormat);
byte[] buffer = new byte[m_FinalSource.WaveFormat.BytesPerSecond / 2];
soundInSource.DataAvailable += (s, e) =>
{
int read;
while ((read = m_FinalSource.Read(buffer, 0, buffer.Length)) > 0)
m_Writer.Write(buffer, 0, read);
};
l_Status.Text = "RECORD !!!";
m_SoundKeeper.Start();
}
private void btn_Stop_Click(object sender, EventArgs e)
{
if (m_SoundKeeper == null)
return;
m_SoundKeeper.Stop();
m_SoundKeeper.Dispose();
m_SoundKeeper = null;
m_FinalSource.Dispose();
if (m_Writer is IDisposable)
((IDisposable)m_Writer).Dispose();
l_Status.Text = "...";
}
}
}
Where do I should to use variable "need_wave_format" in this code so that the output is a file of the Wav-PCM format?
I need to stream my OS mixer sound to the microphone. (to transfer them both via skype).
Important thing is -- I need to have ability to configure delay/latency of the stream.
(VAC) Virtual Audio Cable is not solution for me: it doesn't work in my case. I have an external USB sound device an app doesn't work for me. I have tried it. Truly.
I google it more than 2 days and found nothing.
So I want to try wrote my own app for this. Have no experience with NAudio.
At the moment all I have is:
using System;
using System.Collections.Generic;
using NAudio.Wave;
namespace SoundApp
{
public class AudioCable
{
private WaveOut _wvOut = null;
private DirectSoundOut _output = null;
private WaveIn _sourceStreamIn = null;
private WaveOut _sourceStreamOut = null;
public void InitDevices(string fromDevice, string toDevice)
{
Dispose();
_sourceStreamIn = new WaveIn();
_sourceStreamOut = new WaveOut();
_output = new DirectSoundOut();
if (fromDevice.Contains("INPUT"))
{
var tmp = fromDevice.Split('|')[0].Replace("INPUT: ", "").Trim(' ');
int tmpDeviceNumber = int.Parse(tmp);
_sourceStreamIn.DeviceNumber = tmpDeviceNumber;
}
else
{
var tmp = toDevice.Split('|')[0].Replace("OUTPUT: ", "").Trim(' ');
int tmpDeviceNumber = int.Parse(tmp);
_sourceStreamOut.DeviceNumber = tmpDeviceNumber;
}
Guid deviceGuid;
if (toDevice.Contains("INPUT"))
{
var tmp = toDevice.Split('|')[0].Replace("INPUT: ", "").Trim(' ');
int tmpDeviceNumber = int.Parse(tmp);
WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(tmpDeviceNumber);
deviceGuid = deviceInfo.ManufacturerGuid;
}
else
{
var tmp = toDevice.Split('|')[0].Replace("OUTPUT: ", "").Trim(' ');
int tmpDeviceNumber = int.Parse(tmp);
WaveOutCapabilities deviceInfo = WaveOut.GetCapabilities(tmpDeviceNumber);
deviceGuid = deviceInfo.ManufacturerGuid;
}
_output = new DirectSoundOut(deviceGuid);
}
public void PlaySound()
{
WaveInProvider waveIn = null;
if (_sourceStreamIn != null)
{
waveIn = new WaveInProvider(_sourceStreamIn);
}
else if (_sourceStreamOut != null)
{
throw new Exception("Sorry, not supported right now");
//waveIn = new WaveInProvider(_sourceStreamOut);
}
_output.Init(waveIn);
_output.Play();
}
public void Dispose()
{
_sourceStreamIn = null;
_sourceStreamOut = null;
if (_output != null)
{
if (_output.PlaybackState == PlaybackState.Playing)
{
_output.Stop();
}
_output.Dispose();
_output = null;
}
}
public string[] GetAudioDevices()
{
var devices = new List<string>();
for (int i = 0; i < WaveIn.DeviceCount; i++)
{
WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(i);
devices.Add($"INPUT: {i} | {deviceInfo.ProductName}");
}
for (int i = 0; i < WaveOut.DeviceCount; i++)
{
WaveOutCapabilities deviceInfo = WaveOut.GetCapabilities(i);
devices.Add($"OUTPUT: {i} | {deviceInfo.ProductName}");
}
return devices.ToArray();
}
}
}
And the form source:
namespace SoundApp
{
public partial class Form1 : Form
{
AudioCable _ac = new AudioCable();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
cBoxSource.DropDownStyle = ComboBoxStyle.DropDownList;
cBoxTarget.DropDownStyle = ComboBoxStyle.DropDownList;
cBoxSource.Items.AddRange(_ac.GetAudioDevices());
cBoxTarget.Items.AddRange(_ac.GetAudioDevices());
}
private void btnStartStop_Click(object sender, EventArgs e)
{
_ac.InitDevices(cBoxSource.SelectedItem.ToString(), cBoxTarget.SelectedItem.ToString());
_ac.PlaySound();
}
}
}
So at the first I'm trying to stream microphone to the sound output device.... And it does not work at all.
So My questions is:
There are no microphone sound and I'm do not understand why so. Code is valid and dont throw any errors.
Looks like there is no ability to stream outputDevice sound stream to the inputDevice with NAudio. Is there exist some hack for this?
I have two Clients (Client-PC1 + Client-PC2) on my Network.
On each of that Clients I like to run a small c# Forms/Console Application and I like to communicate between that Applications.
I like to trigger the Application on Client-PC2 from Client-PC1. (in Code-Part: menuItem1_Click)
I already did some research and found this article on TechNet: How to: Use Named Pipes for Network Interprocess Communication
But I have one mistake or misunderstanding:
On the server side there is a specific number of threads that can be handled (at the moment: numThreads = 4)
So if I trigger from Client-PC1 more then 4 times then the Server side (Client-PC2) is closing the whole application...
How can I change this code to accept more than just 4 requests/triggers?
In total there are only 1-2 Computers that will connect to the server but sending multiple requests.
I think that I make something wrong on the client side after sending the request/trigger?
Any ideas?
Client Code:
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Pipes;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace NamedPipe_Client
{
class Program
{
private static int numClients = 4;
private static bool isConnected = false;
private System.Windows.Forms.NotifyIcon notifyIcon1;
private System.Windows.Forms.ContextMenu contextMenu1;
private System.Windows.Forms.MenuItem menuItem1;
private System.ComponentModel.IContainer components;
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void Main(string[] args)
{
Program pg = new Program();
//pg.CreateNotifyicon();
Application.Run();
Console.ReadLine();
}
Program()
{
CreateNotifyicon();
// hide application
System.IntPtr HWnd = FindWindow(null, Application.ExecutablePath);
if (HWnd != null)
{
bool result = ShowWindow(HWnd, 0);
}
}
private void CreateNotifyicon()
{
this.components = new System.ComponentModel.Container();
this.contextMenu1 = new System.Windows.Forms.ContextMenu();
this.menuItem1 = new System.Windows.Forms.MenuItem();
// Initialize menuItem1
this.menuItem1.Index = 0;
this.menuItem1.Text = "E&xit";
this.menuItem1.Click += new System.EventHandler(this.menuItem1_Click);
// Initialize contextMenu1
this.contextMenu1.MenuItems.AddRange(
new System.Windows.Forms.MenuItem[] { this.menuItem1 });
// Create the NotifyIcon.
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
// The Icon property sets the icon that will appear
// in the systray for this application.
notifyIcon1.Icon = new Icon("app_icon.ico");
// The ContextMenu property sets the menu that will
// appear when the systray icon is right clicked.
notifyIcon1.ContextMenu = this.contextMenu1;
// The Text property sets the text that will be displayed,
// in a tooltip, when the mouse hovers over the systray icon.
notifyIcon1.Text = "Console App (Console example)";
notifyIcon1.Visible = true;
// Handle the DoubleClick event to activate the form.
notifyIcon1.DoubleClick += new System.EventHandler(this.notifyIcon1_DoubleClick);
notifyIcon1.Click += new System.EventHandler(this.notifyIcon1_Click);
}
private void notifyIcon1_Click(object Sender, EventArgs e)
{
MessageBox.Show("clicked");
}
private void notifyIcon1_DoubleClick(object Sender, EventArgs e)
{
MessageBox.Show("Double clicked");
}
private void menuItem1_Click(object Sender, EventArgs e)//on menu click exit.
{
//Show application again
//System.IntPtr HWnd = FindWindow(null, Application.ExecutablePath);
//if (HWnd != null)
//{
// bool result = ShowWindow(HWnd, 1);
//}
NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", "testpipe",
PipeDirection.InOut, PipeOptions.None,
TokenImpersonationLevel.Impersonation);
Console.WriteLine("Connecting to server...\n");
pipeClient.Connect();
StreamString ss = new StreamString(pipeClient);
// Validate the server's signature string
if (ss.ReadString() == "I am the one true server!")
{
// The client security token is sent with the first write.
// Send the name of the file whose contents are returned
// by the server.
//ss.WriteString(#"C:\Test\textfile.txt");
ss.WriteString("Test");
// Print the file to the screen.
Console.Write(ss.ReadString());
}
else
{
Console.WriteLine("Server could not be verified.");
}
pipeClient.Close();
}
// Helper function to create pipe client processes
private static void StartClients()
{
int i;
string currentProcessName = Environment.CommandLine;
Process[] plist = new Process[numClients];
Console.WriteLine("Spawning client processes...\n");
if (currentProcessName.Contains(Environment.CurrentDirectory))
{
currentProcessName = currentProcessName.Replace(Environment.CurrentDirectory, String.Empty);
}
// Remove extra characters when launched from Visual Studio
currentProcessName = currentProcessName.Replace("\\", String.Empty);
currentProcessName = currentProcessName.Replace("\"", String.Empty);
for (i = 0; i < numClients; i++)
{
// Start 'this' program but spawn a named pipe client.
plist[i] = Process.Start(currentProcessName, "spawnclient");
}
while (i > 0)
{
for (int j = 0; j < numClients; j++)
{
if (plist[j] != null)
{
if (plist[j].HasExited)
{
Console.WriteLine("Client process[{0}] has exited.",
plist[j].Id);
plist[j] = null;
i--; // decrement the process watch count
}
else
{
Thread.Sleep(250);
}
}
}
}
Console.WriteLine("\nClient processes finished, exiting.");
}
}
// Defines the data protocol for reading and writing strings on our stream
public class StreamString
{
private Stream ioStream;
private UnicodeEncoding streamEncoding;
public StreamString(Stream ioStream)
{
this.ioStream = ioStream;
streamEncoding = new UnicodeEncoding();
}
public string ReadString()
{
int len;
len = ioStream.ReadByte() * 256;
len += ioStream.ReadByte();
byte[] inBuffer = new byte[len];
ioStream.Read(inBuffer, 0, len);
return streamEncoding.GetString(inBuffer);
}
public int WriteString(string outString)
{
byte[] outBuffer = streamEncoding.GetBytes(outString);
int len = outBuffer.Length;
if (len > UInt16.MaxValue)
{
len = (int)UInt16.MaxValue;
}
ioStream.WriteByte((byte)(len / 256));
ioStream.WriteByte((byte)(len & 255));
ioStream.Write(outBuffer, 0, len);
ioStream.Flush();
return outBuffer.Length + 2;
}
}
}
Server Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace NamedPipe_Server
{
class Program
{
private static int numThreads = 4;
static void Main(string[] args)
{
int i;
Thread[] servers = new Thread[numThreads];
Console.WriteLine("\n*** Named pipe server stream with impersonation example ***\n");
Console.WriteLine("Waiting for client connect...\n");
for (i = 0; i < numThreads; i++)
{
servers[i] = new Thread(ServerThread);
servers[i].Start();
}
Thread.Sleep(250);
while (i > 0)
{
for (int j = 0; j < numThreads; j++)
{
if (servers[j] != null)
{
if (servers[j].Join(250))
{
Console.WriteLine("Server thread[{0}] finished.", servers[j].ManagedThreadId);
servers[j] = null;
i--; // decrement the thread watch count
}
}
}
}
Console.WriteLine("\nServer threads exhausted, exiting.");
}
private static void ServerThread(object data)
{
NamedPipeServerStream pipeServer =
new NamedPipeServerStream("testpipe", PipeDirection.InOut, numThreads);
int threadId = Thread.CurrentThread.ManagedThreadId;
// Wait for a client to connect
pipeServer.WaitForConnection();
Console.WriteLine("Client connected on thread[{0}].", threadId);
try
{
// Read the request from the client. Once the client has
// written to the pipe its security token will be available.
StreamString ss = new StreamString(pipeServer);
// Verify our identity to the connected client using a
// string that the client anticipates.
ss.WriteString("I am the one true server!");
string filename = ss.ReadString();
if (filename.ToString() == "Test")
{
Console.WriteLine("yes");
ss.WriteString("Done");
}
// Read in the contents of the file while impersonating the client.
//ReadFileToStream fileReader = new ReadFileToStream(ss, filename);
// Display the name of the user we are impersonating.
//Console.WriteLine("Reading file: {0} on thread[{1}] as user: {2}.",
// filename, threadId, pipeServer.GetImpersonationUserName());
//pipeServer.RunAsClient(fileReader.Start);
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
pipeServer.Close();
}
}
// Defines the data protocol for reading and writing strings on our stream
public class StreamString
{
private Stream ioStream;
private UnicodeEncoding streamEncoding;
public StreamString(Stream ioStream)
{
this.ioStream = ioStream;
streamEncoding = new UnicodeEncoding();
}
public string ReadString()
{
int len = 0;
len = ioStream.ReadByte() * 256;
len += ioStream.ReadByte();
byte[] inBuffer = new byte[len];
ioStream.Read(inBuffer, 0, len);
return streamEncoding.GetString(inBuffer);
}
public int WriteString(string outString)
{
byte[] outBuffer = streamEncoding.GetBytes(outString);
int len = outBuffer.Length;
if (len > UInt16.MaxValue)
{
len = (int)UInt16.MaxValue;
}
ioStream.WriteByte((byte)(len / 256));
ioStream.WriteByte((byte)(len & 255));
ioStream.Write(outBuffer, 0, len);
ioStream.Flush();
return outBuffer.Length + 2;
}
}
// Contains the method executed in the context of the impersonated user
public class ReadFileToStream
{
private string fn;
private StreamString ss;
public ReadFileToStream(StreamString str, string filename)
{
fn = filename;
ss = str;
}
public void Start()
{
string contents = File.ReadAllText(fn);
ss.WriteString(contents);
}
}
}
I've been searching the internet and I haven't had any luck. I'm using an Xbox Kinect with the Kinect SDK v1.0. I want to take the raw depth data and convert it into a text document so I can use the depth data. I found something on this site but it was for the Beta2 and I need to use v1.0. Any help is appreciated but I am new to coding so sample code would be best.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
using System.Diagnostics;
using System.IO;
namespace DepthTextStream
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
const float MaxDepthDistance = 4095; // max value returned
const float MinDepthDistance = 850; // min value returned
const float MaxDepthDistanceOffset = MaxDepthDistance - MinDepthDistance;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
kinectSensorChooser1.KinectSensorChanged += new DependencyPropertyChangedEventHandler(kinectSensorChooser1_KinectSensorChanged);
}
void kinectSensorChooser1_KinectSensorChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var oldSensor = (KinectSensor)e.OldValue;
//stop the old sensor
if (oldSensor != null)
{
oldSensor.Stop();
oldSensor.AudioSource.Stop();
}
//get the new sensor
var newSensor = (KinectSensor)e.NewValue;
if (newSensor == null)
{
return;
}
//turn on features that you need
newSensor.DepthStream.Enable(DepthImageFormat.Resolution320x240Fps30);
newSensor.SkeletonStream.Enable();
//sign up for events if you want to get at API directly
newSensor.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(newSensor_AllFramesReady);
try
{
newSensor.Start();
}
catch (System.IO.IOException)
{
//this happens if another app is using the Kinect
kinectSensorChooser1.AppConflictOccurred();
}
}
void newSensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
short[] depthData;
using (DepthImageFrame depthFrame = e.OpenDepthImageFrame()) //create a new frame every time one is ready
{
//assign a value to depthData
depthData = new short[depthFrame.PixelDataLength];
}
}
private void SaveDepthData(short[] depthData)
{
//initialize a StreamWriter
StreamWriter sw = new StreamWriter(#"C:/Example.txt");
//search the depth data and add it to the file
for (int i = 0; i < depthData.Length; i++)
{
sw.WriteLine(depthData[i] + "\n"); //\n for a new line
}
//dispose of sw
sw.Close();
SaveDepthData(depthData);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
StopKinect(kinectSensorChooser1.Kinect);
}
private void StopKinect(KinectSensor sensor)
{
if (sensor != null)
{
if (sensor.IsRunning)
{
//stop sensor
sensor.Stop();
//stop audio if not null
if (sensor.AudioSource != null)
{
sensor.AudioSource.Stop();
}
}
}
}
}
}
This is pretty simple using version 1.5.0.1, which is practically the same as version 1.0 and will work on it. All you need to complete this is A)a short[] to hold the depth data B)a DepthImageFrame to move the data to the array, and C)A StreamWriter to save the data.
Add a short[] to store your depth data, and inside of your DepthFrameReadyEventArgs (or AllFramesReadyEventArgs) you "use" a DepthImageFrame by doing:
short[] depthData;
...
using (DepthImageFrame depthFrame = e.OpenDepthImageFrame(()) //create a new frame every time one is ready
{
//assign a value to depthData
depthData = new short[depthFrame.PixelDataLength];
}
Then you can add the depth from each frame to depthData using DepthImageFrame.CopyPixelDataTo
using (DepthImageFrame depthFrame = e.OpenDepthImageFrame(()) //create a new frame every time one is ready
{
//assign a value to depthData
depthData = new short[depthFrame.PixelDataLength];
//add raw depth data to depthData
depthFrame.CopyPixelDataTo(depthData);
}
Then we can write a method to save our data using a StreamWriter.
private void SaveDepthData(short[] depthData)
{
//initialize a StreamWriter
StreamWriter sw = new StreamWriter(#"C:/Example.txt");
//search the depth data and add it to the file
for (int i = 0; i < depthData.Length; i++)
{
sw.WriteLine(depthData[i] + "\n"); //\n for a new line
}
//dispose of sw
sw.Close();
}
...
SaveDepthData(depthData);
Hope this helps!
I have a WPF which executes a GUI for serial communication. I want to keep triggering the device and recoed the values till the user says stop. I have a global bool variable STOP which I set to false when user presses the stop which in turn should terminate the while loop which triggers the device continuously but the problem is that once the user selects the run button whcih runs the while loop, the WPF app freezes and doesn't accept the STOP button click.
Can someone give me an idea of what is happening here or a any suggestion on how to implement it differently.
Here is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.Ports;
using Keyence.data_class;
using Microsoft.Win32;
using System.IO;
using Keyence;
using System.Threading;
namespace Keyence
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public static string filePath;
public static string fileName;
public static int baudrate = 9600;
public static string thresHold = "60";
public bool STOP = true;
public static char[] buffer = new char[256];
public static string x, y, match;
public static string value;
public static SerialPort port = new SerialPort("COM4", baudrate, Parity.None, 8, StopBits.One);
public MainWindow()
{
InitializeComponent();
//port.DataReceived
//SerialPort port = new SerialPort(COM, baudrate, Parity.None, 8, StopBits.One);
port.Open();
port.NewLine = "\r";
//*******display camera types*****
string[] cameraTypes = new string[] { "CVseries100 ", "CVseries500" , "CVseries700" };
foreach (string cam in cameraTypes)
{
camera_type.Items.Add(cam);
}
//*******select your trigger mode( default is set to NONE)*******
string[] triggerModes = new string[] { "triggerModeNone", "triggerModeDATA", "triggerModeRepeat" };
foreach(string trigger in triggerModes)
{
trigger_mode.Items.Add(trigger);
}
//*****put a default value for thresHold********
threshold_value.Text = thresHold;
//*******add values to the baudrate dropdown********
baud_rate.Items.Add("9600");
baud_rate.Items.Add("19200");
baud_rate.Items.Add("38400");
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
public static void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
value = sp.ReadTo("\r");
string[] values = value.Split(new char[] { ',' });
x = values[0];
y = values[1];
match = values[2];
}
//public static void get_data()
//{
// port.Write("T");
//}
#region encapsulates all the individuals functions when the user changes settings ( UI interaction functions)
private void get_sample_Click(object sender, RoutedEventArgs e)
{
//write code to read x,y,threshold values in the text boxes
port.Write("T");
//MainWindow.get_data();
x_value.Text = string.Format("{0}", x);
y_value.Text = string.Format("{0}", y);
thresholdvalue.Text = string.Format("{0}", match);
}
#region the method opens a savefileDialog(dataFile) and lets user save the file in which data is stored
public void data_file_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog dataFile = new SaveFileDialog();
dataFile.DefaultExt = ".txt";
dataFile.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
dataFile.RestoreDirectory = true;
dataFile.Title = "select or create a new file";
DateTime currentTime = DateTime.Now;
dataFile.Filter = " Text Document |*.txt | Excel |*.xls";
string datepatt = #"M-d-yy_hh-mm_Data";
string saveDT = currentTime.ToString(datepatt);
dataFile.FileName = saveDT;
Nullable<bool> result = dataFile.ShowDialog();
if (result == true)
{
filePath = dataFile.FileName;
fileName = dataFile.SafeFileName;
}
System.IO.FileStream fs = (System.IO.FileStream)dataFile.OpenFile();
using (StreamWriter Write = new StreamWriter(fs))
{
Write.WriteLine("Wafer Placement Data\n\n");
Write.WriteLine("File Name : {0}\n", fileName);
Write.WriteLine("Port Name : COM4\n");
Write.WriteLine("Threshold : {0}\n", threshold_value.Text);
Write.WriteLine("Date : {0}\n\n", Convert.ToString(DateTime.Now));
//************Print Header to the file******************
Write.WriteLine("\tX\tY\tcorrelation\tDate\n");
}
}
#endregion
#region function called when the threshold value is changed
private void threshold_value_TextChanged(object sender, TextChangedEventArgs e)
{
thresHold = threshold_value.Text;
}
#endregion
#region function to write individual data points on the window for checking
private void writeSample(double X, double Y, double threshold)
{
FileStream file = new FileStream(filePath, FileMode.Append, FileAccess.ReadWrite);
using (StreamWriter Writer = new StreamWriter(file))
{
Writer.WriteLine(DateTime.Now);
Writer.WriteLine("\t X \t Y\t threshold% ");
}
}
#endregion
private void run_button_Click(object sender, RoutedEventArgs e)
{
do
{
port.Write("T");
FileStream file = new FileStream(filePath, FileMode.Append, FileAccess.Write);
Thread.Sleep(500);
using (StreamWriter Writer = new StreamWriter(file))
{
Writer.WriteLine("\t{0}\t{1}\t{2}\t{3}", x, y, match, Convert.ToString(DateTime.Now));
}
port.DiscardInBuffer();
} while (STOP);
}
private void stop_button_Click(object sender, RoutedEventArgs e)
{
STOP = false;
}
private void command_TextChanged(object sender, TextChangedEventArgs e)
{
string C = command.Text;
port.WriteLine(C);
}
#endregion
}
}
You need to run your serial port code in separate thread. In your implementation GUI thread is busy w/ serial port communication that is why your window is frozen. The following article explains exactly what you need:
http://www.ryanvice.net/wpf-3-5/using-backgroundworker-with-wpf/