I have an app that I need to play a wav file when a key or button pressed or clicked, I use the SoundPlayer class but when i try to play another wav file at the same time the one that was playing stops.
Is there a way to play multiple wav files at the same time?
If its one could you please give me examples or tutorial?
Here's what I got so far:
private void pictureBox20_Click(object sender, EventArgs e)
{
if (label30.Text == "Waiting 15.wav")
{
MessageBox.Show("No beat loaded");
return;
}
using (SoundPlayer player = new SoundPlayer(label51.Text))
{
try
{
player.Play();
}
catch (FileNotFoundException)
{
MessageBox.Show("File has been moved." + "\n" + "Please relocate it now!");
}
}
}
Thanks!
You can do this with the System.Windows.Media.MediaPlayer class. Note that you will need to add references to WindowsBase and PresentationCore.
private void pictureBox20_Click(object sender, EventArgs e)
{
const bool loopPlayer = true;
if (label30.Text == "Waiting 15.wav")
{
MessageBox.Show("No beat loaded");
return;
}
var player = new System.Windows.Media.MediaPlayer();
try
{
player.Open(new Uri(label51.Text));
if(loopPlayer)
player.MediaEnded += MediaPlayer_Loop;
player.Play();
}
catch (FileNotFoundException)
{
MessageBox.Show("File has been moved." + "\n" + "Please relocate it now!");
}
}
EDIT: You can loop the sound by subscribing to the MediaEnded event.
void MediaPlayer_Loop(object sender, EventArgs e)
{
MediaPlayer player = sender as MediaPlayer;
if (player == null)
return;
player.Position = new TimeSpan(0);
player.Play();
}
Based on your code, I'm guessing that you are writing some kind of music production software. I'm honestly not sure that this method will loop perfectly every time, but as far as I can tell, it's the only way to loop using the MediaPlayer control.
You cannot play two sounds at once using SoundPlayer.
SoundPlayer uses the Native WINAPI PlaySound which does not support playing multiple sound at same instance.
Better Option would be to Reference WindowsMediaPlayer
Add a reference to C:\Windows\System32\wmp.dll
var player1 = new WMPLib.WindowsMediaPlayer();
player1.URL = #"C:\audio_output\sample1.wav";
var player2 = new WMPLib.WindowsMediaPlayer();
player2.URL = #"C:\audio_output\sample2.wav";
Related
I have a problem when I try to play a list of songs, my code does not work. Only the first few seconds each song plays but I want to play all the contents of each song list:
private void Play()
{
List<Song> songList = ViewModelLocator.Instance.SongListVM.Songs;
foreach(Song song in songList)
{
audioFileReader = new AudioFileReader(song.Path);
waveOutDevice.Init(audioFileReader);
waveOutDevice.Play();
}
}
I tried to use a Thread:
waveOutDevice.Play();
Thread.Sleep(audioFileReader.TotalTime);
but it only hangs.
For me I used this :
int song_index=0; // index of the song
private void player_play()
{
outputdevice.PlaybackStopped += playbackstopped;
if (outputdevice.PlaybackState != PlaybackState.Paused)
{
to_play = playlist.Rows[song_index].Cells[0].Value.ToString();
audiofile = new AudioFileReader(to_play);
outputdevice.Init(audiofile);
}
outputdevice.Play();
}
// this event occur when the playing file has ended
private void playbackstopped(object sender, StoppedEventArgs e)
{
song_index++; // play the next file
player_play();
}
The problem is simple: I want to record audio using the microphone when and only when a key is held down. When the key is lifted I want it to stop recording. Then pass this recording to the speech recognition.
The issue is when I press and hold the Z button, It will go into the gkh_KeyUp event and continue to run this code. I want to simply record while it is held, not run this record function a bunch of times.
I want to use this in conjunction with Microsofts speech recognition.
using System.Speech.Recognition;
public partial class Form1 : Form
{
SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine();
Grammar dictationGrammar = new DictationGrammar();
public Form1()
{
InitializeComponent();
globalKeyboardHook gkh = new globalKeyboardHook();
gkh.HookedKeys.Add(Keys.Z);
//gkh.HookedKeys.Add(Keys.B);
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
recognizer = new SpeechRecognitionEngine();
dictationGrammar = new DictationGrammar();
recognizer.LoadGrammar(dictationGrammar);
}
void gkh_KeyUp(object sender, KeyEventArgs e)
{
textBox1.Text = "Up" + e.KeyCode.ToString();
try
{
RecognitionResult result = recognizer.Recognize();
textBox1.Text = result.Text;
}
catch (InvalidOperationException exception)
{
textBox1.Text = String.Format("Could not recognize input from default aduio device. Is a microphone or sound card available?\r\n{0} - {1}.", exception.Source, exception.Message);
}
e.Handled = true;
}
void gkh_KeyDown(object sender, KeyEventArgs e)
{
textBox1.Text += "Down" + e.KeyCode.ToString();
try
{
//recognizer.SetInputToDefaultAudioDevice();
recognizer.SetInputToAudioStream()
}
catch (InvalidOperationException exception)
{
button1.Text = String.Format("Could not recognize input from default aduio device. Is a microphone or sound card available?\r\n{0} - {1}.", exception.Source, exception.Message);
}
e.Handled = true;
}
private void button1_Click(object sender, EventArgs e)
{
SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine();
Grammar dictationGrammar = new DictationGrammar();
recognizer.LoadGrammar(dictationGrammar);
try
{
button1.Text = "Speak Now";
recognizer.SetInputToDefaultAudioDevice();
//recognizer.SetInputToAudioStream;
RecognitionResult result = recognizer.Recognize();
textBox1.Text = result.Text;
}
catch (InvalidOperationException exception)
{
button1.Text = String.Format("Could not recognize input from default aduio device. Is a microphone or sound card available?\r\n{0} - {1}.", exception.Source, exception.Message);
}
finally
{
recognizer.UnloadAllGrammars();
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
Keyboard hook: http://www.codeproject.com/Articles/19004/A-Simple-C-Global-Low-Level-Keyboard-Hook
There is no difference between real very frequent keypresses and keypresses emulated when you hold the button.
You'd need to use a timeout, if the down was not emitted after 0.5 seconds after up, you stop the recording.
You can access hold state of the key if you still want to use a hook, but you need to use a bit lower level access. You can explore WM_KEYDOWN event and look for a bit 30 of the key state:
How to disable WM_KEYDOWN repeat event for Shift/Ctrl/Alt key?
I've been at this for a while, but made no progress. So this is my last resort!
I am trying to send the system-audio (the audio I hear in my headphones) to Skype (making the persons in my call hear what I hear basically). And I thought I would do this using the Skype4comlib and naudio.
What I've done is to create a class which uses the WasapiLoopbackCapture and WaveFileWriter to write temporary data to a .wav file, and redirect audio using the SkypeSystemAudio.set_InputDevice method. But when I'm talking to somebody and I try to start recording, the person doesn't hear me anymore. I just go completely quiet and no sound is being played to the person.
I thought it would be best if I posted the whole class since it's easier to understand everything.
public class SkypeSystemAudio
{
public NAudio.Wave.WasapiLoopbackCapture capture;
NAudio.CoreAudioApi.MMDevice device;
NAudio.Wave.WaveFileWriter writer;
private Call CurrentCall = null;
private Skype SkypeApplet;
private const int SkypeProtocol = 9;
private bool IsRecording = false;
public string tempfilepath = System.IO.Directory.GetCurrentDirectory() + #"\temp.wav";
#region Public
public void Initialize()
{
device = NAudio.Wave.WasapiLoopbackCapture.GetDefaultLoopbackCaptureDevice();
Init();
}
public void Initialize(NAudio.CoreAudioApi.MMDevice device)
{
this.device = device;
Init();
}
public void StartRecording()
{
capture.StartRecording();
if (CurrentCall != null)
{
CurrentCall.set_OutputDevice(TCallIoDeviceType.callIoDeviceTypeFile, tempfilepath);
IsRecording = true;
}
}
public void StopRecording()
{
capture.StopRecording();
if (CurrentCall != null)
{
CurrentCall.set_OutputDevice(TCallIoDeviceType.callIoDeviceTypeFile, "");
}
}
#endregion
private void Init()
{
capture = new WasapiLoopbackCapture(device);
capture.ShareMode = NAudio.CoreAudioApi.AudioClientShareMode.Shared;
capture.DataAvailable += capture_DataAvailable;
capture.RecordingStopped += capture_RecordingStopped;
WaveFormat format = new WaveFormat(16000, 1); // skype wants 16 Bit samples, 16khz, mono WAV file
//tried using the standard waveformat in the device object too. Didn't work though.
writer = new WaveFileWriter(tempfilepath, format );
SkypeApplet = new Skype();
SkypeApplet.Attach(SkypeProtocol, true);
SkypeApplet.CallStatus += SkypeApplet_CallStatus;
}
void SkypeApplet_CallStatus(Call pCall, TCallStatus Status)
{
if (Status == TCallStatus.clsRinging)
{
CurrentCall = pCall;
pCall.Answer();
}
}
void capture_DataAvailable(object sender, WaveInEventArgs e)
{
if (writer != null)
writer.Write(e.Buffer, 0, e.BytesRecorded);
}
void capture_RecordingStopped(object sender, StoppedEventArgs e)
{
IsRecording = false;
}
}
Does anyone know why this isn't working? I have no clues anymore what to do next.
Any help will greatly appreciated!
I have actually done some something similar, but not using Skype4COM.
What I did was using "Virtual Cables" just like Sebastian L suggested, this way you can control whats going in and out off skype, the downside is that you need to install the virtual cables and configure Skype to use them.
The cables will appear in audio devices as standard input/output.
I have used these cables VAC and VB cable
Hope it helps.
I want the Windows Phone 8 app that I am building at this moment to access the camera for taking a photo when a concrete button on the screen is pressed and then save the image that has been taken into a determined folfer (a folder created into the Windows Phone project by me, not the Windows Phone default image gallery).
Could you help me accesing the camera, taking the picture and saving it into the folder created by me, please? I am using XAML and C#.
Thank you so much!!!
I would recommend PhotoCamera class if capture is to be processed on a button in the app
PhotoCamera myCamera = new Microsoft.Devices.PhotoCamera(CameraType.Primary);
//viewfinderBrush is a videobrush object declared in xaml
viewfinderBrush.SetSource(myCamera);
myCamera.Initialized += myCamera_Initialized;
myCamera.CaptureCompleted += new EventHandler<CameraOperationCompletedEventArgs>(camera_CaptureCompleted);
myCamera.CaptureImageAvailable += new EventHandler<Microsoft.Devices.ContentReadyEventArgs>(camera_CaptureImageAvailable);
//Events
void myCamera_Initialized(object sender, CameraOperationCompletedEventArgs e)
{
try
{
if (e.Succeeded)
{
}
}
catch
{
MessageBox.Show("Problem occured in camera initialization.");
}
}
void camera_CaptureCompleted(object sender, CameraOperationCompletedEventArgs e)
{
try
{
}
catch
{
MessageBox.Show("Captured image is not available, please try again.");
}
}
void camera_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
try
{
}
catch (Exception ex)
{
MessageBox.Show("Captured image is not available, please try again. " + ex.Message);
}
}
And there is one more alternative called CameraCaptureTask
CameraCaptureTask cameraCaptureTask;
cameraCaptureTask = new CameraCaptureTask();
cameraCaptureTask.Completed += new EventHandler<PhotoResult>(cameraCaptureTask_Completed);
cameraCaptureTask.Show();
void cameraCaptureTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
MessageBox.Show(e.ChosenPhoto.Length.ToString());
//Code to display the photo on the page in an image control named myImage.
//System.Windows.Media.Imaging.BitmapImage bmp = new System.Windows.Media.Imaging.BitmapImage();
//bmp.SetSource(e.ChosenPhoto);
//myImage.Source = bmp;
}
}
Check this for PhotoCamera class
And this for CameraCaptureTask
There's a simple code demonstration here showing your to put the camera API to use for Windows Phone8 apps.
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if ((PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true) ||
(PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing) == true)) {
// Initialize the default camera.
_photoCamera = new Microsoft.Devices.PhotoCamera();
//Event is fired when the PhotoCamera object has been initialized
_photoCamera.Initialized += new EventHandler<Microsoft.Devices.CameraOperationCompletedEventArgs>(OnPhotoCameraInitialized);
//Set the VideoBrush source to the camera
viewfinderBrush.SetSource(_photoCamera);
}
else {
// The camera is not supported on the device.
this.Dispatcher.BeginInvoke(delegate() {
// Write message.
txtDebug.Text = "A Camera is not available on this device.";
});
}
}
private void OnPhotoCameraInitialized(object sender, CameraOperationCompletedEventArgs e) {
int width = Convert.ToInt32(_photoCamera.PreviewResolution.Width);
int height = Convert.ToInt32(_photoCamera.PreviewResolution.Height);
}
Dont forget to add this line in WMAppManifent.xml file.
<Capability Name="ID_CAP_ISV_CAMERA"/>
you can read here ,
Using Cameras in Your Windows Phone Application
I'm experimenting on how to play mp3 using Naudio. My simple app has one windows form and one button to play/pause the music. The app however has two major problem:
While it was intended that if the music is playing and the play button is pressed, the app should stop playing. Instead when the button is re-pressed, the app restart the music and then (sometime) throw an exception
If the button is pressed two or three times (and without any delay) ,the app throw a NAudio.MmException (Message=InvalidParameter calling acmStreamClose)
Can someone tell me what's wrong with my code? Below is my code:
using System;
using System.Windows.Forms;
namespace NaudioTesting
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private NAudio.Wave.BlockAlignReductionStream stream = null;
private NAudio.Wave.DirectSoundOut output = null;
public void LoadFile(string filePath)
{
DisposeWave();
if (filePath.EndsWith(".mp3"))
{
NAudio.Wave.WaveStream pcm =
NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(new NAudio.Wave.Mp3FileReader(filePath));
stream = new NAudio.Wave.BlockAlignReductionStream(pcm);
}
else if (filePath.EndsWith(".wav"))
{
NAudio.Wave.WaveStream pcm = new NAudio.Wave.WaveChannel32(new NAudio.Wave.WaveFileReader(filePath));
stream = new NAudio.Wave.BlockAlignReductionStream(pcm);
}
else throw new InvalidOperationException("Not a correct audio file type.");
output = new NAudio.Wave.DirectSoundOut();
output.Init(stream);
output.Play();
}
private void playPauseButton_Click(object sender, EventArgs e)
{
string filePath = "GetLoud.mp3";
LoadFile(filePath);
if (output != null)
{
if (output.PlaybackState == NAudio.Wave.PlaybackState.Playing) output.Pause();
else if (output.PlaybackState == NAudio.Wave.PlaybackState.Paused) output.Play();
}
}
private void DisposeWave()
{
try
{
if (output != null)
{
if (output.PlaybackState == NAudio.Wave.PlaybackState.Playing) output.Stop();
output.Dispose();
output = null;
}
if (stream != null)
{
stream.Dispose();
stream = null;
}
}
catch (NAudio.MmException)
{
throw;
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
DisposeWave();
}
}
}
Looking at the DirectSoundOut source, the implementation for Play and Pause doesn't support resuming. Namely, what happens to you is exactly what it should. Calling play will always start from begining of the stream.
You should use WaveOut instead. It supports resuming by calling Play again, just like what you have in your code.
output = new NAudio.Wave.WaveOut();