UI not updating sounds played first in foreach loop C# WPF - c#

I have made a card game that gets and shows player cards from resources in a UI using a foreach loop which works fine. I have recently added a card sound as well so that a sound would be played before each image is shown in the UI. However, the sounds are always played first and then the images are shown. A bit annoying...
I use sound player and playsync(). How do I force the GUI to update? (between the sounds)
Here is some of the code...
Starts with
//loop
foreach (var player in playerGUIs)....
//Call the sound Card_Sound(); //See below
//Update image player.img1.Source = new BitmapImage(new
Uri(("/Utilities;Component/Resources/" + card_file + ".png"),
UriKind.Relative));
private void Card_Sound()
{ //Play sound System.Threading.Thread.Sleep(800); // First sleep 800 milliseconds
using (FileStream stream = File.Open(#"Resources\dealingcard.wav",
FileMode.Open)) {
SoundPlayer myNewSound = new SoundPlayer(stream);
myNewSound.Load();
myNewSound.PlaySync(); }
}

PlaySync() will block the UI (if running on the UI thread) did you try Play()?

Related

c# - how to remove the interval between two timer ticks

I am using timer to connect several audio files together. There are a list of audio files and the timer will read files one by one. Once there is an audio read, it will be played. The goal is to play the audio file right after the previous one when it is finished(without any break).
(I am using Naudio)
Here is the code:
private void timer_key_Tick(object sender, EventArgs e)
{
if(!isPlaying)
{
//play the current audio
DirectSoundOut dso = sounds2[key_indexer];
dso.Play();
targetMusics.Add(dso);
}
else
{
foreach (DirectSoundOut dso in targetMusics)
{//stop the current audio
dso.Stop();
}
targetMusics.Clear();
key_indexer++; //switch to the next audio
if (key_indexer >= myMT.Keys.Count)
{
key_indexer = 0;
timer_key.Stop();
}
}
isPlaying = !isPlaying;
}
However, the fact is, when the first music finished, the second one didn't play at once. It comes after one second break. Is this the problem about timer itself? How should I change it?
Thanks for the help from #HansPassant. I made a mistake about logic in this timer. Here is the correct code after I applied his suggestion:
//stop the current playing
foreach(DirectSoundOut d in targetMusics)
{
d.Stop();
}
targetMusics.Clear();
//stop the entire process
if (key_indexer >= myMT.Keys.Count)
{
key_indexer = 0;
timer_key.Stop();
}
else
{ //play the current audio
DirectSoundOut dso = sounds2[key_indexer];
targetMusics.Add(dso);
dso.Play();
key_indexer++;
}

reduce CPU overhead while proccessing Video Stream

I am developing C# WPF Auto Number Plate Recognition Using an OCR.
The Flow is, i am getting a pictures from a video stream MJPEG and this images should be passed to the OCR to get the plate number and other details.
The problem is : the Video stream is producing about 30 Frame/second and the CPU can't handle this much of processing also it will take around 1 Sec to process 1 frame, Also when i will get many frames on the Queue the CPU will be 70% used (Intel I7 4th G).
Can anyone suggest solution and better implementation.
//This is the queue where it will hold the frames
// produced from the video streaming(video_Newfram1)
private readonly Queue<byte[]> _anpr1Produces = new Queue<byte[]>();
//I am using AForg.Video to read the MJPEG Streaming
//this event will be triggered for every frame
private void video_NewFrame1(object sender, NewFrameEventArgs eventArgs)
{
var frameDataAnpr = new Bitmap(eventArgs.Frame);
AnprCam1.Source = GetBitmapimage(frameDataAnpr);
//add current fram to the queue
_anpr1Produces.Enqueue(imgByteAnpr);
//this worker is the consumer that will
//take the frames from the queue to the OCR processing
if (!_workerAnpr1.IsBusy)
{
_workerAnpr1.RunWorkerAsync(imgByteAnpr);
}
}
//This is the consumer, it will take the frames from the queue to the OCR
private void WorkerAnpr1_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
if (_anpr1Produces.Count <= 0) continue;
BgWorker1(_anpr1Produces.Dequeue());
}
}
//This method will process the frames that sent from the consumer
private void BgWorker1(byte[] imageByteAnpr)
{
var anpr = new cmAnpr("default");
var objgxImage = new gxImage("default");
if (imageByteAnpr != null)
{
objgxImage.LoadFromMem(imageByteAnpr, 1);
if (anpr.FindFirst(objgxImage) && anpr.GetConfidence() >= Configs.ConfidanceLevel)
{
var vehicleNumber = anpr.GetText();
var vehicleType = anpr.GetType().ToString();
if (vehicleType == "0") return;
var imagename = string.Format("{0:yyyy_MMM_dd_HHmmssfff}", currentDateTime) + "-1-" +
vehicleNumber + ".png";
//this task will run async to do the rest of the process which is saving the vehicle image, getting vehicle color, storing to the database ... etc
var tsk = ProcessVehicle("1", vehicleType, vehicleNumber, imageByteAnpr, imagename, currentDateTime, anpr, _anpr1Produces);
}
else
{
GC.Collect();
}
}
}
What you should do is this:
First, figure out if a frame is worth processing or not. If you're using a compressed video stream, you can usually quickly read the frame's compressed size. It stores the difference between the current frame and the previous one.
When it's small, not much changed (i.e: no car drove by).
That's a low-tech way to do motion detection, without even having to decode a frame, and it should be extremely fast.
That way, you can probably decide to skip 80% of the frames in a couple of milliseconds.
Once and a while you'll get frames that need processing. Make sure that you can buffer enough frames so that you can keep recording while you're doing your slow processing.
The next thing to do is find a region of interest, and focus on those first. You could do that by simply looking at areas where the color changed, or try to find rectangular shapes.
Finally, one second of processing is SLOW if you need to process 30 fps. You need to make things faster, or you'll have to build up a gigantic buffer, and hope that you'll ever catch up if it's busy on the road.
Make sure to make proper use of multiple cores if they are available, but in the end, knowing which pieces of the image are NOT relevant is the key to faster performance here.

How to close Window Media Player after it is finish playing?

I want to know how to close the media player when it finishes playing my wav file. Because if I run this multiple times, it consumes an dangerous amount of computer ram. If you can solve that without closing it, by all means tell me.
var player = new WMPLib.WindowsMediaPlayer();
player.URL = #"D:\notes\01.wav";
This is the code to play it.
There isn't a way to exit the player, the only(not so ideal approach) is to kill it.
var proc = Process.GetProcessesByName("wmplayer");
if (proc.Length > 0) {
proc[proc.Length - 1].Kill();
}
This might do the trick for you
var player = new WMPLib.WindowsMediaPlayer();
player.URL = #"D:\notes\01.wav";
Thread.Sleep(2000);
player.controls.stop();
player.close();
Edit
Than you can kill the process and stop the WMPlayer
var prc = Process.GetProcessesByName("wmplayer");
if (prc.Length > 0) prc[prc.Length - 1].Kill();

how to detect front and back camera in window tablet in winforms C#

I'm using aforge in winforms for video recording. I wanna to record video both (front and back camera) in window tablet. I have able to find list of Video Capture Device but not identify which is front or rear camera.
Name space whose I use:
using AForge.Video;
using AForge.Video.DirectShow;
I have sawed you my finding video capture device snippet of code:
public VideoCaptureDevice cam = null;
public FilterInfoCollection usbCams;
...
usbCams = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (usbCams.Count == 1)
{
cam = new VideoCaptureDevice(usbCams[0].MonikerString);
}
else if (usbCams.Count == 2)
{
cam = new VideoCaptureDevice(usbCams[1].MonikerString);
}
cam.NewFrame += new NewFrameEventHandler(cam_NewFrame);
cam.Start();
...
private void cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap bitmap = (Bitmap)eventArgs.Frame.Clone();
ImgContainer.Image = bitmap;
}
I have tested in different devices like iball and lenovo yoga 8. I have found one reason is that in Iball tablet return first front camera name and second rear camera but in lenovo tablet return first rear camera and second front camera. I have total confused. How to identify front and rear camera?
usbCams is a list with all the available camera devices in your machine.
With this:
if (usbCams.Count == 1)
{
cam = new VideoCaptureDevice(usbCams[0].MonikerString);
}
else if (usbCams.Count == 2)
{
cam = new VideoCaptureDevice(usbCams[1].MonikerString);
}
What you are doing is, if there is only one device use the first one, and if there are two devices use the second one, but it's not sure that the second one will be the rear or the front.
What I've done in my app is use a selector and fill it with all the available devices, and let the user choose.
Something like:
List<string> camaras = new List<string>();
foreach (FilterInfo item in usbCams)
{
camaras.Add(item.Name);
}
comboBox.ItemsSource = camaras;
And when the combobox change the selection
cam.Stop();
cam= new VideoCaptureDevice(LoaclWebCamsCollection[comboBox.SelectedIndex].MonikerString);
cam.NewFrame += new NewFrameEventHandler(cam_NewFrame);
cam.Start();
I don't have enough devices now to test the order of the cams, but it can be that ther are ordered by name device, or by driver installation priority or whatever.
A hack is to check the capabilities and set the camera with the highest resolution as back camera. If there is a difference in quality than the back camera is usually the better one.
This won't work always, for example the Surface Pro 1 has 2 cameras with the same resolution.

Why is my background music not looping?

Dose anyone have any idae why this code is not working for my background music to constantly loop??
In load Content:
backgroundMusic.Play(0.3f, 0.0f, 0.0f); //play background music (first float number is for volume)
In update:
SoundEffectInstance instance = backgroundMusic.CreateInstance(); //creates instance for backgroundMusic
instance.IsLooped = true; //states that instance should loop meaning background music loops and never stops
Thanks in advance
Edit: I now have this:
Content Load:
Song backgroundMusic = Content.Load<Song>("backgroundMusic");
and then seperately:
public void PlayMusicRepeat(Song backgroundMusic)
{
MediaPlayer.Play(backgroundMusic);
MediaPlayer.IsRepeating = true;
}
If you need to manage the backgroud music you should use the Song class, SoundEffect should be used only for sound effects.
Something like this:
public void PlayMusicRepeat(Song song)
{
MediaPlayer.Play(song);
MediaPlayer.IsRepeating = true;
}
Of course the loading should be like this:
Song music = Game.Content.Load<Song>("background");
You are playing the SoundEffect, but looping the SoundEffectInstance, that won't work.
And following this article from Microsoft (http://msdn.microsoft.com/en-us/library/dd940203.aspx), you have to set the IsLooped property BEFORE playing the sound.
So your code should look like this:
In LoadContent:
instance = backgroundMusic.CreateInstance();
instance.IsLooped = true;
In Update:
if(instance.State == SoundState.Stopped)
instance.Play();

Categories