I'm trying to control a Ximea camera (http://www.ximea.com) via a C# application.
I used an example that the company ships with the camera. Everytime I want to connect to the camera (using the OpenDevice function), I get an error that says - 'invalid handle'. What does this mean and what can I do to fix that?
Here is the code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Drawing;
using xiApi.NET;
namespace xiApi.NET_example
{
class Program
{
static void Main(string[] args){
{
xiCam myCam = new xiCam();
try
{
// Initialize first camera
myCam.OpenDevice(0);
// Set device exposure to 2 milliseconds
int exposure_us = 2000;
myCam.SetParam(PRM.EXPOSURE, exposure_us);
// Set device gain to 5 decibels
float gain_db = 5;
myCam.SetParam(PRM.GAIN, gain_db);
// Set image output format to monochrome 8 bit
myCam.SetParam(PRM.IMAGE_DATA_FORMAT, IMG_FORMAT.MONO8);
//Start acquisition
myCam.StartAcquisition();
// Capture images
Bitmap myImage;
int timeout = 1000;
for (int i = 0; i < 10; i++)
{
myCam.GetImage(out myImage, timeout );
string fName = string.Format("image{0}.bmp", i);
myImage.Save(fName);
}
// Stop acquisition
myCam.StopAcquisition();
}
catch (System.ApplicationException appExc)
{
// Show handled error
Console.WriteLine(appExc.Message);
System.Console.ReadLine();
myCam.CloseDevice();
}
finally
{
myCam.CloseDevice();
}
Related
I have 6 audio sources which I need to play on 6 separate channels using ASIO.
I managed to get this working using WaveOutEvent as the output, but when I switch to AsioOut I get a null reference error, and I can't figure out what I'm doing wrong.
I need to use ASIO since I require 6 output channels and because I have to broadcast the audio over the network using Dante protocol.
The output device is a Dante Virtual Soundcard.
The error is:
NullReferenceException: Object reference not set to an instance of an object
NAudio.Wave.AsioOut.driver_BufferUpdate (System.IntPtr[] inputChannels, System.IntPtr[] outputChannels) (at <7b1c1a8badc0497bac142a81b5ef5bcf>:0)
NAudio.Wave.Asio.AsioDriverExt.BufferSwitchCallBack (System.Int32 doubleBufferIndex, System.Boolean directProcess) (at <7b1c1a8badc0497bac142a81b5ef5bcf>:0)
UnityEngine.<>c:<RegisterUECatcher>b__0_0(Object, UnhandledExceptionEventArgs)
This is the (simplified) code that plays the audio. The buffers are filled by other methods in external classes.
using NAudio.Wave;
using System;
using System.Collections.Generic;
public class AudioMultiplexer
{
MultiplexingWaveProvider multiplexer;
AsioOut asioOut;
public List<BufferedWaveProvider> buffers;
public int outputChannels = 6;
public int waveFormatSampleRate = 48000;
public int waveFormatBitDepth = 24;
public int waveFormatChannels = 2;
public void Start()
{
buffers = new List<BufferedWaveProvider>();
var outputFormat = new WaveFormat(waveFormatSampleRate, waveFormatBitDepth, waveFormatChannels);
for (int i = 0; i < outputChannels; i++)
{
var buffer = new BufferedWaveProvider(outputFormat);
buffer.DiscardOnBufferOverflow = true;
// Make sure the buffers are big enough, just in case
buffer.BufferDuration = TimeSpan.FromMinutes(5);
buffers.Add(buffer);
}
multiplexer = new MultiplexingWaveProvider(buffers, outputChannels);
for (int i = 0; i < outputChannels; i++)
{
// Each input has 2 channels, left & right, take only one channel from each input source
multiplexer.ConnectInputToOutput(i * 2, i);
}
var driverName = GetDanteDriverName();
if (string.IsNullOrEmpty(driverName))
{
return;
}
asioOut = new AsioOut(driverName);
asioOut.AudioAvailable += AsioOut_AudioAvailable;
asioOut.Init(multiplexer);
asioOut.Play();
}
private void AsioOut_AudioAvailable(object sender, AsioAudioAvailableEventArgs e)
{
// Do nothing for now
Console.WriteLine("Audio available");
}
private string GetDanteDriverName()
{
foreach (var driverName in AsioOut.GetDriverNames())
{
if (driverName.Contains("Dante Virtual Soundcard"))
{
return driverName;
}
}
return null;
}
private void OnDestroy()
{
asioOut.Stop();
asioOut.Dispose();
asioOut = null;
}
}
I may have a misunderstanding of how AsioOut works but I'm not sure where to start on this or how to debug the error.
You can use the Low-latency Multichannel Audio asset for unity to play multi-channel audio with asio. It's made especially for unity, unlike naudio, and it works without problems!
I have created a program in C# for my children to test them on reading music. It displays random notes at set intervals (determined by a timer) and then checks the currently displayed note against input from the keyboard to see if they got it right. It is working well, apart from the fact that if two notes are accidentally pressed at once, the second of them is taken to be the intended answer for the subsequent note, which hasn't even been displayed yet! I assume that the notes that are played on the musical keyboard are stored in a buffer and then used when next needed. I would like to be able to "wipe the slate clean" when a new note is displayed on the screen, so that any previous input is disregarded. I'd be grateful for any thoughts as to how I can do this please.
Some of the code is below:
using System;
using Midi;
using System.Media;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication6
{
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
// Create persistent delegates which we can add and remove to events.
noteOnHandler = new InputDevice.NoteOnHandler(this.NoteOn);
noteOffHandler = new InputDevice.NoteOffHandler(this.NoteOff);
InputDevice preferredInputDevice = InputDevice.InstalledDevices[0];
UseInputDevice(InputDevice.InstalledDevices[0]);
}
private void UseInputDevice(InputDevice newInputDevice)
{
if (newInputDevice == inputDevice)
{
return;
}
if (inputDevice != null)
{
if (inputDevice.IsOpen)
{
if (inputDevice.IsReceiving)
{
inputDevice.StopReceiving();
}
inputDevice.Close();
}
inputDevice.NoteOn -= noteOnHandler;
inputDevice.NoteOff -= noteOffHandler;
}
inputDevice = newInputDevice;
inputDevice.NoteOn += noteOnHandler;
inputDevice.NoteOff += noteOffHandler;
inputDevice.Open();
inputDevice.StartReceiving(null);
}
// Method called when the input device receives a NoteOn message. Updates
// the input status label. Respects GUI thread affinity by invoking to the
// GUI thread if necessary.
public void NoteOn(NoteOnMessage msg)
{
if (button1.Text == "STOP")
{
if (InvokeRequired)
{
BeginInvoke(noteOnHandler, msg);
return;
}
if (string.Equals(String.Format("{0}", msg.Pitch), notename)) { currentscore++; correct[numberofnotes] = true; using (SoundPlayer player = new SoundPlayer("chime_up.wav")) { player.PlaySync(); } }
else { using (SoundPlayer player = new SoundPlayer("klaxon_ahooga.wav")) { player.PlaySync(); } correct[numberofnotes] = false; }
outof++;
score.Text = String.Format("{0}", currentscore);
notesshown.Text = String.Format("{0}", outof);
numberofticks = 0;
if (outof < 20) { generate_note(); }
Redrawit();
Invalidate();
if (outof == 20) { reset_screen(); }
}
}
// Method called when the input device receives a NoteOff message. Updates
// the input status label. Respects GUI thread affinity by invoking to the
// GUI thread if necessary.
public void NoteOff(NoteOffMessage msg)
{
if (InvokeRequired)
{
BeginInvoke(noteOffHandler, msg);
return;
}
}
// Persistent delegate objects for the note handlers.
private InputDevice.NoteOnHandler noteOnHandler;
private InputDevice.NoteOffHandler noteOffHandler;
}
}
I have been breaking my head over this for a long time now and I can't seem to find how to solve this. Simply put I need to present Parallel programming to my class and i am making a demo that clearly shows the diffrence between single threaded and multi threaded.
First the program takes a screenshot and loads that in this class into a bitmap.
Then it loads the winform with a picturebox called screenshot. Next it does Form1_Load and loads the screenshot into the picturebox.
Then Form1_Shown Runs the for loop which just scrambles the pixels around based on a randomizer and updates the image from the left to the right.
example: http://gyazo.com/ab04583bb33de59d08407886da1c4870
This all works.
I now want to make it so that the screenshot is being updated from the left to the middle by the first thread, and from the middle to the right with the second thread.
But when i put it in 2 separate threads it says "An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll"
The error implies I am making illegal cross thread calls. Particulary on screenshot and probably also on mybitmap.
Visual studio helps me by linking me to "How to: Make Thread-Safe Calls to Windows Forms Controls"
But i am not getting any wiser out of this information which is probably because i am not that fluent with the C# terminology yet.
How should i approach/fix this ?
This is the class where everything happens (except taking the screenshot):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ScreenOutput
{
public partial class Form1 : Form
{
PictureBox screenshot;
Bitmap myBitmap = new Bitmap(#".\screenshot.jpg");
public Form1()
{
InitializeComponent();
}
private int Xcount;
private int Ycount;
private int maxXValue = Screen.PrimaryScreen.Bounds.Width - 1;
private int maxXValueT1 = 960;
private int maxXValueT2 = 1919;
private int maxYValue = Screen.PrimaryScreen.Bounds.Height - 1;
private int maxYValueT1 = 539;
private int maxYValueT2 = 1079;
private void Form1_Load(object sender, EventArgs e)
{
screenshot.Image = myBitmap;
}
private void Form1_Shown(object sender, EventArgs e)
{
Thread startThread1 = new Thread(new ThreadStart(thread1));
Thread startThread2 = new Thread(new ThreadStart(thread2));
startThread1.Start();
startThread2.Start();
Thread.Sleep(10000); //waiting for completion
startThread1.Abort();
startThread2.Abort();
//this is how it would work without multithreading
/*Random random = new Random();
for (Xcount = 0; Xcount < maxXValue; Xcount++)
{
screenshot.Refresh();
for (Ycount = 0; Ycount < maxYValue; Ycount++)
{
int calculatedX = Xcount + random.Next(0, maxXValue);
if (calculatedX > maxXValue) calculatedX = maxXValue;
myBitmap.SetPixel(Xcount, Ycount, myBitmap.GetPixel(calculatedX, Ycount));
}
}
Thread.Sleep(2000);*/
Application.Exit();
}
public void thread1()
{
Random random = new Random();
for (Xcount = 0; Xcount < maxXValueT1; Xcount++)
{
screenshot.Refresh();
for (Ycount = 0; Ycount < maxYValueT1; Ycount++)
{
int calculatedX = Xcount + random.Next(0, maxXValueT1);
if (calculatedX > maxXValue) calculatedX = maxXValueT1;
myBitmap.SetPixel(Xcount, Ycount, myBitmap.GetPixel(calculatedX, Ycount));
}
}
}
public void thread2()
{
Random random = new Random();
for (Xcount = 0; Xcount < maxXValueT2; Xcount++)
{
screenshot.Refresh();
for (Ycount = 0; Ycount < maxYValueT2; Ycount++)
{
int calculatedX = Xcount + random.Next(0, maxXValueT2);
if (calculatedX > maxXValueT2) calculatedX = maxXValueT2;
myBitmap.SetPixel(Xcount, Ycount, myBitmap.GetPixel(calculatedX, Ycount));
}
}
}
}
}
You will need to Invoke the GUI thread.
I prefer the following solution.
Using a Form member ('screenshot' in this case) check to see if InvokeRequired = true. If so then Invoke a delegate using that members BeginInvoke() function as the following example demonstrates:
private void ScreenshotRefresh()
{
if(screenshot.InvokeRequired)
{
screenshot.BeginInvoke(new MethodInvoker(this.ScreenshotRefresh));
}
else
{
screenshot.Refresh();
}
}
I'm new to C# programming and trying to write an application which is part of my final thesis.
I have a microprocessor that continuously send data from a sensor to my computer via serial port. All I want is to plotting this data using Zedgraph.
The problem is that the graph got too much delay and time lag. It seems the problem happens because I continuously update the whole graph at a very high rate.
I have stucked on this problem in a week and still dont find out a solution. I'll be more than happy if someone can help me out.
This is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ZedGraph;
using System.IO.Ports;
using System.Threading;
namespace DynamicData
{
public partial class Form1 : Form
{
private SerialPort port;
private string buffer = "";
private void connect()
{
port = new SerialPort("COM8", 115200, Parity.None, 8, StopBits.One);
port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived);
if (!port.IsOpen) port.Open();
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load( object sender, EventArgs e )
{
connect();
GraphPane myPane = zedGraphControl1.GraphPane;
RollingPointPairList list = new RollingPointPairList(500);
LineItem curve = myPane.AddCurve( "Sensor", list, Color.Blue, SymbolType.None );
myPane.XAxis.Scale.Min = 0;
myPane.XAxis.Scale.Max = 10;
myPane.YAxis.Scale.Min = 0;
myPane.YAxis.Scale.Max = 300;
myPane.XAxis.Scale.MinorStep = 0.5;
myPane.XAxis.Scale.MajorStep = 1;
zedGraphControl1.AxisChange();
}
private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
//sample data: ;100*100000:
//sampling rate ~100Hz
buffer += port.ReadExisting();
//flush incomplete package
while (buffer[0] != ';')
{
buffer = buffer.Remove(0, 1);
if (buffer.Length < 1) break;
}
//got a complete package, go to data handling
while (buffer.Contains(":"))
{
DataHandling();
}
}
private void DataHandling()
{
string[] nameArray = buffer.Split(new[] { ";", ":", "*" }, StringSplitOptions.RemoveEmptyEntries);
//plot sensor data vs. time
draw(Convert.ToInt32(nameArray[0]), Convert.ToInt32(nameArray[1]));
//remove handled package in buffer
var index = buffer.IndexOf(":");
buffer = buffer.Remove(0, index + 1);
}
double time = 0;
private void draw(int sensor, int t)
{
//convert tick to sec (uP clock rate = 16MHZ)
time = time + (t / 16000000.0);
// Get the first CurveItem in the graph
LineItem curve = zedGraphControl1.GraphPane.CurveList[0] as LineItem;
// Get the PointPairList
IPointListEdit list = curve.Points as IPointListEdit;
list.Add(time, sensor);
//Keep the X scale at a rolling 10 second interval, with one
//major step between the max X value and the end of the axis
Scale xScale = zedGraphControl1.GraphPane.XAxis.Scale;
if (time > xScale.Max - xScale.MajorStep)
{
xScale.Max = time + xScale.MajorStep;
xScale.Min = xScale.Max - 10.0;
}
//Display sensor data
this.Invoke(new Action(() => { textBox1.Text = byte1.ToString(); }));
axisChangeZedGraph(zedGraphControl1);
}
delegate void axisChangeZedGraphCallBack(ZedGraphControl zg);
private void axisChangeZedGraph(ZedGraphControl zg)
{
if (zg.InvokeRequired)
{
axisChangeZedGraphCallBack ad = new axisChangeZedGraphCallBack(axisChangeZedGraph);
zg.Invoke(ad, new object[] { zg });
}
else
{
// zg.AxisChange();
zg.Invalidate();
zg.Refresh();
}
}
}
}
Thank you for reading!
The problem is that you call invalidate with every point you draw. That produces a very high processor load. I'm working on a very similar project, USB device, realtime plotting data. I use a separate thread for data acquisition. This thread creates an event, every time it receives a datapacket. The data is put into a queue. The graph is updated with a timer. You find an example here. In this code the graph is updated every 50 ms, it is not really necessary to draw faster. In the timertick I check the size of the Queue and draw more or less points and then call invalidate. I don`t know if this is a good solution(just 6month experience in C#), but it works quite well with 7500 points. You should try to use a timer for the refresh of the graph first.
1). Create and format the the curve only once. store it at the module level.
2). When adding a point use curve.AddPoint(); then zg.Refresh();
//this is just to add a point to the plot, the curve object should have already been created
private void draw(int sensor, int t)
{
//convert tick to sec (uP clock rate = 16MHZ)
time = time + (t / 16000000.0);
//curve should be a module-level variable already set up with proper formatting,
//just no points yet
curve.AddPoint(time, sensor);
//Display sensor data
this.Invoke(new Action(() => { textBox1.Text = byte1.ToString(); }));
zg.AxisChange();
zg.Refresh();
}
I have this class that im getting the information from the animated gif:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.IO;
public class AnimatedGif
{
private List<AnimatedGifFrame> mImages = new List<AnimatedGifFrame>();
public AnimatedGif(string path)
{
Image img = Image.FromFile(path);
int frames = img.GetFrameCount(FrameDimension.Time);
if (frames <= 1) throw new ArgumentException("Image not animated");
byte[] times = img.GetPropertyItem(0x5100).Value;
int frame = 0;
for (; ; )
{
int dur = BitConverter.ToInt32(times, 4 * frame);
mImages.Add(new AnimatedGifFrame(new Bitmap(img), dur));
if (++frame >= frames) break;
img.SelectActiveFrame(FrameDimension.Time, frame);
}
img.Dispose();
}
public List<AnimatedGifFrame> Images { get { return mImages; } }
}
public class AnimatedGifFrame
{
private int mDuration;
private Image mImage;
internal AnimatedGifFrame(Image img, int duration)
{
mImage = img; mDuration = duration;
}
public Image Image { get { return mImage; } }
public int Duration { get { return mDuration; } }
}
Then in Form1 in the constructor im looping over the List of images and get the duration of each of the images. So in the List in this case there are 4 images each one duration is 1.
So when im showing the animatd gif im trying to display the speed in a label.
But there are two problems:
The loop in the end show me that speed is now 2 not 4.
The label the result there is all the time 0 and 2/100 is not 0.
What i want to do is to show the actual speed.
Like in the program Easy gif animator 5:
If im standing on one image from the 4 i see that its speed is 0.01seconds wich is Delay 1 wich is 1/100th sec.
And if i mark all the images in the program i get speed 0.04 seconds.
Maybe i confusing between speed and duration.
I want to get the speed of the animated gif.
This is my code in Form1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MyAnimatedGifEditor
{
public partial class Form1 : Form
{
int speed;
Image myImage;
AnimatedGif myGif;
public Form1()
{
InitializeComponent();
myImage = Image.FromFile(#"D:\fananimation.gif");
myGif = new AnimatedGif(#"D:\fananimation.gif");
for (int i = 0; i < myGif.Images.Count; i++)
{
speed = myGif.Images[i].Duration;
speed++;
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
pictureBox1.Image = myImage;
label2.Text = (speed / 100).ToString();
}
}
}
Image from the easy gif animator after selected all images:
In the end i want to show on two labels one the duration of the animated gif and one the speed.
There is a problem with the portion of your code where you are looping through the images of the animated gif. You probably want two separate variables here instead of just speed.
So something like
for (int i = 0; i < myGif.Images.Count; i++)
{
totalDuration += myGif.Images[i].Duration;
count++;
}
And to solve your integer math problem, divide by 100.0 instead of 100:
label2.Text = (totalDuration / 100.0).ToString();