Can't play .wav file with audioplayer xamarin forms - c#

I'm using audio recorder plugin package to record and play audio in Xamarin.Forms Android application.
here is my code in mypage.cs:
private static readonly AudioRecorderService recorder = new AudioRecorderService
{
StopRecordingOnSilence = false,
StopRecordingAfterTimeout = false,
FilePath = "/storage/emulated/0/Android/data/com.companyname.projectname/" + Guid.NewGuid().ToString()+".wav"
};
public RecordPage()
{
InitializeComponent();
}
private async void Button_Clicked(object sender, EventArgs e)
{
await recorder.StartRecording();
}
private async void Button_Clicked2(object sender, EventArgs e)
{
await recorder.StopRecording();
}
private void Button_Clicked3(object sender,EventArgs e)
{
AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.Play(recorder.GetAudioFilePath());
}
there is no issue with recording audio. the audio will record, save and play in system music players.
but when I want to play it with AudioPlayer class, it doesn't play anything. also there are no exception throws. I tried to play some audios with the .mp3 extension and it's working for them. also, it's working for .wav files which they're converted from .mp3 to .wav.
it has a problem just with the audios recorded by AudioRecorderService
please someone help me!
thank you
-- notice the anroid device I'm testing on it is xiaomi poco x3 NFC, Android v-11
edit :
Xiaomi was the reason of this problem. it's working with other devices.

Related

No audio with WAV and MediaPlayer in WPF

I'm trying to add background music to my WPF program. I also want additional sounds to happen "over" the background music. I tried using a SoundPlayer however, this could only play one piece of audio at once.
I am now trying to use MediaPlayer but I cannot get any audio to play. Here is my code:
In my ShellViewModel I start the background music:
Sounds.StartBackgroundMusic()
In my sounds class I have the following:
private static MediaPlayer _backgroundMusic = new MediaPlayer();
public static void StartBackgroundMusic()
{
_backgroundMusic.Open(new Uri("pack://application:,,,/Assets/Sounds/backgroundmusic.wav"));
_backgroundMusic.MediaEnded += new EventHandler (BackgroundMusic_Ended);
_backgroundMusic.Play();
}
private static void BackgroundMusic_Ended(object sender, EventArgs e)
{
_backgroundMusic.Position = TimeSpan.Zero;
_backgroundMusic.Play();
}
Since I want the background music to loop continuously, I used the answer in this question to add the BackgroundMusic_Ended event. Can someone please help shed some light on why my audio isn't playing?
I tried to reproduce the problem but it worked as expected.
I created a new WPF application in Visual Studio and used the following code in MainWindow.xaml.cs:
using System;
using System.Windows;
using System.Windows.Media;
namespace WpfApp1
{
public partial class MainWindow : Window
{
private static MediaPlayer _backgroundMusic = new MediaPlayer();
public MainWindow()
{
InitializeComponent();
StartBackgroundMusic();
}
public static void StartBackgroundMusic()
{
_backgroundMusic.Open(new Uri(#"C:\<path-to-sound-file>\music.wav"));
_backgroundMusic.MediaEnded += new EventHandler(BackgroundMusic_Ended);
_backgroundMusic.Play();
}
private static void BackgroundMusic_Ended(object sender, EventArgs e)
{
_backgroundMusic.Position = TimeSpan.Zero;
_backgroundMusic.Play();
}
}
}
Did you try to use a "regular" file path to load a sound file instead of "pack://..."? When I used the wrong path I didn't get any sound and there was no error message or exception.
Since I couldn't use MediaPlayer to play embedded resources and SoundPlayer can only play one sound at a time, I used a combination of them and saved the embedded background music resource to disk so that MediaPlayer could play it. I make a blog about it here
Heres what I did:
I set up my SoundPlayer as this was the simplest one of the two. I created a new SoundPlayer object using the embedded resource
private static readonly SoundPlayer _soundOne = new SoundPlayer(WPF.Properties.Resources.soundOne);
Now the MediaPlayer. I make sure that my audio file is set as an Embedded Resource under the Build Actions in the file’s properties in Visual Studio. Now that we have done this, we can create the method for saving the embedded WAV file to the %temp% location on disk:
public static void SaveMusicToDisk(){
//This sets up a new temporary file in the %temp% location called "backgroundmusic.wav"
using (FileStream fileStream = File.Create(Path.GetTempPath() + "backgroundmusic.wav")){
//This them looks into the assembly and finds the embedded resource
//inside the WPF project, under the assets folder
//under the sounds folder called backgroundmusic.wav
//PLEASE NOTE: this will be different to you
Assembly.GetExecutingAssembly().GetManifestResourceStream("WPF.Assets.Sounds.backgroundmusic.wav").CopyTo(fileStream);
}
}
We play this by creating a new MediaPlayer object and using the temp file location to play the audio:
//Create a new MediaPlayer object
private static readonly MediaPlayer _backgroundMusic = new MediaPlayer();
public static void StartBackgroundMusic(){
//Open the temp WAV file saved in the temp location and called "backgroundmusic.wav"
_backgroundMusic.Open(new Uri(Path.Combine(Path.GetTempPath(), "backgroundmusic.wav")));
//Add an event handler for when the media has ended, this way
//the music can be played on a loop
_backgroundMusic.MediaEnded += new EventHandler(BackgroundMusic_Ended);
//Start the music playing
_backgroundMusic.Play();
}
My BackgroundMusic_Ended method looks like this and just makes sure that the music is always restarted once it has finished:
private static void BackgroundMusic_Ended(object sender, EventArgs e){
//Set the music back to the beginning
_backgroundMusic.Position = TimeSpan.Zro;
//Play the music
_backgroundMusic.Play();
}
Then I just had to worry about disposing of the objects and cleaning up the temp file when the program is closing.

MediaElement is refusing to loop

So I was trying to loop Background music in my UWP App, I have a class called soundControl that handles music and sounds like this:
public class soundControl
{
private static MediaElement loop = new MediaElement();
public static async void stopLoop()
{
loop.Stop();
}
public static async void loadLoopTimeBG()
{
Windows.Storage.StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync(#"Assets\Sounds");
Windows.Storage.StorageFile file = await folder.GetFileAsync("battle.wav");
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
loop.AutoPlay = false;
loop.SetSource(stream, file.ContentType);
loop.IsLooping = true;
}
public static void loopTimeBG()
{
loop.Play();
}
And whenever I want to play this music I call :
soundControl.loadLoopTimeBG();
soundControl.loopTimeBG();
the problem is the it plays just one time and stops and I have no Idea why
I tried another approach like:
loop.MediaEnded += mediaEnded;
and the event handler like this:
private static void mediaEnded(object sender, RoutedEventArgs e)
{
loop.Position = TimeSpan.Zero;
loop.Play();
}
it also didn't work and when debugging it doesn't even triger the mediaEnded event when music is complete.
Any help here would be most appreciated.
Thanks
MediaPlayer
Windows.Media.Playback.MediaPlayer is the recommended player for UWP that does not require to be in the XAML visual tree.
Its API is very similar to MediaElement:
private static MediaPlayer _mediaPlayer = new MediaPlayer();
public static async Task PlayUsingMediaPlayerAsync()
{
Windows.Storage.StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync(#"Assets");
Windows.Storage.StorageFile file = await folder.GetFileAsync("Click.wav");
_mediaPlayer.AutoPlay = false;
_mediaPlayer.Source = MediaSource.CreateFromStorageFile(file);
_mediaPlayer.MediaOpened += _mediaPlayer_MediaOpened;
_mediaPlayer.IsLoopingEnabled = true;
}
private static void _mediaPlayer_MediaOpened(MediaPlayer sender, object args)
{
sender.Play();
}
You can even display the visuals of a MediaPlayer in XAML using MediaPlayerElement.
MediaPlayer allows for even more advanced playback scenarios using the MediaPlaybackList with support for looping, shuffle and gapless playback.
mediaElement.SetPlaybackSource(mediaPlaybackList);
MediaElement
After some digging around it seems that there are two issues.
MediaElement is XAML based control (in the Windows.UI.Xaml.Controls namespace), and it seems that it does not work properly until it is actually attached to a visual tree. Once you put the MediaElement on the page, it works as expected.
Secondly, loading source media does not happen immediately. Once you set the source, the control needs some time to actually load the media. For this purpose, you can use the MediaOpened event, that will notify you once it is really loaded.
So the code could look somewhat like this:
public static async Task LoadAndPlayAsync()
{
Windows.Storage.StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync(#"Assets");
Windows.Storage.StorageFile file = await folder.GetFileAsync("Click.wav");
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
loop.AutoPlay = false;
loop.SetSource(stream, file.ContentType);
//or simpler -
//loop.Source = new Uri("ms-appx:///Assets/Click.wav", UriKind.Absolute);
loop.MediaOpened += Loop_MediaOpened;
loop.IsLooping = true;
}
private static void Loop_MediaOpened(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
//play once the media is actually ready
loop.Play();
}
And before you call the LoadAndPlayAsync method, you have to attach the control somewhere (for example in a Grid):
GridContainer.Children.Add(SoundController.loop);
await SoundController.LoadAndPlayAsync();
I have created a sample project for my tests on my GitHub, you can check it out to see how I implemented it. The first button in the app attaches the control and the second loads and plays the sound. You can see that if you click only the second one, the sound does not play.

Play sound in Combobox in C#

I'm new in C# programming, I created a combobox with items and I want that items to play sound when i chose one, like this,
or that.
I'm using Visual Studio 2015.
Could would be in methods play1 and play2
private void AudioComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (AudioComboBox.SelectedIndex == AudioComboBox.Items.IndexOf("Sali 3la Mohammed 1"))
{
play1();
}
else if (AudioComboBox.SelectedIndex == AudioComboBox.Items.IndexOf("Sali 3la Mohammed 2"))
{
play2();
}
}
private void play1()
{
}
private void play2()
{
}
You can use MediaElement or the new AudioGraph to play sounds in UWP.
MediaElement is the simpler approach, which has the disadvantage of causing the music stop on Mobile devices, so it is really not too appropriate your purpose.
MediaElement player = new MediaElement();
var stream = await yourSoundFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
player.SetSource(stream, file.ContentType);
player.Play();
AudioGraph is specifically created for sound effects in UWP apps and is the best choice for you. There is a quick and simple tutorial on Loek van den Ouweland's blog, so I definitely recommend you to check it out. Basically you need to create an AudioGraph instance and with it AudioFileInputNodes for each of the sounds you need.
This should work
private void AudioComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (AudioComboBox.SelectedIndex == AudioComboBox.Items.IndexOf("Sali 3la Mohammed 1"))
{
play1();
}
else if (AudioComboBox.SelectedIndex == AudioComboBox.Items.IndexOf("Sali 3la Mohammed 2"))
{
play2();
}
}
private void play1()
{
SoundPlayer simpleSound = new SoundPlayer("sound1.wav");
simpleSound.Play();
}
private void play2()
{
SoundPlayer simpleSound = new SoundPlayer("sound2.wav");
simpleSound.Play();
}

Vlc.DotNet - Not able to set the volume before playing an audio

I downloaded the Vlc.DotNet project from Github and have been adding more functionalities to its Sample Forms application. Everything goes fine, except on thing: I noticed that every time I start the application and play an audio, the audio sounds like its volume is 100% (or something around that) - even after I set it to a lower value.
I tried setting the volume before playing the audio, but it didn't work.
If I debug the code, I see that the volume is always set to -1.
For instance, if I execute the following lines of code, after setting the volume to 40, when I debug it, the volume is still -1:
myVlcControl.Play(new FileInfo(FileName));
myVlcControl.Audio.Volume = 40;
Change the order of the lines above also doesn't work.
The funny thing is, when the audio is already playing and I change the volume,it is successfully changed to the select value on the NumericUpDown. The code below is the event where this happens:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
myVlcControl.Audio.Volume = (int)numericUpDown1.Value;
}
I've been trying to solve this problem for two days now. Unfortunately, my coding skills are not even close the people behind this project. I have already posted this problem on their Issues page on Github, but since there are questions since November without replies, I decided to try the StackOverflow. Hopefully someone here uses Vlc.DotNet and have a solution for my problem.
That being said:
Does anyone have the same problem?
Does anyone know how to solve it?
Any suggestions?
Thanks!
[EDIT on Jan 8, 2016, 11:50 AM GMT-2]
The user higankanshi on Github answered me the following:
I have found the problem.
You should use LibVlc 2.2.0(or later).
Vlc.DotNet is using LibVlc 2.1.5
Then, I executed some tests and came to the following conclusions:
You're right. Using the LibVlc 2.2.0 I'm able to set the Volume before playing.
Unfortunately, for some reason, setting the volume before playing the audio only works on the first time the application is opened. After stopping the audio, changing the volume, and playing it again, the volume doesn't change anymore - only changes while playing.
Here are the steps with results:
Execute the application;
Change the volume at run time before playing an audio file;
Play the audio file;
RESULT: the audio plays at the specified volume, successfully! =)
Press Stop;
Change the volume again;
Press Play again (at this point, the implementation inside the play method should get the new volume information);
RESULT: the audio plays again at the same volume it played before. Setting the volume doesn't work anymore.
I'm doing my tests on the Vlc.DotNet.Forms.Samples - CLR 4 - .Net 4.5 project. The changes I've made to the project were:
Added a NumericUpDown control, so that I could change the volume at run time;
Associated the ValueChanged event to the NumericUpDown control, so that every time it changes the value, the new value is passed to the VlcControl;
Created a Play() function that always gets the last volume value before playing the audio;
My code is below:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
myVlcControl.Audio.Volume = (int)numericUpDown1.Value;
}
private void Play()
{
myVlcControl.Audio.Volume = (int)numericUpDown1.Value;
myVlcControl.Play(new FileInfo(FileName));
}
private void OnButtonPlayClicked(object sender, EventArgs e)
{
Play();
}
private void OnButtonStopClicked(object sender, EventArgs e)
{
myVlcControl.Stop();
}
private void OnButtonPauseClicked(object sender, EventArgs e)
{
myVlcControl.Pause();
}
Any ideas?
I have found working solution:
int volume { get; set; }
public Constructor(){
InitializeComponent();
myVlcControl.VideoOutChanged += myVlcControl_VideoOutChanged;
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
this.volume = (int)numericUpDown1.Value;
myVlcControl.Audio.Volume = volume;
}
void vlcPlayer_VideoOutChanged(object sender, VlcMediaPlayerVideoOutChangedEventArgs e)
{
myVlcControl.Audio.Volume = volume;
}
This seems to work for both file and stream.
How would this work. Default 40, if you need volume changed at start of playback:
myVlcControl.Audio.Volume = volume;
and add basic function to MediaChanged event to verify that volume is always correct. Also, might be good idea to add slider from 0-200 and default is to 40 -> ValueChanged event -> volume = volumeSlider.Value;
private static int volume = 40;
private void volume_changer(int vol)
{
volume = vol;
}
private void preview_Player_MediaChanged(object sender, Vlc.DotNet.Core.VlcMediaPlayerMediaChangedEventArgs e)
{
preview_Player.Audio.Volume = volume;
}
My working solution is same as Marcin Bigorge explained above.
vlcControl.TimeChanged += vlcControl_VideoOutChanged;
private void vlcControl_VideoOutChanged(object sender, VlcMediaPlayerTimeChangedEventArgs e)
{
vlcControl.Audio.Volume = volume;
}

Play audio from Assets folder in W10 universal app

I have several .wav and .mp3 files in my app under Assets/Audio, and I'm trying to play them when something is tapped in the UI. I've written the following code (with the file name hardcoded for testing purposes), but when the function is triggered, no sound plays. If I replace attempting to play from a file to playing an audio stream created by Windows.Media.SpeechSynthesis.SpeechSynthesizer, everything works fine.
private async void SoundItem_Tapped(object sender, TappedRoutedEventArgs e)
{
ListViewItem soundItem = sender as ListViewItem;
if (soundItem.IsSelected)
{
Uri sourceUri = new Uri(String.Format("ms-appx:///Assets/Audio/151Cry.wav", UriKind.Absolute));
await PlayAudio(sourceUri, soundItem);
}
else if (inUsePlayers.ContainsKey(soundItem))
{
MediaElement player = inUsePlayers[soundItem];
player.Stop();
inUsePlayers.Remove(soundItem);
players.Enqueue(player);
}
else
{
}
}
private async Task PlayAudio(Uri sourceUri, ListViewItem soundItem)
{
MediaElement player = RequestPlayer(soundItem);
player.Source = sourceUri;
player.IsLooping = true;
await player.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
player.Stop();
player.Play();
});
}
Here's the location of the file within the tree:
Aside from dragging the sound files into the project, I've haven't done anything. Maybe they need to be added to a resource file or copied to the output folder as well? I expected that something would throw an exception if the item pointed to by the URI didn't exist, but nothing's being thrown, even when I give it a bogus filename.
You need to do following things to play you media element.
Your resource files should be set to "Copy to Output directory"
value to "Copy if newer" or "Copy always". to do this right
click your resource file go to Properties and set Copy to Output directory value to Copy always and Build action to
content
Your player(MediaElement) should be added somewhere to View xaml
tree. I do not know your RequestPlayer method is adding
mediaEelement to view xaml or not. e.g
layoutRoot.Children.Add(player)
You need to register Player_MediaOpened event to play your
audio file. If you call 'play' before player is opened media will
not play the sound... and if you want that if any thing is happend
to your player not playing than register Player_MediaFailed it
will give you the reason why it is filed to play.
here is the code.
private async Task PlayAudio(Uri sourceUri, ListViewItem soundItem)
{
MediaElement player = RequestPlayer(soundItem);
player.IsLooping = true;
player.AutoPlay = false;
player.MediaOpened += Player_MediaOpened;
player.MediaFailed += Player_MediaFailed;
player.Source = sourceUri;
player.IsLooping = true;
//Add media element to xaml tree if not added by your RequestPlayer Method..
this.LayoutRoot.Children.Add(player);
}
private void Player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
{
}
private async void Player_MediaOpened(object sender, RoutedEventArgs e)
{
await player.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
player.Play();
});
}
Hope this helps...

Categories

Resources