I a Windows 8 Metro App (C#/XAML):
How can I trigger the same sound effect twice so that it plays simultaneously.
The second play should start before the first has finished.
Related questions are:
Playing two sounds simultaneously c#
and Play two sounds simultaneusly
I found this class for XNA which does what I want, but is not available under Metro:
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.soundeffectinstance.aspx
Just create a separate media element for every sound effect.
(not sure I need to relocate the file every time)
public async void PlayLaserSound()
{
var package = Windows.ApplicationModel.Package.Current;
var installedLocation = package.InstalledLocation;
var storageFile = await installedLocation.GetFileAsync("Assets\\Sounds\\lazer.mp3");
if (storageFile != null)
{
var stream = await storageFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
MediaElement snd = new MediaElement();
snd.SetSource(stream, storageFile.ContentType);
snd.Play();
}
}
Related
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
I am trying to track the changes of the pictures library because I want my app to upload new photos to to a server. To track the changes I followed the MSDN article over here https://msdn.microsoft.com/en-us/magazine/mt790201.aspx
If I run my code on my phone (Windows 10 Mobile with Fall Creators Update) it does not work if the pictures are saved to the sd-card. But if remove the sd-card and reboot my phone I can read the changes from the change-tracker. On a Desktop-PC everything works fine.
This is how I enable the background task for the change-tracker:
public async Task Register()
{
// Check if your app has access to the background
var requestStatus = await BackgroundExecutionManager.RequestAccessAsync();
if (!(requestStatus ==
BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity ||
requestStatus == BackgroundAccessStatus.AllowedSubjectToSystemPolicy ||
requestStatus ==
BackgroundAccessStatus.AllowedWithAlwaysOnRealTimeConnectivity ||
requestStatus == BackgroundAccessStatus.AlwaysAllowed))
{
Debug.WriteLine("Failed to get access to the background");
return;
}
// Build up the trigger to fire when something changes in the pictures library
var builder = new BackgroundTaskBuilder();
builder.Name = "Photo Change Trigger";
StorageLibrary picturesLib =
await StorageLibrary.GetLibraryAsync(KnownLibraryId.Pictures);
var picturesTrigger = StorageLibraryContentChangedTrigger.Create(picturesLib);
// We are registering to be activated in OnBackgroundActivated instead of
// BackgroundTask.Run; either works, but I prefer the single-process model
builder.SetTrigger(picturesTrigger);
BackgroundTaskRegistration task = builder.Register();
}
And this is how I get the changes, which contains the code that does not work:
public async Task GetChanges()
{
StorageLibrary picturesLib =
await StorageLibrary.GetLibraryAsync(KnownLibraryId.Pictures);
StorageLibraryChangeTracker picturesTracker = picturesLib.ChangeTracker;
picturesTracker.Enable();
StorageLibraryChangeReader changeReader = picturesTracker.GetChangeReader();
// if photos are saved on the SD-card the next line does not work
IReadOnlyList<StorageLibraryChange> changes = await changeReader.ReadBatchAsync();
}
Am I doing something wrong or is this a bug in Windows 10 Mobile? I already tried to factory reset my device or reformatting my SD-Card, but nothing worked.
As described in the official blogpost:
Calling Enable()
It’s mentioned above, but just to make sure that it is clear: Apps should call ChangeTracker.Enable() as soon as they start tracking the file system and before every enumeration of the changes. This will ensure that the change tracker is not going to miss changes to the folders included in the library.
So I would suggest to call the Enable in the Register method as well, right after the task is registered.
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
I am a beginner and a student who is just introduced to the WP app development, and as for my first project, I decided to build a very simple camera app, with limited functionality. So far, I have my GUI ready, and my question is, how do I activate the main camera ( or switch between the front and the main cameras )? This is my code on the OnNavigatedTo section which opens up the front camera of the phone.
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
Windows.Phone.UI.Input.HardwareButtons.BackPressed += BackButtonPress;
media = new MediaCapture();
await media.InitializeAsync();
////rotation
media.SetPreviewRotation(VideoRotation.Clockwise270Degrees);
// VideoRotation previewRotation = media.GetPreviewRotation();
////start Capture preview
////capturePreview is a CaptureElement defined in XAML.
this.capPrev.Source = media;
await media.StartPreviewAsync();
}
I might be missing a simple line of code, that I am not aware of. My app right now launches the front camera instead of the main. What should I do to switch to the main camera? (I have the switch button ready on the appbar, which currently does nothing).
Thank you
Welcome to Stackoverflow.
First I didn't get what you wrote in your code.
Here is the Sample & article for your requirement
Still if you face any issue please be specify your problem.
Best of luck
You can enumerate cameras using below given line.
var set = new MediaCaptureInitializationSettings();
var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
set.VideoDeviceId = devices[0].Id; // You should choose any value from devices collection
media = new MediaCapture();
await media.InitializeAsync(set);
Don't forget to dispose camera in OnNavigatedFrom event.
protected async override void OnNavigatedFrom(NavigationEventArgs e)
{
await _camCapture.StopPreviewAsync();
media.Dispose();
}
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.