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;
}
Related
I am writing a program which is supposed to detect when a USB serial device is plugged in and then log on to the new com port. The code below works wonderfully, but I have noticed in debugging the code and stepping through it that the event handler "DetectChange" fires twice. I'm not sure that this is normal, or an action of the debugger.
In any case, the code works, but I am new at event handling and I would like to make sure that I am not going to cause any issues as I add more code to actually read and write from the serial port.
(I got some of this code from stackoverflow, but I have misplaced my paper with names for attribution. If you see your code below, my heartfelt thanks.)
using System;
using System.IO.Ports;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Management;
using System.Threading;
namespace SerialTest
{
public partial class Form1 : Form
{
SerialMethods serialMethods = new SerialMethods();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
loadCmdBox();
}
private void CmdBoxPort_SelectedIndexChanged(object sender, EventArgs e)
{
handleComPort();
}
private void handleComPort()
{
// Set the right port for the selected item.
// The portname is based on the "COMx" part of the string (SelectedItem)
string item = CmdBoxPort.SelectedItem.ToString();
// Search for the expression "(COM" in the "selectedItem" string
if (item.Contains("(COM"))
{
// Get the index number where "(COM" starts in the string
int indexOfCom = item.IndexOf("(COM");
// Set PortName to COMx based on the expression in the "selectedItem" string
// It automatically gets the correct length of the COMx expression to make sure
// that also a COM10, COM11 and so on is working properly.
string PortName = item.Substring(indexOfCom + 1, item.Length - indexOfCom - 2);
if (serialMethods._serialPort.IsOpen)
{
serialMethods._serialPort.Close();
serialMethods.Connect(PortName);
label5.Text = "Active Port: " + PortName;
}
else
{
serialMethods.Connect(PortName);
label5.Text = PortName;
}
}
else
return;
}
private void loadCmdBox()
{
// Get all serial (COM)-ports you can see in the devicemanager
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\cimv2",
"SELECT * FROM Win32_PnPEntity WHERE ClassGuid=\"{4d36e978-e325-11ce-bfc1-08002be10318}\"");
// Sort the items in the combobox
CmdBoxPort.Sorted = true;
// Add all available (COM)-ports to the combobox
foreach (System.Management.ManagementObject queryObj in searcher.Get().Cast<ManagementObject>())
{
CmdBoxPort.Items.Add(queryObj["Caption"]);
}
SerialPortService.PortsChanged += (sender1, changedArgs) => DetectChange(changedArgs.EventType);
label2.Text = "";
label3.Text = "";
label4.Text = "";
}
protected Task<Task> getSerPorts()
{
CmdBoxPort.Text = "";
CmdBoxPort.Update();
if (!String.IsNullOrEmpty(CmdBoxPort.Text))
{
handleComPort();
return Task.FromResult(Task.CompletedTask);
}
else
{
loadCmdBox();
return Task.FromResult(Task.CompletedTask);
}
}
private void ExitButton_Click(object sender, EventArgs e)
{
SerialPortService.CleanUp();
this.Close();
}
private void RefreshButton_Click(object sender, EventArgs e)
{
refresh();
}
protected Task<Task> refresh()
{
label2.Text = "";
label3.Text = "";
label4.Text = "";
CmdBoxPort.Items.Clear();
getSerPorts();
return Task.FromResult(Task.CompletedTask);
}
protected virtual void DetectChange(EventType changedArgs)
{
if (changedArgs == EventType.Insertion)
{
try
{
Task tr = (Task)Invoke(new Action( () => { getSerPorts(); }));
Task rr = (Task)Invoke(new Action(() => { refresh(); }));
}
catch (Exception ex) { MessageBox.Show("Exception at insertion invoke method " + ex, "Exception", MessageBoxButtons.OK); }
}
else if (changedArgs == EventType.Removal)
{
try
{
Task tr = (Task)Invoke(new Action( () => { getSerPorts(); }));
Task rr = (Task)Invoke(new Action(() => { refresh(); }));
}
catch (Exception ex) { MessageBox.Show("Exception at removal invoke method " + ex, "Exception", MessageBoxButtons.OK); }
}
return;
}
}
public static class SerialPortService
{
private static SerialPort _serialPort;
private static string[] _serialPorts;
private static ManagementEventWatcher arrival;
private static ManagementEventWatcher removal;
private static readonly SerialMethods SD = new SerialMethods();
static SerialPortService()
{
_serialPorts = SerialPort.GetPortNames();
MonitorDeviceChanges();
}
public static void CleanUp()
{
arrival.Stop();
removal.Stop();
}
public static event EventHandler<PortsChangedArgs> PortsChanged;
private static void MonitorDeviceChanges()
{
try
{
var deviceArrivalQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
var deviceRemovalQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
arrival = new ManagementEventWatcher(deviceArrivalQuery);
removal = new ManagementEventWatcher(deviceRemovalQuery);
arrival.EventArrived += (o, args) => RaisePortsChangedIfNecessary(EventType.Insertion);
removal.EventArrived += (sender, eventArgs) => RaisePortsChangedIfNecessary(EventType.Removal);
// Start listening for events
arrival.Start();
removal.Start();
}
catch (ManagementException err)
{
MessageBox.Show("Management exception = " + err, "Info", MessageBoxButtons.OK);
}
}
private static void RaisePortsChangedIfNecessary(EventType eventType)
{
lock (_serialPorts)
{
var availableSerialPorts = SerialPort.GetPortNames();
if (eventType == EventType.Insertion)
{
var added = availableSerialPorts.Except(_serialPorts).ToArray();
_serialPorts = availableSerialPorts;
PortsChanged.Raise(null, new PortsChangedArgs(eventType, added));
}
else if (eventType == EventType.Removal)
{
var removed = _serialPorts.Except(availableSerialPorts).ToArray();
_serialPorts = availableSerialPorts;
PortsChanged.Raise(null, new PortsChangedArgs(eventType, removed));
}
}
}
public static void Raise<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
{
handler?.Invoke(sender, args);
}
}
public enum EventType
{
Insertion,
Removal,
}
public class PortsChangedArgs : EventArgs
{
private readonly EventType _eventType;
private readonly string[] _serialPorts;
public PortsChangedArgs(EventType eventType, string[] serialPorts)
{
_eventType = eventType;
_serialPorts = serialPorts;
}
public string[] SerialPorts => _serialPorts;
public EventType EventType => _eventType;
}
}
Just took a short look at this. It seems like getSerPorts() will always execute loadCmdBox() (CmdBoxPort.Text = ""; ... if (!String.IsNullOrEmpty(CmdBoxPort.Text))) that will attach a new event handler (previous attached event handlers will not be removed by attaching a new one).
You should either remove the existing event handler befor attaching a new one or only attach the event handler once.
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
I have created a splash screen. On my splash screen I have given a progress bar and two buttons to perform some action. On button click I am displaying respective forms once the modules of those forms are getting loaded completely along with showing the progress on progress bar. Once the respective form will open, Splash screen shall be closed and Form should be shown on top of the screen.
But the issue is that after the splash screen closing, My form is opening in background or you can say getting out of focus which should not happen. I have checked various solutions given on google or stackoverflow but could not able to resolve my problem.
Following is my code :
SplashScreen.cs
// <--- Data Members
// --->
public SplashScreen()
{
InitializeComponent();
this.Opacity = 0.0;
UpdateTimer.Interval = TIMER_INTERVAL;
UpdateTimer.Start();
this.ClientSize = this.BackgroundImage.Size;
}
static public void ShowSplashScreen()
{
if (ms_frmSplash != null)
{
return;
}
ms_oThread = new Thread(new ThreadStart(SplashScreen.ShowForm));
ms_oThread.IsBackground = true;
ms_oThread.SetApartmentState(ApartmentState.STA);
ms_oThread.Start();
while (ms_frmSplash == null || ms_frmSplash.IsHandleCreated == false)
{
System.Threading.Thread.Sleep(TIMER_INTERVAL);
}
}
static public void CloseForm()
{
if (ms_frmSplash != null && ms_frmSplash.IsDisposed == false)
{
ms_frmSplash.m_dblOpacityIncrement = -ms_frmSplash.m_dblOpacityDecrement;
}
ms_oThread = null;
ms_frmSplash = null;
}
static public void SetStatus(string newStatus)
{
SetStatus(newStatus, true);
}
static public void SetStatus(string newStatus, bool setReference)
{
if (ms_frmSplash == null)
{
return;
}
ms_frmSplash.m_sStatus = newStatus;
if (setReference)
{
ms_frmSplash.SetReferenceInternal();
}
}
static public void SetReferencePoint()
{
if (ms_frmSplash == null)
{
return;
}
ms_frmSplash.SetReferenceInternal();
}
static private void ShowForm()
{
ms_frmSplash = new SplashScreen();
Application.Run(ms_frmSplash);
}
private void SetReferenceInternal()
{
if (m_bDTSet == false)
{
m_bDTSet = true;
m_dtStart = DateTime.Now;
ReadIncrements();
}
double dblMilliseconds = ElapsedMilliSeconds();
m_alActualTimes.Add(dblMilliseconds);
m_dblLastCompletionFraction = m_dblCompletionFraction;
if (m_alPreviousCompletionFraction != null && m_iIndex < m_alPreviousCompletionFraction.Count)
{
m_dblCompletionFraction = (double)m_alPreviousCompletionFraction[m_iIndex++];
}
else
{
m_dblCompletionFraction = (m_iIndex > 0) ? 1 : 0;
}
}
private double ElapsedMilliSeconds()
{
TimeSpan ts = DateTime.Now - m_dtStart;
return ts.TotalMilliseconds;
}
private void ReadIncrements()
{
string sPBIncrementPerTimerInterval = SplashScreenXMLStorage.Interval;
double dblResult;
if (Double.TryParse(sPBIncrementPerTimerInterval, System.Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo, out dblResult) == true)
{
m_dblPBIncrementPerTimerInterval = dblResult;
}
else
{
m_dblPBIncrementPerTimerInterval = .0015;
}
string sPBPreviousPctComplete = SplashScreenXMLStorage.Percents;
if (sPBPreviousPctComplete != "")
{
string[] aTimes = sPBPreviousPctComplete.Split(null);
m_alPreviousCompletionFraction = new ArrayList();
for (int i = 0; i < aTimes.Length; i++)
{
double dblVal;
if (Double.TryParse(aTimes[i], System.Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo, out dblVal) == true)
{
m_alPreviousCompletionFraction.Add(dblVal);
}
else
{
m_alPreviousCompletionFraction.Add(1.0);
}
}
}
else
{
m_bFirstLaunch = true;
m_sTimeRemaining = "";
}
}
private void StoreIncrements()
{
string sPercent = "";
double dblElapsedMilliseconds = ElapsedMilliSeconds();
for (int i = 0; i < m_alActualTimes.Count; i++)
{
sPercent += ((double)m_alActualTimes[i] / dblElapsedMilliseconds).ToString("0.####", System.Globalization.NumberFormatInfo.InvariantInfo) + " ";
}
SplashScreenXMLStorage.Percents = sPercent;
m_dblPBIncrementPerTimerInterval = 1.0 / (double)m_iActualTicks;
SplashScreenXMLStorage.Interval = m_dblPBIncrementPerTimerInterval.ToString("#.000000", System.Globalization.NumberFormatInfo.InvariantInfo);
}
public static SplashScreen GetSplashScreen()
{
return ms_frmSplash;
}
private void UpdateTimer_Tick(object sender, System.EventArgs e)
{
if (Program.isRadarSelected)
{
if (count >= 100)
{
UpdateTimer.Stop();
this.Close();
}
else
{
updateProgressBar();
count += 5;
}
}
if (m_dblOpacityIncrement > 0)
{
m_iActualTicks++;
if (this.Opacity < 1)
{
this.Opacity += m_dblOpacityIncrement;
}
}
else
{
if (this.Opacity > 0)
{
this.Opacity += m_dblOpacityIncrement;
}
else
{
StoreIncrements();
UpdateTimer.Stop();
this.Close();
}
}
}
private void updateProgressBar()
{
SplashScreen.SetStatus("Loading : " + count + " %");
statusLabel.Text = m_sStatus;
m_dblLastCompletionFraction += m_dblPBIncrementPerTimerInterval;
int width = (int)Math.Floor(statusPanel.ClientRectangle.Width * m_dblLastCompletionFraction);
int height = statusPanel.ClientRectangle.Height;
int x = statusPanel.ClientRectangle.X;
int y = statusPanel.ClientRectangle.Y;
if (width > 0 && height > 0)
{
m_rProgress = new Rectangle(x, y, width, height);
if (!statusPanel.IsDisposed)
{
Graphics g = statusPanel.CreateGraphics();
LinearGradientBrush brBackground = new LinearGradientBrush(m_rProgress, Color.FromArgb(58, 96, 151), Color.FromArgb(181, 237, 254), LinearGradientMode.Horizontal);
g.FillRectangle(brBackground, m_rProgress);
g.Dispose();
}
}
}
private void RadarSelectionButton_Click(object sender, EventArgs e)
{
Program.isButtonClicked= true;
}
Program.cs
internal static class Program
{
public static bool isButtonClicked= false;
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SplashScreen.ShowSplashScreen();
Application.DoEvents();
while (!isButtonClicked)
{
System.Threading.Thread.Sleep(50);
}
Application.Run(new MyForm());
SplashScreen.CloseForm();
}
}
As far as I remember Application.Run(...) is blocking, meaning that your splash screen would never close before the main window is closed. You could try the code below. Let me know how it goes.
internal static class Program
{
public static bool isButtonClicked= false;
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SplashScreen.ShowSplashScreen();
Application.DoEvents();
while (!isButtonClicked)
{
System.Threading.Thread.Sleep(50);
}
var window = new MyForm();
window.Load += (s, e) =>
{
SplashScreen.CloseForm();
window.Activate();
}
Application.Run(window);
}
}
Regarding you CloseForm method, I am unsure how you intended it to work. The only thing you are doing is setting the opacity? But as far as you write this is not your issue. But I would think that you need to signal the main window of the splash screen to close, before the Application.Run(..) would exit.
And also the while loop in the ShowSplashScreen method; Why? Consider using stuff like ManualResetEvent for waiting and signaling between threads. Always better to wait for an event rather than polling.
I am another person dabbling with C# and wanting to create a simple audio application that plays wav files loaded into the program via an upload program. My issue is that I need to get whatever audio file currently being played to pause with the track timer of the audio file being used when I start the audio file again via my Play button. I already have a global timer, 'baseTimer', that I think I can use to set the audio file, that was stopped, track duration point. However I do not know how to accomplish this nor do I really know how to use all of the mci commands yet.
I have displayed all of my code for my main application... I also have read that I may need to utilize threading, but I've also read that it would be impossible to set an audio files track duration with a thread.
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
}
System.Timers.Timer baseTimer = new System.Timers.Timer();
List<string> PlayList = new List<string>();
List<byte> PlayList_byte;
int soundNum = 0;
private string music_PATH { get; set; }
private string talk_PATH { get; set; }
private byte Pause_TIME { get; set; }
private string Pause_RADIO { get; set; }
bool isStopped = new bool();
bool isPaused = new bool();
[DllImport("winmm.dll")]
private static extern uint mciSendString(string command, StringBuilder returnValue, int returnLength, IntPtr winHandle);
public static int GetSoundLength(string fileName)
{
StringBuilder lengthBuf = new StringBuilder(32);
mciSendString(string.Format("open \"{0}\" type waveaudio alias wave", fileName), null, 0, IntPtr.Zero);
mciSendString("status wave length", lengthBuf, lengthBuf.Capacity, IntPtr.Zero);
mciSendString("close wave", null, 0, IntPtr.Zero);
int length = 0;
int.TryParse(lengthBuf.ToString(), out length);
return length;
}
private void SetPath()
{
music_PATH = #"..\\..\\commercial\list.txt";
talk_PATH = #"..\\..\\main\list.txt";
StreamReader myReader;
using (myReader = new StreamReader(music_PATH))
{
while (myReader.Peek() != -1)
{
string read = myReader.ReadLine();
PlayList.Add(read);
}
}
using (myReader = new StreamReader(talk_PATH))
{
while (myReader.Peek() != -1)
{
string read = myReader.ReadLine();
PlayList.Add(read);
}
myReader.Close();
}
foreach (string sound in PlayList)
{
soundNum++;
}
}
private string CurrentSound()
{
try
{
Random _randx = new Random();
int pick = _randx.Next(0, soundNum);
string currentaudio = PlayList[pick];
Pause_RADIO = currentaudio;
return currentaudio;
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
return null;
}
string _SelectedSound = "";
private string _Sound(string currentradio, string pattern)
{
foreach (Match entry in Regex.Matches(currentradio, pattern))
{
_SelectedSound = entry.Value.ToString();
}
if (_SelectedSound == "music")
{
return "commercial";
}
else if (_SelectedSound == "talk")
{
return "main";
}
return null;
}
private void _SetTimer(string currentradio, string pattern)
{
baseTimer.Interval = GetSoundLength(#"..\\..\\" + pattern + #"\" + currentradio);
}
private bool isRepeat(string lastradio, string currentradio)
{
if (lastradio == currentradio)
{
return true;
}
else
{
return false;
}
}
private void baseTimerElasped(object sender, ElapsedEventArgs e)
{
Radio.FrmMain play = new Radio.FrmMain();
play.PlayPlayer();
}
private void PlayPlayer()
{
MediaPlayer wavplayer;
try
{
if (soundNum == 0)
{
SetPath();
PlayPlayer();
}
else
{
string currentradio = CurrentSound();
bool localcheck = isRepeat(_SelectedSound, currentradio);
if (localcheck == true)
{
PlayPlayer();
}
else
{
string Pattern = #"(music|talk)";
string selected = _Sound(currentradio, Pattern);
_SetTimer(currentradio, selected);
switch (selected)
{
case "commercial":
music_PATH = #"..\\..\\commercial\";
PlayList_byte = new List<byte>(File.ReadAllBytes(music_PATH + currentradio));
wavplayer = new MediaPlayer(PlayList_byte.GetRange(0, PlayList_byte.Count).ToArray());
wavplayer.Play();
baseTimer.Start();
break;
case "main":
talk_PATH = #"..\\..\\main\";
PlayList_byte = new List<byte>(File.ReadAllBytes(talk_PATH + currentradio));
wavplayer = new MediaPlayer(PlayList_byte.GetRange(0, PlayList_byte.Count).ToArray());
wavplayer.Play();
baseTimer.Start();
break;
}
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message + ex.StackTrace + ex.Source);
}
}
private void PausePlayer()
{
MediaPlayer wavplayer = new MediaPlayer(PlayList_byte.GetRange(0, PlayList_byte.Count).ToArray());
baseTimer.Stop();
MessageBox.Show("Count: " + PlayList_byte.Count + "Pause_TIME: " + Pause_TIME + "\nPlaylist_byte" + PlayList_byte.ToString());
try
{
switch (isPaused)
{
case false:
isPaused = true;
wavplayer.Stop();
break;
case true:
isPaused = false;
string localcheck = _Sound(Pause_RADIO, #"(music|talk)");
switch (localcheck)
{
case "commercial":
music_PATH = #"..\\..\\commercial\";
wavplayer.Play(PlayList_byte.GetRange(PlayList_byte.Count - Pause_TIME, PlayList_byte.Count - Pause_TIME).ToArray());
break;
case "main":
talk_PATH = #"..\\..\\main\";
wavplayer.Play(PlayList_byte.GetRange(PlayList_byte.Count - Pause_TIME, PlayList_byte.Count - Pause_TIME).ToArray());
break;
}
break;
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message + ex.Data);
}
}
private void btnPlay_Click(object sender, EventArgs e)
{
switch (isStopped)
{
case false:
isStopped = true;
btnPlay.Image = Image.FromFile(#"..\\..\\Pause.png");
lblPlay.Text = "Pause";
if (isPaused == false)
{
PlayPlayer();
}
else
{
PausePlayer();
}
break;
case true:
isStopped = false;
btnPlay.Image = Image.FromFile(#"..\\..\\Play.png");
lblPlay.Text = "Play";
PausePlayer();
break;
}
baseTimer.Elapsed += new ElapsedEventHandler(baseTimerElasped);
}
private void btnNext_Click(object sender, EventArgs e)
{
PlayPlayer();
}
private void btnStop_Click(object sender, EventArgs e)
{
MediaPlayer wavplayer = new MediaPlayer();
wavplayer.Stop();
baseTimer.Stop();
}
private void btnQuit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void btnGetUpload_Click(object sender, EventArgs e)
{
Uploader FrmUpload = new Uploader();
FrmUpload.Show();
this.Hide();
}
}
class MediaPlayer
{
SoundPlayer wavplayer;
public MediaPlayer()
{
Stop();
}
public MediaPlayer(byte[] buffer)
{
MemoryStream memStream = new MemoryStream(buffer, true);
wavplayer = new SoundPlayer(memStream);
}
public void Play()
{
wavplayer.Play();
}
public void Play(byte[] buffer)
{
wavplayer.Stream.Seek(0, SeekOrigin.Begin);
wavplayer.Stream.Write(buffer, 0, buffer.Length);
wavplayer.Play();
}
public void Stop()
{
wavplayer.Stop();
}
}
Edit:
For clarity currentaudio has a file as such "music3.wav" or "talk1.wav" in it.
Super old question but just for anyone looking here's what worked for me:
double currentPos = audioplayer.CurrentPosition;
audioplayer.Play();
audioplayer.Seek(currentPos);
SoundPlayer is extremely limited, and doesn't support Pause and Resume. Are you able to use the WPF MediaElement instead? You will find it is much more powerful, supporting playing files of many types, repositioning, setting volume, pausing and resuming. You can also use it to get the file length instead of mci.
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.