How do I ensure reliable async wav playback in dotnet? - c#

I am playing wav files as user prompts in dotnet. My code works fine on a laptop, but seems to skip sounds on a netbook. How do I ensure wav playback is consistent on the netbook in dotnet?
Current code that causes occasional playback problems in netbook:
using (var player = new SoundPlayer(pSoundPath))
{
player.Play();
}
Same issue when I pre-load the sounds into a dictionary to call by sound name:
Dictionary<string, SoundPlayer> playerDict = new Dictionary<string, SoundPlayer>();
playerDict.Add(soundName, new SoundPlayer(soundPath));
playerDict[soundname].LoadAsync();

Perhaps giving a dedicated higher-priority thread to the Player may help. Async != parallel. It could be that the async call is contending for processor time with your foreground work.

Related

How can I use sound effect in C# console app?

I´m doing this small RPG game in the C# console app, and I wanted to add some background music and effects when choosing menu options.
What I noticed was that I wasn´t able to do anything when the background music started to play. I thought of threading, but this is completly new to me (started to learn C# 6 weeks ago).
What I managed to do was starting a new thread and play the sounds
static Thread backgroundMusic = new Thread(() =>
{
using (var audioFile = new AudioFileReader(AppDomain.CurrentDomain.BaseDirectory + "\\menu.mp3"))
using (var outputDevice = new WaveOutEvent())
{
backgroundMusic.IsBackground = true;
outputDevice.Init(audioFile);
outputDevice.Play();
while (true)
{
Thread.Sleep(1);
}
}
});
And then for the sound effect I do...
static Thread click = new Thread(() =>
{
using (var audioFile = new AudioFileReader(AppDomain.CurrentDomain.BaseDirectory + "\\click.mp3"))
using (var outputDevice = new WaveOutEvent())
{
click.IsBackground = true;
outputDevice.Init(audioFile);
outputDevice.Play();
while (true)
{
Thread.Sleep(1);
}
}
});
I start these with
click.Start();
backgroundMusic.Start();
Ok so far so good. It plays the background music and it plays the sound effect, but only one time. Can I reuse the thread in some way to play the click sound again when another option is chosen?
And can I abort sound in some way? I might want different music when you play the game and in the menus.
tried backgroundMusic.Abort(); but then I got this:
System.PlatformNotSupportedException: 'Thread abort is not supported on this platform.'
And i can not restart a thread once I´ve started it one time. I tried with
backgroundMusic.Start();
I´ve been checking out forums but all seems to cover windows forms, and not be working with console app.
https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread?view=net-5.0
I´ve also checked out the documentation... but honestly I think the documentation at microsoft is NOT for beginners. I find it very hard to understand.
I´ve might have been doing it all wrong, so don´t be hard on me, but please come with suggestions how I can improve.
So I want:
Background music playing and looping
Click sound every time you choose a menu option
I have:
Background music playing once (til the end of the file)
Click sound on the first menu option, there after it throws an exception (see above)
You should never, ever use Thread.Abort(). It just stops the thread in an "evil" way - by throwing an exception, and you never know what side effects that will have.
You need CancellationToken. Check out this article: https://learn.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads

How to play background music in C# Form FROM properties.resources simultaneously with other sounds

I'm new to C# and I'm making a mini-game. Playing sound effects is no problem, I can just use the System.Media.SoundPlayer class object to play a wav file streaming from, for example Properties.Resources.attack.wav, this is good but the background music will stop after I play the sound effect. Yes, I know there's Windows Media Player, but that uses URI, which I can't seem to add the resources directory there. I don't want to use local directory like #"D:\MyGame\backgroundmusic.wav" because I want to send it to a friend and can still hear the music. Is there any class or external sdk's that allow sound to be played simultaneously with other sounds FROM Properties.Resources? If none, what is the URI of the Resources folder inside a solution? Any help or advice would be awesome! Thank you.
edit: I already opened those links and tried them all several times. My main question is "How to play sound FROM the Resources Folder of the solution without other sounds interrupting it"
This is the concept:
private void Form_Load(object sender, EventArgs e)
{
var player = new System.Windows.Media.MediaPlayer();
player.Open(Properties.Resources.sfx_background);
player.Play();
}
private void attack()
{
SoundPlayer p1 = new SoundPlayer();
p1.Stream = Properties.Resources.sfx_sword;
p1.Play();
}
Where p1 plays synchronous with player, in which player gets the sound file from the Resources of the solution, not from a local storage of a computer.

How can I check if MediaPlayer has finished loading a sound?

I am trying to play multiple sounds at the same time for a simple game using the MediaPlayer class (System.Windows.Media.Mediaplayer).
To play the same sound multiple times at the same time, I created my own class, which loads the same sound many times.
Here is a short example:
sound = new MediaPlayer[count]; //array of MediaPlayers
//...
for (int a = 0; a < count; a++)
{
sound[a] = new MediaPlayer();
sound[a].Open(new System.Uri(sp + pfad)); //load sound
}
Here is my problem:
If I try to play a sound shortly after starting the game either I can't hear the sound or the beginning of the first sound I loaded will start playing (even if I tried to play a completely different sound).
It seems like all these MediaPlayers (I'm loading ~100) need some time to load the sounds.
Therefore I'm looking for a way to check if the loading is done.
Loading or playback? When the media has finished playback it rises the MediaEnded event, when buffering has finished it rises BufferingEnded event. MediaPlayer events.

Iterating through an array and play sound issue

I am traversing an array list of Music Notes object with the aim to play a whole stream of sound files all of each with a different duration.
The problem is that I can hear only just like a beep for each music note!!
The thread is going sleep for the length of the current MusicNote so I don't know why I am hearing only beeps!
//----------Play the whole list----------
public void PlayAll()
{
foreach (MusicNote m in list)
{
m.sp1.Stop();
m.sp1.Play();
Thread.Sleep(m.NoteDuration * 100);
}
}
Your posted code should work.You will just call that function on thread. if console there is no need for thread too
And here is your problem :
If the .wav file has not been specified or it fails to load, the Play
method will play the default beep sound.
SoundPlayer.Play documentation

Background audio not working in windows 8 store / metro app

I've tried setting background audio through both a mediaElement in XAML
<MediaElement x:Name="MyAudio" Source="Assets/Sound.mp3" AudioCategory="BackgroundCapableMedia" AutoPlay="False" />
And programmatically
async void setUpAudio()
{
var package = Windows.ApplicationModel.Package.Current;
var installedLocation = package.InstalledLocation;
var storageFile = await installedLocation.GetFileAsync("Assets\\Sound.mp3");
if (storageFile != null)
{
var stream = await storageFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
_soundEffect = new MediaElement();
_soundEffect.AudioCategory = AudioCategory.BackgroundCapableMedia;
_soundEffect.AutoPlay = false;
_soundEffect.SetSource(stream, storageFile.ContentType);
}
}
// and later...
_soundEffect.Play();
But neither works for me. As soon as I minimise the app the music fades out
akton replied to a similar question with this excellent answer
It wasn't easy to find initially as it doesn't use 'audio' in the title and I wasn't playing music. It's an excellent, comprehensive answer, the likes of which I love to see on StackExchange. It also mentions a few things other answers to similar questions had failed to point out. In brief
You need to handle the MediaControl events PlayPressed, PausePressed, PlayPausedTogglePressed and StopPressed, even if you have no buttons. EDIT: these events are required by Windows 8 app certification, make sure they actually work.
Add audio to the list of support background tasks in the applications manifest [see aktons answer for more detail]
However, in implementing this solution I did come across what I can only assume is a bug. I've built a kitchen timer within a UserControl. It plays an optional ticking sound as it counts down and then buzzes when elapsed. However, if the ticking sound is turned off before the timer is set, the buzz sound will not play. It seems that a Windows 8 app needs to play a sound before being minimised in order for background audio to work. To fix this, I created a silent audio file which is 1 second in duration. This file plays whether the ticking is on or off. It's a weird hack, and I hope I can figure out a better solution, but for now its all I can think of.

Categories

Resources