Exception when playing wave with WaveOutEvent of NAudio - c#

In my WPF application, I want to play mp3 and wave files with WaveOutEvent from NAudio. It works fine with mp3s, but I get a NullReferenceException in NAudio.Core "The object reference has not been set to an object instance." when I run it with a wave-file. The exception occures after the player was started with _player.Play();
Here is my code:
using (AudioFileReader afr = new AudioFileReader(_filename))
{
OffsetSampleProvider osp = new OffsetSampleProvider(afr);
osp.SkipOver = currentCursorPosition;
osp.Take = PlaybackDuration;
WaveOutEvent player = new WaveOutEvent();
player.Init(osp);
player.Play();
}
Exception.Source = NAudio.Core
Exception.StackTrace = bei NAudio.Wave.WaveFileReader.get_Position()
Modul is NAudio.Core.dll, version 2.01.0.0
Any idea what might be wrong and how to solve this?
Thanks in advance,
Frank

The Play method only begins playback. You're then disposing the AudioFileReader before it has finished playing the file.

Related

.net c# windows forms, play sound without overlaping [duplicate]

Is there a way to play two sounds at the same time?
I know that SoundPlayer isn't able to do this.
I can't use SoundEffect as I believe it's only part of XNA.
The two required sounds will be called at unknown and random times. The sound needs to be be controlled after it is played. i.e., the sound must be able to be stopped before it has finished playing.
Reference PresentationCore and WindowsBase and try this...
var p1 = new System.Windows.Media.MediaPlayer();
p1.Open(new System.Uri(#"C:\windows\media\tada.wav"));
p1.Play();
// this sleep is here just so you can distinguish the two sounds playing simultaneously
System.Threading.Thread.Sleep(500);
var p2 = new System.Windows.Media.MediaPlayer();
p2.Open(new System.Uri(#"C:\windows\media\tada.wav"));
p2.Play();
EDIT
I received a downvote probably because at first glance this looks like it will play the second sound after the first is finished. It doesn't, they are played by windows asynchronously. The sleep is there so if you test this code verbatim you can hear the sounds play together, it wouldn't be noticeable without the delay since they are the same sound.
This code demonstrates the two sounds playing on separate threads on top of each other, which is sort of pointless since the playback doesn't block anyway
new System.Threading.Thread(() => {
var c = new System.Windows.Media.MediaPlayer();
c.Open(new System.Uri(#"C:\windows\media\tada.wav"));
c.Play();
}).Start();
System.Threading.Thread.Sleep(500);
new System.Threading.Thread(() => {
var c = new System.Windows.Media.MediaPlayer();
c.Open(new System.Uri(#"C:\windows\media\tada.wav"));
c.Play();
}).Start();
http://msdn.microsoft.com/en-us/library/system.windows.media.mediaplayer.stop.aspx
The class also has the control you need to stop playback
The "MediaPlayer" object will not let you play two sounds at once, even if you create two instances. You will need to bring in the native windows API "mciSendString".
[DllImport("winmm.dll")]
static extern Int32 mciSendString(string command, StringBuilder buffer, int bufferSize, IntPtr hwndCallback);
public Form1()
{
InitializeComponent();
mciSendString(#"open C:\Users\Jono\Desktop\applause.wav type waveaudio alias applause", null, 0, IntPtr.Zero);
mciSendString(#"play applause", null, 0, IntPtr.Zero);
mciSendString(#"open C:\Users\Jono\Desktop\foghorn.wav type waveaudio alias foghorn", null, 0, IntPtr.Zero);
mciSendString(#"play foghorn", null, 0, IntPtr.Zero);
}
check PlaySound method here http://msdn.microsoft.com/en-us/library/aa909766.aspx, and its flag SND_ASYNC .
Solution :
Hi,
I was developing a WP8 App and i needed multiple sounds to play simultaneously, the solutions mentioned above didnt work for me, So i used the XNA framwork. here is the link
http://msdn.microsoft.com/en-us/library/ff842408.aspx
and then play ur sound files like this...
SoundEffect Sound = SoundEffect.FromStream(Application.GetResourceStream(new Uri("Assets/Sounds/wav/sound.wav", UriKind.Relative)).Stream);
Sound.Play();
For looping...
SoundEffectInstance Sound = SoundEffect.FromStream(Application.GetResourceStream(new Uri("Assets/Sounds/wav/sound.wav", UriKind.Relative)).Stream).CreateInstance();
Sound.IsLooped = true;
Sound.Play();
Note: the files must be in ".wav" (PCM, 8 or 16-bit, 8KHz to 48KHz, mono or stereo) format
From http://alvas.net/alvas.audio,samples.aspx#sample7 and http://alvas.net/alvas.audio,samples.aspx#sample6
Player pl = new Player();
byte[] arr = File.ReadAllBytes(#"in.wav");
pl.Play(arr);
Player pl2 = new Player();
pl2.FileName = "123.mp3";
pl2.Play();
or mix audio data before playing How to mix to mix two audio file..
private void Mix(string outfile, string infile1, string infile2, int shiftSec)
{
WaveReader wr1 = new WaveReader(File.OpenRead(infile1));
WaveReader wr2 = new WaveReader(File.OpenRead(infile2));
IntPtr format1 = wr1.ReadFormat();
WaveFormat wf = AudioCompressionManager.GetWaveFormat(format1);
WaveWriter ww = new WaveWriter(File.Create(outfile), AudioCompressionManager.FormatBytes(format1));
byte[] data0 = wr1.ReadData(0, shiftSec);
byte[] data1 = wr1.ReadData(shiftSec);
byte[] data2 = wr2.ReadData();
byte[] mixData = AudioCompressionManager.Mix(format1, data2, data1);
ww.WriteData(data0);
ww.WriteData(mixData);
ww.Close();
wr2.Close();
wr1.Close();
}
The accepted answer didn't work for me.
Here is what worked:
Make sure you add references to PresentationCore and WindowsBase dlls.
private void Form1_Load(object sender, EventArgs e)
{
System.Media.SoundPlayer player = new System.Media.SoundPlayer(#"C:\Users\me\source\repos\TacticalIslandSurvival\sounds\blazer rail.wav");
player.PlayLooping();
}
private void button1_MouseEnter(object sender, EventArgs e)
{
var p1 = new System.Windows.Media.MediaPlayer();
p1.Open(new System.Uri(#"C:\Users\me\source\repos\TacticalIslandSurvival\sounds\click.wav"));
p1.Play();
}

How can I make the SpeechSynthesizer speak through a particular device?

I am new to the Speech Recognition, so please excuse me if the question is very basic level.
My application captures what I speak through my microphone. I have written some responses using my c# code for every command I say and the SpeechSynthesizer does this without any issues using the code mentioned below.
But I want the SpeechSynthesizer to respond back through my laptop speaker, rather than my default input device (my microphone). Is it doable?
The code I am currently using is given below. I am looking for something which can get all the playback devices available and then select and speak back using my speaker.
public void SpeakTheText(string text)
{
SpeechInput = text;
SpeechSynthesizer _synthesizer = new SpeechSynthesizer();
_synthesizer.SelectVoiceByHints(VoiceGender.Male);
_synthesizer.SetOutputToDefaultAudioDevice();//Microphone
_synthesizer.SpeakAsync(SpeechInput);
}
You could use the System.Media.SoundPlayer class to output the audio from a stream. See this example from MSDN
public void SpeakTheText(string text)
{
// Initialize a new instance of the speech synthesizer.
using (SpeechSynthesizer synth = new SpeechSynthesizer())
using (MemoryStream streamAudio = new MemoryStream())
{
// Create a SoundPlayer instance to play the output audio file.
System.Media.SoundPlayer m_SoundPlayer = new System.Media.SoundPlayer();
// Set voice to male
synth.SelectVoiceByHints(VoiceGender.Male);
// Configure the synthesizer to output to an audio stream.
synth.SetOutputToWaveStream(streamAudio);
// Speak a phrase.
synth.Speak(text);
streamAudio.Position = 0;
m_SoundPlayer.Stream = streamAudio;
m_SoundPlayer.Play();
// Set the synthesizer output to null to release the stream.
synth.SetOutputToNull();
// Insert code to persist or process the stream contents here.
}
}
I'm not sure if SoundPlayer can specify an output device, but it should output using your default output device.
Have a look at NAudio, it has implemented this feature. You can have a look at the implementation on their GIT implementation and copy the code you need or clone/ get the package.
as per the implementation, you can simply loop overthem
[TestFixture]
public class DirectSoundTests
{
[Test]
[Category("IntegrationTest")]
public void CanEnumerateDevices()
{
foreach(var device in DirectSoundOut.Devices)
{
Debug.WriteLine(String.Format("{0} {1} {2}", device.Description, device.ModuleName, device.Guid));
}
}
}
Based on the Microsoft docs for the method - the Control Panel is what determines your audio output - and that should not be a microphone - that should be an audio device with speakers.. make sure you have that configured - and tested in the control panel

error in realtime wasapi capture(from sound card) manipulate and play

I'm trying to capture all sound going through the computer to manipulate and play it in realTime (there can be a slight delay due to manipulation but nothing too serious).
I'm trying to do this using Naudio wasapi. The problem is:
When I do it in exclusive mode, this line: audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, latencyRefTimes,outputFormat, Guid.Empty);
throws this exception:
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in NAudio.dll
Additional information: HRESULT: 0x88890016
When I do it in shared mode I get lot of noise which I think is caused by sound feedback (similiar to what happens when recording and playing at the same time)
Here's my code:
WasapiLoopbackCapture source = new WasapiLoopbackCapture();
source.DataAvailable += CaptureOnDataAvailable;
bufferedWaveProvider = new BufferedWaveProvider(source.WaveFormat);
volumeProvider = new VolumeSampleProvider(bufferedWaveProvider.ToSampleProvider());
WasapiOut soundOut = new WasapiOut(AudioClientShareMode.Shared, 0);
soundOut.Init(volumeProvider);
soundOut.Play();
source.StartRecording();
soundOut.Volume = 0.5f;
}
private void CaptureOnDataAvailable(object sender, WaveInEventArgs waveInEventArgs)
{
int length = waveInEventArgs.Buffer.Length;
byte[] byteSamples = new Byte[length];
float[] buffer = waveInEventArgs.Buffer.toFloatArray(waveInEventArgs.BytesRecorded);//buffer to contains the samples about to be manipulated
fixer.fixSamples(length / 2, buffer, ref fixedSamples);
if (fixedSamples.Count > 0)
{
//convert the fixed samples back to bytes in order for them to be able to play out
byteSamples = fixedSamples.convertToByteArray(position);
bufferedWaveProvider.AddSamples(byteSamples, 0, byteSamples.Length);
volumeProvider.Volume = .5f;
}
position = fixedSamples.Count;
}
How can I solve these problems?
Also, I don't know if it's the best approach for what i'm trying to do, so if anyone has a better idea how to do this I'm more than happy to hear.
(i thought about using asio, but decided not to since there are a lot of computers without an asio driver)
this error is AUDCLNT_E_UNSUPPORTED_FORMAT
You can only capture audio in certain formats with WASAPI. Usually has to be IEEE float, stereo, 44.1kHz / 48kHz

VlcControl not streaming properly

I'm using VlcDotNet to stream video and I faced a strange issue recently. When I stream video from my webcamera with VLC player I can perfectly watch it. But when I try to stream it using VlcControl I get an error that VLC couldn't connect to the source. I'm using the same options in VLC and VlcControl:
:sout=#transcode{vcodec=h264,vb=0,scale=0,acodec=mpga,ab=128,channels=2,samplerate=44100}:http{mux=ffmpeg{mux=flv},dst=:10177/} :sout-keep
Maybe I missing something, please look at my code:
if (Environment.Is64BitOperatingSystem)
{
VlcContext.LibVlcDllsPath = CommonStrings.LIBVLC_DLLS_PATH_DEFAULT_VALUE_AMD64;
VlcContext.LibVlcPluginsPath = CommonStrings.PLUGINS_PATH_DEFAULT_VALUE_AMD64;
}
else
{
VlcContext.LibVlcDllsPath = CommonStrings.LIBVLC_DLLS_PATH_DEFAULT_VALUE_X86;
VlcContext.LibVlcPluginsPath = CommonStrings.PLUGINS_PATH_DEFAULT_VALUE_X86;
}
//Set the startup options
VlcContext.StartupOptions.IgnoreConfig = true;
VlcContext.StartupOptions.LogOptions.LogInFile = true;
VlcContext.StartupOptions.LogOptions.ShowLoggerConsole = false;
VlcContext.StartupOptions.LogOptions.Verbosity = VlcLogVerbosities.None;
VlcContext.CloseAll();
VlcContext.Initialize();
VlcControl player = new VlcControl();
var media = new LocationMedia("dshow://");
media.AddOption(":sout=#transcode{vcodec=h264,vb=0,scale=0,acodec=mpga,ab=128,channels=2,samplerate=44100}:http{mux=ffmpeg{mux=flv},dst=:10177/} :sout-keep");
player.Media = media;
player.Play();
Console.WriteLine("Translation started...");
Console.ReadLine();
I think Vlc could not connect to your webcam because you didn't pass it the name of the camera
i tried it and i got
:dshow-vdev=USB2.0 Camera :dshow-adev= :live-caching=300
try at as another aption but make sure to change the camera name
PS. you can find this option, when you open Open Capture device --> tick the Show More Options
i think this will solve your problem :)

Can't open a mpg-File for capture using EmguCV with C#

I'm trying to open a mpg-File using emguCV. I use the following code:
if (instance == null)
{
lock (m_lock)
{
try
{
instance = new Capture(0); // capture from camera works fine if a camera is connected
}
catch (NullReferenceException)
{
String sFileName = #"C:\tmp\MarkerMovie.mpg";
try
{
if (File.Exists(sFileName))
{
instance = new Capture(sFileName); // here the exception is thrown
}
else
{
MessageBox.Show("No Camera and no Video-File found");
}
}
catch (NullReferenceException)
{
MessageBox.Show("Couldn't open Video: "+sFileName);
}
}
}
}
If a webcam is connected everything works fine, but when I unplug the webcam the line instance = new Capture(sFileName); throws a NullReferenceException:
Message = "Unable to create capture from C:\tmp\MarkerMovie.mpg"
I debugged and found the reason is in the constructor of capture. The following command always returns a Null-Pointer:
_ptr = CvInvoke.cvCreateFileCapture(fileName);
I could open the same video using C++ using this code:
cap = cvCaptureFromFile("C:\\tmp\\MarkerMovie.mpg");
I'm new to openCV, so I'm not sure which information you need to help me. I installed emguCV yesterday from http://sourceforge.net/projects/emgucv/ on a Windows XP computer. The installer-version is x86_2.3.0.1416. I included opencv_core231.dll, opencv_highgui231.dll and opencv_imgproc231.dll to my project.
Does somebody know how I can make this code working?
Let me know if you need more information.
Thanks.
I had the same problem and adding the opencv_ffmpeg.dll to the project seems to solve it. (Found in the bin directory in the Emgu CV directory) I have tried it on the project that you posted and it seems to be working too. Hope it helps.
With EmguCV in C#, you need to put the opencv_ffmpeg.dll, for example: opencv_ffmpeg2410.dll, be careful if you have x86 or 64 bits

Categories

Resources