I am writing a UWP application.It's like a simple custom camera with Taking PHOTO Button. It includes an XAML view having captureElement, and page behind the code.
The issue is that Camera opens on 50% of the screen on devices: Lumia 950 and Lumia 950XL as if the Grid containing captureElement is divided into two columns but on other devices, it perfect.
I took help of:
Microsoft UWP Samples: Camera Sample
namespace InfoMedia.Views.Posting
{
public sealed partial class PostingCameraView : BasePage
{
private readonly DisplayInformation _displayInformation = DisplayInformation.GetForCurrentView();
private readonly SimpleOrientationSensor _orientationSensor = SimpleOrientationSensor.GetDefault();
private SimpleOrientation _deviceOrientation = SimpleOrientation.NotRotated;
private DisplayOrientations _displayOrientation = DisplayOrientations.Portrait;
private static readonly Guid RotationKey = new Guid("C380465D-2271-428C-9B83-ECEA3B4A85C1");
private StorageFolder _captureFolder = null;
private readonly DisplayRequest _displayRequest = new DisplayRequest();
private readonly SystemMediaTransportControls _systemMediaControls = SystemMediaTransportControls.GetForCurrentView();
// MediaCapture and its state variables
private MediaCapture _mediaCapture;
private bool _isInitialized;
private bool _isPreviewing;
private bool _mirroringPreview;
private bool _externalCamera;
private bool _isRecording;
private PostingAdViewModel postingAdViewModel;
#region Constructor, lifecycle, and navigation
public PostingCameraView()
{
this.InitializeComponent();
if (ApplicationHelper.GetInstance().DetectDeviceFamily() == CommonServices.Enums.DeviceType.Phone)
{
NavigationCacheMode = NavigationCacheMode.Disabled;
this.Loaded += PostingCameraView_Loaded;
}
}
private async void PostingCameraView_Loaded(object sender, RoutedEventArgs e)
{
postingAdViewModel.IsCameraInitializing = true;
await SetupUiAsync();
await InitializeCameraAsync();
postingAdViewModel.IsCameraInitializing = false;
}
#region Event handlers
private async void SystemMediaControls_PropertyChanged(SystemMediaTransportControls sender, SystemMediaTransportControlsPropertyChangedEventArgs args)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
// Only handle this event if this page is currently being displayed
if (args.Property == SystemMediaTransportControlsProperty.SoundLevel && Frame.CurrentSourcePageType == typeof(MainPage))
{
if (sender.SoundLevel == SoundLevel.Muted)
{
await CleanupCameraAsync();
}
else if (!_isInitialized)
{
await InitializeCameraAsync();
}
}
});
}
private void OrientationSensor_OrientationChanged(SimpleOrientationSensor sender, SimpleOrientationSensorOrientationChangedEventArgs args)
{
if (args.Orientation != SimpleOrientation.Faceup && args.Orientation != SimpleOrientation.Facedown)
{
_deviceOrientation = args.Orientation;
}
}
private async void DisplayInformation_OrientationChanged(DisplayInformation sender, object args)
{
_displayOrientation = sender.CurrentOrientation;
if (_isPreviewing)
{
await SetPreviewRotationAsync();
}
}
#endregion Event handlers
#region MediaCapture methods
private async Task InitializeCameraAsync()
{
Debug.WriteLine("InitializeCameraAsync");
if (_mediaCapture == null)
{
// Attempt to get the back camera if one is available, but use any camera device if not
var cameraDevice = await FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel.Back);
if (cameraDevice == null)
{
Debug.WriteLine("No camera device found!");
return;
}
// Create MediaCapture and its settings
_mediaCapture = new MediaCapture();
// Register for a notification when video recording has reached the maximum time and when something goes wrong
_mediaCapture.RecordLimitationExceeded += MediaCapture_RecordLimitationExceeded;
_mediaCapture.Failed += MediaCapture_Failed;
var settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameraDevice.Id };
// Initialize MediaCapture
try
{
await _mediaCapture.InitializeAsync(settings);
_isInitialized = true;
}
catch (UnauthorizedAccessException)
{
Debug.WriteLine("Access to the camera is denied. You can change the permissions in mobile settings for camera", "Alert!");
}
// If initialization succeeded, start the preview
if (_isInitialized)
{
// Figure out where the camera is located
if (cameraDevice.EnclosureLocation == null || cameraDevice.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Unknown)
{
// No information on the location of the camera, assume it's an external camera, not integrated on the device
_externalCamera = true;
}
else
{
// Camera is fixed on the device
_externalCamera = false;
// Only mirror the preview if the camera is on the front panel
_mirroringPreview = (cameraDevice.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front);
}
await StartPreviewAsync();
UpdateCaptureControls();
}
}
}
private async Task StartPreviewAsync()
{
// Prevent the device from sleeping while the preview is running
_displayRequest.RequestActive();
// Set the preview source in the UI and mirror it if necessary
PreviewControl.Source = _mediaCapture;
PreviewControl.FlowDirection = _mirroringPreview ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
// Start the preview
await _mediaCapture.StartPreviewAsync();
_isPreviewing = true;
// Initialize the preview to the current orientation
if (_isPreviewing)
{
await SetPreviewRotationAsync();
}
}
private async Task FocusCameraLens()
{
if (_mediaCapture != null)
{
if (_isPreviewing)
{
// test if focus is supported
if (_mediaCapture.VideoDeviceController.FocusControl.Supported)
{
// get the focus control from the mediaCapture object
var focusControl = _mediaCapture.VideoDeviceController.FocusControl;
// try to get full range, but settle for the first supported one.
var focusRange = focusControl.SupportedFocusRanges.Contains(AutoFocusRange.FullRange)
? AutoFocusRange.FullRange
: focusControl.SupportedFocusRanges.FirstOrDefault();
var focusMode = focusControl.SupportedFocusModes.Contains(FocusMode.Auto)
? FocusMode.Auto
: focusControl.SupportedFocusModes.FirstOrDefault();
focusControl.Configure(
new FocusSettings
{
Mode = focusMode,
AutoFocusRange = focusRange
});
try
{
// finally wait for the camera to focus
await focusControl.FocusAsync();
}
catch (Exception _focusExp)
{
//Ignore
}
}
}
}
}
private async Task SetPreviewRotationAsync()
{
// Only need to update the orientation if the camera is mounted on the device
if (_externalCamera) return;
// Calculate which way and how far to rotate the preview
int rotationDegrees = ConvertDisplayOrientationToDegrees(_displayOrientation);
// The rotation direction needs to be inverted if the preview is being mirrored
if (_mirroringPreview)
{
rotationDegrees = (360 - rotationDegrees) % 360;
}
// Add rotation metadata to the preview stream to make sure the aspect ratio / dimensions match when rendering and getting preview frames
var props = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview);
int MFVideoRotation = ConvertVideoRotationToMFRotation(VideoRotation.Clockwise90Degrees);
// props.Properties.Add(RotationKey, rotationDegrees);
props.Properties.Add(RotationKey, PropertyValue.CreateInt32(MFVideoRotation));
await _mediaCapture.SetEncodingPropertiesAsync(MediaStreamType.VideoPreview, props, null);
}
int ConvertVideoRotationToMFRotation(VideoRotation rotation)
{
int MFVideoRotation = 0; // MFVideoRotationFormat::MFVideoRotationFormat_0 in Mfapi.h
switch (rotation)
{
case VideoRotation.Clockwise90Degrees:
MFVideoRotation = 90; // MFVideoRotationFormat::MFVideoRotationFormat_90;
break;
case VideoRotation.Clockwise180Degrees:
MFVideoRotation = 180; // MFVideoRotationFormat::MFVideoRotationFormat_180;
break;
case VideoRotation.Clockwise270Degrees:
MFVideoRotation = 270; // MFVideoRotationFormat::MFVideoRotationFormat_270;
break;
}
return MFVideoRotation;
}
#endregion MediaCapture methods
#region Helper functions
private async Task SetupUiAsync()
{
DisplayInformation.AutoRotationPreferences = DisplayOrientations.Portrait;
if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
{
await Windows.UI.ViewManagement.StatusBar.GetForCurrentView().HideAsync();
}
_displayOrientation = _displayInformation.CurrentOrientation;
if (_orientationSensor != null)
{
_deviceOrientation = _orientationSensor.GetCurrentOrientation();
}
RegisterEventHandlers();
var picturesLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Pictures);
_captureFolder = picturesLibrary.SaveFolder ?? ApplicationData.Current.LocalFolder;
this.UpdateLayout();
}
private void UpdateCaptureControls()
{
postingAdViewModel.IsCaptureButtonEnabled = _isPreviewing;
if (_isInitialized && !_mediaCapture.MediaCaptureSettings.ConcurrentRecordAndPhotoSupported)
{
postingAdViewModel.IsCaptureButtonEnabled = !_isRecording;
PhotoButton.Opacity = postingAdViewModel.IsCaptureButtonEnabled ? 1 : 0;
}
}
private void RegisterEventHandlers()
{
if (ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
{
HardwareButtons.CameraPressed += HardwareButtons_CameraPressed;
}
if (_orientationSensor != null)
{
_orientationSensor.OrientationChanged += OrientationSensor_OrientationChanged;
}
_displayInformation.OrientationChanged += DisplayInformation_OrientationChanged;
_systemMediaControls.PropertyChanged += SystemMediaControls_PropertyChanged;
}
private void UnregisterEventHandlers()
{
if (ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
{
HardwareButtons.CameraPressed -= HardwareButtons_CameraPressed;
}
if (_orientationSensor != null)
{
_orientationSensor.OrientationChanged -= OrientationSensor_OrientationChanged;
}
_displayInformation.OrientationChanged -= DisplayInformation_OrientationChanged;
_systemMediaControls.PropertyChanged -= SystemMediaControls_PropertyChanged;
}
private static async Task<DeviceInformation> FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel desiredPanel)
{
var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
DeviceInformation desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredPanel);
return desiredDevice ?? allVideoDevices.FirstOrDefault();
}
private static async Task ReencodeAndSavePhotoAsync(IRandomAccessStream stream, StorageFile file, PhotoOrientation photoOrientation)
{
using (var inputStream = stream)
{
var decoder = await BitmapDecoder.CreateAsync(inputStream);
using (var outputStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateForTranscodingAsync(outputStream, decoder);
var properties = new BitmapPropertySet { { "System.Photo.Orientation", new BitmapTypedValue(photoOrientation, PropertyType.UInt16) } };
await encoder.BitmapProperties.SetPropertiesAsync(properties);
await encoder.FlushAsync();
}
}
}
#endregion Helper functions
#region Rotation helpers
private SimpleOrientation GetCameraOrientation()
{
if (_externalCamera)
{
return SimpleOrientation.NotRotated;
}
var result = _deviceOrientation;
if (_displayInformation.NativeOrientation == DisplayOrientations.Portrait)
{
switch (result)
{
case SimpleOrientation.Rotated90DegreesCounterclockwise:
result = SimpleOrientation.NotRotated;
break;
case SimpleOrientation.Rotated180DegreesCounterclockwise:
result = SimpleOrientation.Rotated90DegreesCounterclockwise;
break;
case SimpleOrientation.Rotated270DegreesCounterclockwise:
result = SimpleOrientation.Rotated180DegreesCounterclockwise;
break;
case SimpleOrientation.NotRotated:
result = SimpleOrientation.Rotated270DegreesCounterclockwise;
break;
}
}
if (_mirroringPreview)
{
switch (result)
{
case SimpleOrientation.Rotated90DegreesCounterclockwise:
return SimpleOrientation.Rotated270DegreesCounterclockwise;
case SimpleOrientation.Rotated270DegreesCounterclockwise:
return SimpleOrientation.Rotated90DegreesCounterclockwise;
}
}
return result;
}
private static int ConvertDeviceOrientationToDegrees(SimpleOrientation orientation)
{
switch (orientation)
{
case SimpleOrientation.Rotated90DegreesCounterclockwise:
return 90;
case SimpleOrientation.Rotated180DegreesCounterclockwise:
return 180;
case SimpleOrientation.Rotated270DegreesCounterclockwise:
return 270;
case SimpleOrientation.NotRotated:
default:
return 0;
}
}
private static int ConvertDisplayOrientationToDegrees(DisplayOrientations orientation)
{
switch (orientation)
{
case DisplayOrientations.Portrait:
return 90;
case DisplayOrientations.LandscapeFlipped:
return 180;
case DisplayOrientations.PortraitFlipped:
return 270;
case DisplayOrientations.Landscape:
default:
return 0;
}
}
private static PhotoOrientation ConvertOrientationToPhotoOrientation(SimpleOrientation orientation)
{
switch (orientation)
{
case SimpleOrientation.Rotated90DegreesCounterclockwise:
return PhotoOrientation.Rotate90;
case SimpleOrientation.Rotated180DegreesCounterclockwise:
return PhotoOrientation.Rotate180;
case SimpleOrientation.Rotated270DegreesCounterclockwise:
return PhotoOrientation.Rotate270;
case SimpleOrientation.NotRotated:
default:
return PhotoOrientation.Normal;
}
}
#endregion Rotation helpers
}
}
What is causing this issue?
Solved:
var boolean = ApplicationView.TryEnterFullScreenMode();
It hides the soft Navigaiton Bar, and aspect ratio is maintained to captureElement, and camera works fine
Related
I have being trying to make private chat in photon voice unity possible but so far not able to. I read the concept for audio groups https://doc.photonengine.com/en-us/voice/current/getting-started/voice-for-pun
In the project First the player1 joining is the master client who creates the room and have the default audio group set to zero. I am using the demo pushtotalk where I want the joining players to be able to talk to the player1 in one to one talk. I tried giving the other players who join after the master client player1 different audio groups and make master client to subscribe them at push of a button or event to make it work but failed to do so. Just want the player1 to be able to listen to all the other players in a private conversation. Please give examples for explanation using the demo scene in photon voice script. Here is the code -
using Client.Photon.LoadBalancing;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Button))]
public class PushToTalkPrivateButton : MonoBehaviour
{
[SerializeField]
private Button pushToTalkPrivateButton;
[SerializeField]
private Text buttonText;
private PushToTalkScript pttScript;
public byte AudioGroup;
public bool Subscribed;
private void Start()
{
pttScript = FindObjectOfType<PushToTalkScript>();
PhotonVoiceNetwork.Client.OnStateChangeAction += OnVoiceClientStateChanged;
}
private void OnVoiceClientStateChanged(ClientState state)
{
Debug.LogFormat("VoiceClientState={0}", state);
if (pushToTalkPrivateButton != null)
{
switch (state)
{
case ClientState.Joined:
pushToTalkPrivateButton.gameObject.SetActive(true);
Subscribed = Subscribed || PhotonVoiceNetwork.Client.ChangeAudioGroups(null, new byte[1] { AudioGroup });
break;
default:
pushToTalkPrivateButton.gameObject.SetActive(false);
break;
}
}
}
public void SetAudioGroup(PhotonPlayer player)
{
if (!Subscribed)
{
buttonText.text = string.Format("Talk-To-Player{0}", player.ID);
int targetActorNr = player.ID;
if (PhotonNetwork.player.ID < targetActorNr)
{
AudioGroup = (byte) (targetActorNr + PhotonNetwork.player.ID*10);
}
else if (PhotonNetwork.player.ID > targetActorNr)
{
AudioGroup = (byte) (PhotonNetwork.player.ID + targetActorNr*10);
}
else
{
return;
}
if (PhotonVoiceNetwork.ClientState == ClientState.Joined)
{
Subscribed = PhotonVoiceNetwork.Client.ChangeAudioGroups(null, new byte[1] { AudioGroup });
}
}
}
public void PushToTalkOn()
{
if (Subscribed)
{
PhotonVoiceNetwork.Client.GlobalAudioGroup = AudioGroup;
pttScript.PushToTalk(true);
}
}
public void PushToTalkOff()
{
pttScript.PushToTalkOff();
}
}
I just modified OnVoiceClientStateChanged() and SetAudioGroup().
AudioGroup need be set before you call ChangeAudioGroups().
private void OnVoiceClientStateChanged(ClientState state)
{
Debug.LogFormat("VoiceClientState={0}", state);
if (pushToTalkPrivateButton != null)
{
switch (state)
{
case ClientState.Joined:
//Subscribed = Subscribed || PhotonVoiceNetwork.Client.ChangeAudioGroups(null, new byte[1] { AudioGroup });
break;
default:
pushToTalkPrivateButton.gameObject.SetActive(false);
PhotonVoiceNetwork.Client.ChangeAudioGroups(byte[0], null);
break;
}
}
}
public void SetAudioGroup(PhotonPlayer player)
{
if (!Subscribed)
{
buttonText.text = string.Format("Talk-To-Player{0}", player.ID);
int targetActorNr = player.ID;
if (PhotonNetwork.player.ID < targetActorNr)
{
AudioGroup = (byte) (targetActorNr + PhotonNetwork.player.ID*10);
}
else if (PhotonNetwork.player.ID > targetActorNr)
{
AudioGroup = (byte) (PhotonNetwork.player.ID + targetActorNr*10);
}
else
{
return;
}
if (PhotonVoiceNetwork.ClientState == ClientState.Joined)
{
pushToTalkPrivateButton.gameObject.SetActive(true);
Subscribed = PhotonVoiceNetwork.Client.ChangeAudioGroups(null, new byte[1] { AudioGroup });
}
}
}
I have a problem to stop/pause a Mp3 Queue. Any help please?
I use this class from Githup. it work fine but can't stop it:
public class playr
{
private Queue<string> playlist;
private IWavePlayer player = new WaveOutEvent();
private WaveStream fileWaveStream;
public playr()
{
}
public playr(List<string> startingPlaylist)
{
playlist = new Queue<string>(startingPlaylist);
}
public void PlaySong()
{
if (playlist.Count < 1)
{
return;
}
if (player != null && player.PlaybackState != PlaybackState.Stopped)
{
player.Stop();
}
if (fileWaveStream != null)
{
fileWaveStream.Dispose();
}
if (player != null)
{
player.Dispose();
player = null;
}
player = new WaveOutEvent();
fileWaveStream = new NAudio.Wave.Mp3FileReader(playlist.Dequeue(), new Mp3FileReader.FrameDecompressorBuilder(waveFormat => new NLayer.NAudioSupport.Mp3FrameDecompressor(waveFormat)));
var stream = new BlockAlignReductionStream(fileWaveStream);
player.Init(fileWaveStream);
player.Play();
player.PlaybackStopped += (sender, evn) => { PlaySong(); };
}
}
I popup mp3 files from a datagridview. The goal is playing mp3 sounds and drawing charts.
private void Play_Click(object sender, EventArgs e)
{
try
{
playlist = new List<string>();
for (int item = 0; item < dataGridView1.Rows.Count - 1; item++)
{
playlist.Add(#"mp3Conversion\sounds\" + dataGridView1.Rows[item].Cells["mp3"].Value.ToString());
}
playr playr = new playr(playlist);
playr.PlaySong();
}
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
}
It wont to stop when I click stop button. is there a way to add a notifier or manage queue ?
private void btnStop_Click(object sender, EventArgs e)
{
try
{
var playr = new playr(playlist);
playr.stopit();
}
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
}
I hope it's not too late to help you
You can't pause, because you are losing the reference to the object defining a new object
You could try to define the object as static object to solve this problem, but you have to be very careful disposing the object or access to it from multi thread
A very little example
public class playr
{
private Queue<string> playlist;
public static IWavePlayer player = new WaveOutEvent();
// private WaveStream fileWaveStream;
public playr()
{
}
public playr(List<string> startingPlaylist)
{
playlist = new Queue<string>(startingPlaylist);
}
public void PlaySong()
{
if (playlist.Count < 1)
{
return;
}
if (player != null && player.PlaybackState != PlaybackState.Stopped)
{
player.Stop();
}
if (player != null)
{
player.Dispose();
player = null;
}
player = new WaveOutEvent();
var audioFilePath = playlist.First();
var fileWaveStream = new AudioFileReader(audioFilePath);
player.Init(fileWaveStream);
player.Play();
player.PlaybackStopped += (sender, evn) => { PlaySong(); };
}
}
Then you can handle the "player" object from form view
On the face of it it seems quite simple.
I have a switch case and if the condition is met I would like to print text to a label with a animation.
in this case a type writer animation.
I have already made the animation however I cant seem to integrate a similar version it into the switch case itself.
Any help?
Type Writer Animation code c#:
public partial class Form1 : Form
{
int _charIndex = 0;
string _text = "This is a test.";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
_charIndex = 0;
label1.Text = string.Empty;
Thread t = new Thread(new ThreadStart(this.TypewriteText));
t.Start();
}
private void TypewriteText()
{
while (_charIndex < _text.Length)
{
Thread.Sleep(50);
label1.Invoke(new Action(() =>
{
label1.Text += _text[_charIndex];
}));
_charIndex++;
}
}
}
}
And the animation code needs to be placed into this:
Switch case code:
void TestEngine(object sender, SpeechRecognizedEventArgs e)
{
switch (e.Result.Text)
{
case "Test":
//Label animation code goes here
break;
Thanks in advance!
Short answer - move the code in a method and call it from anywhere you want.
Long answer
While it works, it doesn't make sense because all the worker thread does is sleeping and then calling the UI thread. System.Windows.Forms.Timer based approach would be much appropriate for this concrete case. The "modern" approach would be based on async/await. If you need flexibility, the last one is the best choice. But whatever you choose, you'll hit a reentrancy problem at some point and will need to handle it. The best would be to prepare some helper utility class and use it from anywhere. Here is an example:
using System;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Tests
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestForm());
}
class TestForm : Form
{
public TestForm()
{
var label = new Label { Parent = this, AutoSize = true, Top = 8, Left = 8 };
animateHelper = new AnimateHelper(label);
int left = 8;
foreach (var action in (ButtonAction[])Enum.GetValues(typeof(ButtonAction)))
{
var button = new Button { Parent = this, AutoSize = true, Text = action.ToString(), Left = left };
button.Top = DisplayRectangle.Bottom - button.Height - 8;
button.Click += (sender, e) => Execute(action);
left += button.Width + 8;
}
}
protected override void Dispose(bool disposing)
{
if (disposing && animateHelper != null) animateHelper.Cancel();
base.Dispose(disposing);
}
enum ButtonAction { TypewriteText, RepeatText, Cancel }
private void Execute(ButtonAction action)
{
// the original question
switch (action)
{
case ButtonAction.TypewriteText:
TypewriteText("This is a typewriter text animantion test.");
break;
case ButtonAction.RepeatText:
RepeatText("This is a repeating text animantion test.");
break;
case ButtonAction.Cancel:
animateHelper.Cancel();
break;
}
}
AnimateHelper animateHelper;
void TypewriteText(string text)
{
animateHelper.Execute(async (output, ct) =>
{
bool clear = true;
try
{
if (string.IsNullOrEmpty(text)) return;
output.ForeColor = Color.Blue;
for (int length = 1; ; length++)
{
if (ct.IsCancellationRequested) return;
output.Text = text.Substring(0, length);
if (length == text.Length) break;
await Task.Delay(50, ct);
}
clear = false;
}
finally { if (clear) output.Text = string.Empty; }
});
}
void RepeatText(string text)
{
animateHelper.Execute(async (output, ct) =>
{
try
{
if (string.IsNullOrEmpty(text)) return;
output.ForeColor = Color.Red;
while (true)
{
for (int length = 1; length <= text.Length; length++)
{
if (ct.IsCancellationRequested) return;
output.Text = text.Substring(text.Length - length);
await Task.Delay(50, ct);
}
for (int pad = 1; pad < text.Length; pad++)
{
if (ct.IsCancellationRequested) return;
output.Text = new string(' ', pad) + text.Substring(0, text.Length - pad);
await Task.Delay(50, ct);
}
if (ct.IsCancellationRequested) return;
output.Text = string.Empty;
await Task.Delay(250, ct);
}
}
finally { output.Text = string.Empty; }
});
}
}
class AnimateHelper
{
Label output;
Task task;
CancellationTokenSource cts;
public AnimateHelper(Label output) { this.output = output; }
void Reset()
{
if (cts != null) { cts.Dispose(); cts = null; }
task = null;
}
public void Cancel() { DontCare(CancelAsync()); }
async Task CancelAsync()
{
if (task != null && !task.IsCompleted)
{
try { cts.Cancel(); } catch { }
try { await task; } catch { }
}
Reset();
}
public void Execute(Func<Label, CancellationToken, Task> action) { DontCare(ExecuteAsync(action)); }
async Task ExecuteAsync(Func<Label, CancellationToken, Task> action)
{
await CancelAsync();
cts = new CancellationTokenSource();
task = action(output, cts.Token);
try { await task; } catch { }
Reset();
}
// make compiler happy
static void DontCare(Task t) { }
}
}
}
I have a program that when the user says "Start" or "Stop", the program makes a skeleton display on the screen. I use the same code as the Shape Game, and it works fine there, but not on my code. I dont know which part of the code doesn't work since this is my first time eith speech recognition programming. Thanks for your help(Sorry if my code is messy)Recognizing the Speech
public class SpeechRecognizer : IDisposable
{
private KinectAudioSource kinectAudioSource;
private struct WhatSaid
{
public Verbs Verb;
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
this.Stop();
if (this.sre != null)
{
// NOTE: The SpeechRecognitionEngine can take a long time to dispose
// so we will dispose it on a background thread
ThreadPool.QueueUserWorkItem(
delegate(object state)
{
IDisposable toDispose = state as IDisposable;
if (toDispose != null)
{
toDispose.Dispose();
}
},
this.sre);
this.sre = null;
}
this.isDisposed = true;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public EchoCancellationMode EchoCancellationMode
{
get
{
this.CheckDisposed();
return this.kinectAudioSource.EchoCancellationMode;
}
set
{
this.CheckDisposed();
this.kinectAudioSource.EchoCancellationMode = value;
}
}
public static SpeechRecognizer Create()
{
SpeechRecognizer recognizer = null;
try
{
recognizer = new SpeechRecognizer();
}
catch (Exception)
{
// speech prereq isn't installed. a null recognizer will be handled properly by the app.
}
return recognizer;
}
private void CheckDisposed()
{
if (this.isDisposed)
{
throw new ObjectDisposedException("SpeechRecognizer");
}
}
public void Stop()
{
this.CheckDisposed();
if (this.sre != null)
{
this.kinectAudioSource.Stop();
this.sre.RecognizeAsyncCancel();
this.sre.RecognizeAsyncStop();
this.sre.SpeechRecognized -= this.SreSpeechRecognized;
this.sre.SpeechHypothesized -= this.SreSpeechHypothesized;
this.sre.SpeechRecognitionRejected -= this.SreSpeechRecognitionRejected;
}
}
public void Start(KinectAudioSource kinectSource)
{
this.CheckDisposed();
this.kinectAudioSource = kinectSource;
this.kinectAudioSource.AutomaticGainControlEnabled = false;
this.kinectAudioSource.BeamAngleMode = BeamAngleMode.Adaptive;
var kinectStream = this.kinectAudioSource.Start();
this.sre.SetInputToAudioStream(
kinectStream, new SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));
this.sre.RecognizeAsync(RecognizeMode.Multiple);
}
public enum Verbs
{
None = 0,
Start,
Stop,
Resume,
Pause
}
private bool isDisposed;
private readonly Dictionary<string, WhatSaid> speechCommands = new Dictionary<string, WhatSaid>
{
{ "Start", new WhatSaid { Verb = Verbs.Start } },
{ "Stop", new WhatSaid { Verb = Verbs.Stop } },
{ "Resume", new WhatSaid { Verb = Verbs.Resume } },
{ "Pause", new WhatSaid { Verb = Verbs.Pause } },
};
private SpeechRecognitionEngine sre;
private static RecognizerInfo GetKinectRecognizer()
{
Func<RecognizerInfo, bool> matchingFunc = r =>
{
string value;
r.AdditionalInfo.TryGetValue("Kinect", out value);
return "True".Equals(value, StringComparison.InvariantCultureIgnoreCase) && "en-US".Equals(r.Culture.Name, StringComparison.InvariantCultureIgnoreCase);
};
return SpeechRecognitionEngine.InstalledRecognizers().Where(matchingFunc).FirstOrDefault();
}
private SpeechRecognizer()
{
RecognizerInfo ri = GetKinectRecognizer();
this.sre = new SpeechRecognitionEngine(ri);
this.LoadGrammar(this.sre);
}
private void LoadGrammar(SpeechRecognitionEngine speechRecognitionEngine)
{
// Build a simple grammar of shapes, colors, and some simple program control
var single = new Choices();
foreach (var phrase in this.speechCommands)
{
single.Add(phrase.Key);
}
var objectChoices = new Choices();
objectChoices.Add(single);
var actionGrammar = new GrammarBuilder();
actionGrammar.AppendWildcard();
actionGrammar.Append(objectChoices);
var allChoices = new Choices();
allChoices.Add(actionGrammar);
allChoices.Add(single);
// This is needed to ensure that it will work on machines with any culture, not just en-us.
var gb = new GrammarBuilder { Culture = speechRecognitionEngine.RecognizerInfo.Culture };
gb.Append(allChoices);
var g = new Grammar(gb);
speechRecognitionEngine.LoadGrammar(g);
speechRecognitionEngine.SpeechRecognized += this.SreSpeechRecognized;
speechRecognitionEngine.SpeechHypothesized += this.SreSpeechHypothesized;
speechRecognitionEngine.SpeechRecognitionRejected += this.SreSpeechRecognitionRejected;
}
private void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
{
var said = new SaidSomethingEventArgs { Verb = Verbs.None, Matched = "?" };
this.SetLabel("Word not Recognized.... Try 'Start', 'Stop', 'Pause' or 'Resume'");
if (this.SaidSomething != null)
{
this.SaidSomething(new object(), said);
}
}
private void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
{
this.SetLabel("I think you said: " + e.Result.Text);
}
public event EventHandler<SaidSomethingEventArgs> SaidSomething;
private void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
this.SetLabel("\rSpeech Recognized: \t" + e.Result.Text);
if ((this.SaidSomething == null) || (e.Result.Confidence < 0.3))
{
return;
}
var said = new SaidSomethingEventArgs { Verb = 0, Phrase = e.Result.Text };
foreach (var phrase in this.speechCommands)
{
if (e.Result.Text.Contains(phrase.Key) && (phrase.Value.Verb == Verbs.Pause))
{
//pause = true;
break;
}
else if ((e.Result.Text.Contains(phrase.Key) && (phrase.Value.Verb == Verbs.Resume)))
{
//resume = true;
break;
}
else if ((e.Result.Text.Contains(phrase.Key) && (phrase.Value.Verb == Verbs.Start)))
{
//start = true;
break;
}
else if ((e.Result.Text.Contains(phrase.Key) && (phrase.Value.Verb == Verbs.Stop)))
{
//stop = true;
break;
}
}
// Look for a match in the order of the lists below, first match wins.
List<Dictionary<string, WhatSaid>> allDicts = new List<Dictionary<string, WhatSaid>> { this.speechCommands };
bool found = false;
for (int i = 0; i < allDicts.Count && !found; ++i)
{
foreach (var phrase in allDicts[i])
{
if (e.Result.Text.Contains(phrase.Key))
{
found = true;
break;
}
}
}
if (!found)
{
return;
}
}
public class SaidSomethingEventArgs : EventArgs
{
public Verbs Verb { get; set; }
public string Phrase { get; set; }
public string Matched { get; set; }
}
public event Action<string> SetLabel = delegate { };
}
In my Code
private void RecognizeSaidSomething(object sender, SpeechRecognizer.SpeechRecognizer.SaidSomethingEventArgs e)
{
FlyingText.FlyingText.NewFlyingText(this.skeleton.Width / 30, new Point(this.skeleton.Width / 2, this.skeleton.Height / 2), e.Matched);
switch (e.Verb)
{
case SpeechRecognizer.SpeechRecognizer.Verbs.Pause:
pause = true;
break;
case SpeechRecognizer.SpeechRecognizer.Verbs.Resume:
resume = true;
break;
case SpeechRecognizer.SpeechRecognizer.Verbs.Start:
start = true;
break;
case SpeechRecognizer.SpeechRecognizer.Verbs.Stop:
stop = true;
break;
}
}
It doesn't look like you ever call RecognizeSaidSomething() from SreSpeechRecognized(). You create the event args:
var said = new SaidSomethingEventArgs { Verb = 0, Phrase =
e.Result.Text };
But it doesn't appear that you do anything with it.
The foreach loop below that doesn't seem to serve any purpose, you test for the phrase then just break out of the loop. You don't set any variables or call any functions in that loop that I can see.
Then there is a for loop that appears to do something similar to the foreach loop (just in a different manner). It searches for matches to the recognized phrase, but then doesn't do anything with what it finds. It just returns.
I would think somewhere in the SreSpeechRecognized() event handler you want to call RecognizeSaidSomething() and pass it the SaidSomethingEventArgs.
I want to playback a sound file in two or three external sound cards at the same time and I think that using threads is the solution but I really didn't know how to use it in the playback code.
This is the event makes on button play:
public partial class PlaybackForm : Form
{
IWavePlayer waveOut;
string fileName = null;
WaveStream mainOutputStream;
WaveChannel32 volumeStream;
int _deviceNum;
int _deviceNum1;
Thread t1;
Thread t2;
public PlaybackForm(int deviceNum,int deviceNum1)
{
InitializeComponent();
_deviceNum = deviceNum;
_deviceNum1 = deviceNum1;
}
private void buttonPlay_Click(object sender, EventArgs e)
{
if (waveOut != null)
{
if (waveOut.PlaybackState == PlaybackState.Playing)
{
return;
}
else if (waveOut.PlaybackState == PlaybackState.Paused)
{
waveOut.Play();
return;
}
}
// we are in a stopped state
// TODO: only re-initialise if necessary
if (String.IsNullOrEmpty(fileName))
{
toolStripButtonOpenFile_Click(sender, e);
}
if (String.IsNullOrEmpty(fileName))
{
return;
}
try
{
CreateWaveOut();
}
catch (Exception driverCreateException)
{
MessageBox.Show(String.Format("{0}", driverCreateException.Message));
return;
}
mainOutputStream = CreateInputStream(fileName);
trackBarPosition.Maximum = (int)mainOutputStream.TotalTime.TotalSeconds;
labelTotalTime.Text = String.Format("{0:00}:{1:00}", (int)mainOutputStream.TotalTime.TotalMinutes,
mainOutputStream.TotalTime.Seconds);
trackBarPosition.TickFrequency = trackBarPosition.Maximum / 30;
try
{
waveOut.Init(mainOutputStream);
}
catch (Exception initException)
{
MessageBox.Show(String.Format("{0}", initException.Message), "Error Initializing Output");
return;
}
// not doing Volume on IWavePlayer any more
volumeStream.Volume = volumeSlider1.Volume;
waveOut.Play();
}
And this is how to create the waveout:
private void CreateWaveOut()
{
CloseWaveOut();
int latency = (int)comboBoxLatency.SelectedItem;
//if (radioButtonWaveOut.Checked)
{
//WaveCallbackInfo callbackInfo = checkBoxWaveOutWindow.Checked ?
WaveCallbackInfo callbackInfo = WaveCallbackInfo.FunctionCallback();
// WaveCallbackInfo callbackInfo = WaveCallbackInfo.FunctionCallback();
// WaveCallbackInfo.NewWindow(): WaveCallbackInfo.FunctionCallback();
WaveOut outputDevice = new WaveOut(callbackInfo);
outputDevice.DesiredLatency = latency;
outputDevice.DeviceNumber = _deviceNum;
waveOut = outputDevice;
}
}
I declared two deviceNum but until now I can playsound only in one device,that's why I want to use thread.
Can you help me please
Thank you in advance
Do something like that:
using System.Threading;
...
private void buttonPlay_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(this.PlaySound), 1);
ThreadPool.QueueUserWorkItem(new WaitCallback(this.PlaySound), 2);
}
private void PlaySound(object obj)
{
int deviceNumber = (int)obj;
// Do the stuff you used to do in buttonPlay_Click
WaveOut myWaveOut = CreateWaveOut(deviceNumber);
...
}
private WaveOut CreateWaveOut(int deviceNumber)
{
...
WaveOut outputDevice = new WaveOut(callbackInfo);
outputDevice.DesiredLatency = latency;
outputDevice.DeviceNumber = _deviceNum;
return outputDevice;
}