I am learning how to work with xAudio2. Made a simple application Windows 8 in Visual Studio 2012 Express For Windows 8.
Simple xAudio2 player class:
public class SoundEffect
{
readonly XAudio2 _xaudio;
readonly WaveFormat _waveFormat;
readonly AudioBuffer _buffer;
readonly SoundStream _soundstream;
SourceVoice sourceVoice;
public SoundEffect(string soundFxPath)
{
_xaudio = new XAudio2();
var masteringsound = new MasteringVoice(_xaudio);
var nativefilestream = new NativeFileStream(
soundFxPath,
NativeFileMode.Open,
NativeFileAccess.Read,
NativeFileShare.Read);
_soundstream = new SoundStream(nativefilestream);
_waveFormat = _soundstream.Format;
_buffer = new AudioBuffer
{
Stream = _soundstream.ToDataStream(),
AudioBytes = (int)_soundstream.Length,
Flags = BufferFlags.EndOfStream
};
//sourceVoice = null;
}
public void Play()
{
sourceVoice = new SourceVoice(_xaudio, _waveFormat, true);
if (sourceVoice != null)
{
sourceVoice.FlushSourceBuffers();
sourceVoice.SubmitSourceBuffer(_buffer, _soundstream.DecodedPacketsInfo);
sourceVoice.Start();
}
}
public void Stop()
{
sourceVoice.Stop();
}
}
And Xaml:
<Border Background="Gray" MinHeight="150" MinWidth="150" Margin="10,10,0,0" x:Name="A" PointerPressed="btnAPointerPressed" PointerReleased="btnAPointerReleased" />
and:
private SoundEffect shotEffect = new SoundEffect(#"sounds\mywav.wav");
private void btnAPointerPressed(object sender, PointerRoutedEventArgs e)
{
bool _hasCapture = ((Border)sender).CapturePointer(e.Pointer);
shotEffect.Play();
}
private void btnAPointerReleased(object sender, PointerRoutedEventArgs e)
{
((Border)sender).ReleasePointerCapture(e.Pointer);
shotEffect.Stop();
}
Tested in Windows 8 Simulator.
If I press one finger, then everything is fine.
When I click on the button - the sound plays when I let go of your finger - the sound stops.
If I click with two fingers and let go of both fingers, the sound continues to play. And the result is aliasing.
Called two events: btnAPointerPressed and two events: btnAPointerReleased but the sound continues to play. As if the audio stream freezes and continues to play. As if the audio stream freezes and continues to play.
I want to understand the problem haudio2? or I do not properly done something?
When you call Play() again - the previous SourceVoice gets replaced with a new one in your SoundEffect, but you never stop the old one. You should create a new SourceVoice with each touch, but keep them all associated with the pointer IDs so that we can stop each of them when the associated pointers are released.
Related
This Question is In reference with my previous question Embedding VLC player in WInform Application in .Net Core. Core.Intialize() Giving Exception
I want to run the player for certain time and during that time video should be on repeat. Currently code looks like this ...
Core.Initialize();
var libvlc = new LibVLC();
// Make VideoView control
VideoView vv = new VideoView();
vv.MediaPlayer = new MediaPlayer(libvlc);
vv.Dock = DockStyle.Fill;
// Add it to the form
Controls.Add(vv);
var uri = new Uri(#"C:\vid.3gp");
// Use command line options as Options for media playback (https://wiki.videolan.org/VLC_command-line_help/)
var media = new Media(libvlc, uri, ":input-repeat=65535");
vv.MediaPlayer.Play(media);
//Set fullscreen
this.FormBorderStyle = FormBorderStyle.None;
this.Size = Screen.PrimaryScreen.Bounds.Size;
this.Location = Screen.PrimaryScreen.Bounds.Location;
How I can close the player after certain time. currently even if I close the form with the player video keeps playing in background till I close the whole application.
Just to inform the this winform application is created in .netcore3.1.
Regards.
Create MediaPlayer as class field and call it to start/pause/stop it in you WinForm application.
private LibVLC _libVlc;
private MediaPlayer _mediaPlayer;
...
// Call this method in your constructor/initializer
private void StartMediaPlayer(string videoUrl)
{
using var media = new Media(_libVlc, new Uri(videoUrl), ":input-repeat=65535");
_mediaPlayer = new MediaPlayer(_libVlc)
{
Media = media
};
_mediaPlayer.Play();
}
// Method to stop media player
private void button1_Click(object sender, EventArgs e)
{
_mediaPlayer.Stop();
}
In my app there should normally be 2 sounds that overlap (a song and some short sounds). It works fine until from time to time the song suddenly stops playing. Do you know how I could solve this issue?
Here are the functions that I used for adding the songs and the sounds:
private void musical()
{
var p1 = new System.Windows.Media.MediaPlayer();
p1.Open(new System.Uri(#"J:\penalty\penalty\penalty\bin\Debug\Avicii - The Nights (Lyrics HD).wav"));
p1.Play();
}
private void happy()
{
System.Threading.Thread.Sleep(500);
var p2 = new System.Windows.Media.MediaPlayer();
p2.Open(new System.Uri(#"J:\penalty\penalty\penalty\bin\Debug\happy.wav"));
p2.Play();
}
private void sad()
{
System.Threading.Thread.Sleep(500);
var p2 = new System.Windows.Media.MediaPlayer();
p2.Open(new System.Uri(#"J:\penalty\penalty\penalty\bin\Debug\sad.wav"));
p2.Play();
}
If you don't store a reference to the MediaPlayers as field but only in local variables they are likely going to be gargabe collected. This might happen delayed as MediaPlayer uses unmanaged resources that would require a Dispose before being freed. To fix your problem consider storing a reference to the MediaPlayers in a field.
private System.Windows.Media.MediaPlayer _music;
private System.Windows.Media.MediaPlayer _happy;
private System.Windows.Media.MediaPlayer _sad;
and then adjust your methods to use the field instead.
private void musical()
{
_music = new System.Windows.Media.MediaPlayer();
_music.Open(new System.Uri(#"J:\penalty\penalty\penalty\bin\Debug\Avicii - The Nights (Lyrics HD).wav"));
_music.Play();
}
If you would like to repeat the audio (which does not work very well) you can subscribe the MediaEnded event in order set the position back to the beginning and start playing again.
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.
My code snippet below:
using (library = new MediaLibrary())
{
MediaPlayer.Play(library.Songs, 0);
}
and then my app user Interface is no longer responsive after playing the song. What can I do to fix this?
I found a solution, I used a dispatcher timer class like this:
private DispatcherTimer m_dispatcherTimer;
public MainPage()
{
InitializeComponent();
m_dispatcherTimer = new DispatcherTimer();
m_dispatcherTimer.Interval = TimeSpan.FromTicks(10000);
m_dispatcherTimer.Tick += frameworkDispatcherTimer_Tick;
m_dispatcherTimer.Start();
using (library = new MediaLibrary())
{
MediaPlayer.Play(library.Songs, 0);
}
}
void frameworkDispatcherTimer_Tick(object sender, EventArgs e)
{
FrameworkDispatcher.Update();
}
and everything worked just fine. ;)
i need to know how to save a sound stream in a file on the fly after record
this is my code, that i need to save an external file wav or smth.
so at that point here there are record button play button and play objects
private void recordButton_Click(object sender, EventArgs e)
{
// Get audio data in 1/2 second chunks
microphone.BufferDuration = TimeSpan.FromMilliseconds(500);
// Allocate memory to hold the audio data
buffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)];
// Set the stream back to zero in case there is already something in it
stream.SetLength(0);
// Start recording
microphone.Start();
SetButtonStates(false, false, true);
UserHelp.Text = "recording";
// StatusImage.Source = microphoneImage;
}
private void playButton_Click(object sender, EventArgs e)
{
if (stream.Length > 0)
{
// Update the UI to reflect that
// sound is playing
SetButtonStates(false, false, true);
UserHelp.Text = "play";
// Play the audio in a new thread so the UI can update.
Thread soundThread = new Thread(new ThreadStart(playSound));
soundThread.Start();
}
}
private void playSound()
{
// Play audio using SoundEffectInstance so we can monitor it's State
// and update the UI in the dt_Tick handler when it is done playing.
SoundEffect sound = new SoundEffect(stream.ToArray(), microphone.SampleRate, AudioChannels.Mono);
soundInstance = sound.CreateInstance();
soundIsPlaying = true;
soundInstance.Play();
}
You need to build the .wav header properly and then write the audio stream.
Check this example