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
Related
I have a problem with my windows phone 8.1 app. I works fine until i turn on the lock screen, using power button.
It keeps running like its supposed to - but no longer plays the .wav files it´s supposed to.
I have set breakpoints at the methods responsible for playing the sounds, and it seems to run at it should.. Everything else works, all the timer threads and so forth.
I´m using MediaElements to play the sounds, and i have set the properties to
snd.AudioCategory = Windows.UI.Xaml.Media.AudioCategory.BackgroundCapableMedia;
I have also enabled the background audio task in the Package.appmanifest.
I have tried a lot of stuff including adding this code :
Microsoft.Phone.Shell.PhoneApplicationService.Current.ApplicationIdleDetectionMode =
Microsoft.Phone.Shell.IdleDetectionMode.Enabled;
This dosent work however, since it wont recognize the namespace.. Apparently its not used in 8.1 but only 8.0.
This is the method used to play audio :
public async void CountDownFromThree()
{
MediaElement snd = null;
snd = SourceGrid.Children.FirstOrDefault(m => (m as MediaElement) != null) as MediaElement;
if (snd == null)
{
snd = new MediaElement();
SourceGrid.Children.Add(snd);
}
StorageFolder folder = await Package.Current.InstalledLocation.GetFolderAsync(#"Assets\SoundsFolder");
StorageFile file = await folder.GetFileAsync("start-beeps.wav");
var stream = await file.OpenAsync(FileAccessMode.Read);
snd.SetSource(stream, file.ContentType);
snd.MediaEnded += snd_MediaEnded;
snd.Play();
}
Ok. So it seems that in windows phone 8.1, BackgroundMediaPlayer is the way to go. I´ve completely removed all MediaElements - which IMHO having to be part of the visual tree - was pretty wierd afterall.
I found a few resources that helped me, links are below.
http://www.jayway.com/2014/04/24/windows-phone-8-1-for-developers-the-background-media-player/
This codesample helped me a lot, it could be boiled down to very few lines of code for my intended purpose :
https://code.msdn.microsoft.com/windowsapps/BackgroundAudio-63bbc319
Heey,
We created a game with Monogame but we got the following problem.
We got a themesong that plays when you have loaded the game now is the problem that the themesong sometimes plays but sometimes just doesn't. We convert it by the XNA pipeline to a wma and load it into our game with the .xnb together but just sometimes the music doesn't wanna start.
We just use the standard code for starting a song and all of this code does fire.
internal void PlayBackgroundMusic()
{
if (MediaPlayer.GameHasControl)
{
MediaPlayer.Volume = mainVolume;
MediaPlayer.Play(backgroundMusic);
MediaPlayer.IsRepeating = true;
}
}
We also use SoundEffects but these work 100% of the time it's only the song that won't play everytime you start. Windows RT runs it fine by the way.
Make sure that the debugger gets into the if statement through debugging (or remove the statement temporarily). Another possibility might be that the function is running before the game is fully initialized. You could try delaying the function until the game has been fully loaded.
PS: I can't comment on questions yet so here's an answer.
Edit:
Alright, after some messing around with the Song class and looking in the implementation in MonoGame I came to the conclusion that the SoundEffect class is easier to use and better implemented.
backgroundSound = Content.Load<SoundEffect>("alarm");
protected override void BeginRun()
{
// I created an instance here but you should keep track of this variable
// in order to stop it when you want.
var backSong = backgroundSound.CreateInstance();
backSong.IsLooped = true;
backSong.Play();
base.BeginRun();
}
I used this post: using BeginRun override to play the SoundEffect on startup.
If you want to play a song, use the Song class. But make sure you are using ".mp3" instead of ".wma" before converting them into ".xnb".
backgroundMusic = Content.Load<Song>("MainTheme");
MediaPlayer.Play(backgroundMusic);
MediaPlayer.IsRepeating = true;
See MSDN.
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.
I have a medialement with a url-source which streams a radio station. Everything works fine and music plays as expected! When I press the shutdown button and the phone locks, the streaming stops. How can I fix that? Even if I press the "flag" button, I see my main screen but the music stops :/
thanks in advance
You must use the BackgroundAudioPlayer to accomplish this.
See this msdn article for more info and my post explaining some gotchas of the BackgroundAudioPlayer
Taking the sample from the msdn link. I changed the PlayTrack method to:
private void PlayTrack(BackgroundAudioPlayer player)
{
var track = new AudioTrack(
new Uri("http://m1.onweb.gr/1055rock"),
"Online",
"Music",
string.Empty,
null,
string.Empty,
EnabledPlayerControls.Pause);
if (player != null)
{
player.Track = track;
}
}
And I get the errors noted below. How are you trying to start the player?
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.