I have an instrument application that running with XNA Sound Effect. My problem is that;
When I play a sound effect while another one is playing, the last one is killing the first one. It is not what I want, I want to play sounds asynchronously even they are the same sounds too. What can I do about it?
Thanks for your help.
public static SoundEffectInstance passSound;
public static SoundEffect passSound;
LoadSoundInstance("Assets/SoundEffects/passSound.wav", out passSound, out passSoundInstance);
private void LoadSound(String SoundFilePath, out SoundEffect Sound)
{
// For error checking, assume we'll fail to load the file.
Sound = null;
try
{
// Holds informations about a file stream.
StreamResourceInfo SoundFileInfo = App.GetResourceStream(new Uri(SoundFilePath, UriKind.Relative));
// Create the SoundEffect from the Stream
Sound = SoundEffect.FromStream(SoundFileInfo.Stream);
}
catch (NullReferenceException)
{
// Display an error message
MessageBox.Show("Couldn't load sound " + SoundFilePath);
}
}
private void LoadSoundInstance(String SoundFilePath, out SoundEffect Sound, out SoundEffectInstance SoundInstance)
{
// For error checking, assume we'll fail to load the file.
Sound = null;
SoundInstance = null;
try
{
LoadSound(SoundFilePath, out Sound);
SoundInstance = Sound.CreateInstance();
}
catch (NullReferenceException)
{
// Display an error message
MessageBox.Show("Couldn't load sound instance " + SoundFilePath);
}
}
I am using it with only play;
public void PlaySound(SoundEffectInstance sound)
{
sound.Play();
}
If I call PlaySound method while the same sound is playing it is not play the new one.
Related
I have a simple goal for my Unity application running on Android: create a function, which disables my GUI, creates a screenshot, stores the image and enables the GUI again.
This is my current code:
The whole UI is stored in a GameObject which my handler class holds as property:
private bool makeScreenshotFlag;
public GameObject UserInterface;
makeScreenshotFlag above is used in the Update function:
// Update is called once per frame
void Update()
{
if (makeScreenshotFlag)
{
// Working with this flag is necessary,
// since we need to wait for the next frame,
// where the gui is not visible;
MakeScreenShot();
}
}
If the corresponding button gets pressed I fire the following Method:
public void OnCreateScreenshotButtonPressed()
{
UserInterface.SetActive(false);
makeScreenshotFlag = true;
}
And at last the method for the screenshot itself:
private void MakeScreenShot()
{
if (UserInterface.activeSelf) return; // wait for the next frame if the gui is still active
try
{
string filename = "screenshot_" + DateTime.Now.ToString("HH-mm-ss--dd-MM-yyyy") + ".png";
ScreenCapture.CaptureScreenshot(filename);
}
catch (Exception e)
{
DebugHelper.NewLog = "Error capturing screenshot: " + e.Message;
}
finally
{
makeScreenshotFlag = false;
UserInterface.SetActive(true);
}
}
In theory this should work, however the documentation for ScreenCapture.CaptureScreenshot() states the following:
The CaptureScreenshot returns immediately on Android. The screen capture continues in the background. The resulting screen shot is saved in the file system after a few seconds.
In practice this means, when my screenshot is made, the GUI is already enabled again. So far I couldn't find any event or similar to get notified as soon as the screenshot is made. The only thing I can think of is to store the screenshot filename and check if the file exists each frame after the screenshot is started.
Is there any other, more practical way?
Most probably, you are capturing the frame with UI itself. It's better to wait till the end of the frame using Coroutine.
public IEnumerator MakeScreenShot()
{
// Wait till the last possible moment before screen rendering to hide the UI
yield return null;
// Disable UI
UserInterface.SetActive(false);
// Wait for screen rendering to complete
yield return new WaitForEndOfFrame();
// Take screenshot
Application.CaptureScreenshot("screenshot.png");
// Show UI after we're done
UserInterface.SetActive(true);
}
i am making a quiz and in each form i have background music and if they get an answer correct i want to play a sound effect. When i do this is stops the background music and plays the sound effect then no sound is playing, does anyone know how do it?
public static System.Media.SoundPlayer player = new System.Media.SoundPlayer();
public static void sound(string form)
{
switch (form)
{
case "Login":
player.Stop();
player.Stream = Properties.Resources._2marioloadscreen;
player.PlayLooping();
break;
}
}
Here's an example of how to do it, assuming you have two wav files (one for background music, and one for the correct answer sound effect). The key is to know when the sound effect is done playing, then continue with the background music again.
I wrote it as a simple C# Console App.
class Program
{
private static SoundPlayer player;
static void Main(string[] args)
{
using (player = new SoundPlayer())
{
player.SoundLocation = "bkgnd.wav";
player.PlayLooping();
Console.WriteLine("bkgnd.wav is now playing in a loop. (Hit ENTER key to start the hoorayyouwon.wav)");
Console.ReadLine();
Console.WriteLine("hoorayyouwon.wav is now playing.");
player.Stop();
player.SoundLocation = "hoorayyouwon.wav";
player.PlaySync(); // this ensures the hoorayyouwon.wav plays completely before it gets to the next line of code.
Console.WriteLine("bkgnd.wav is now continuing (actually, starting over). (Hit ENTER key to exit)");
player.SoundLocation = "bkgnd.wav";
player.PlayLooping();
Console.ReadLine();
}
}
}
I am using timer to connect several audio files together. There are a list of audio files and the timer will read files one by one. Once there is an audio read, it will be played. The goal is to play the audio file right after the previous one when it is finished(without any break).
(I am using Naudio)
Here is the code:
private void timer_key_Tick(object sender, EventArgs e)
{
if(!isPlaying)
{
//play the current audio
DirectSoundOut dso = sounds2[key_indexer];
dso.Play();
targetMusics.Add(dso);
}
else
{
foreach (DirectSoundOut dso in targetMusics)
{//stop the current audio
dso.Stop();
}
targetMusics.Clear();
key_indexer++; //switch to the next audio
if (key_indexer >= myMT.Keys.Count)
{
key_indexer = 0;
timer_key.Stop();
}
}
isPlaying = !isPlaying;
}
However, the fact is, when the first music finished, the second one didn't play at once. It comes after one second break. Is this the problem about timer itself? How should I change it?
Thanks for the help from #HansPassant. I made a mistake about logic in this timer. Here is the correct code after I applied his suggestion:
//stop the current playing
foreach(DirectSoundOut d in targetMusics)
{
d.Stop();
}
targetMusics.Clear();
//stop the entire process
if (key_indexer >= myMT.Keys.Count)
{
key_indexer = 0;
timer_key.Stop();
}
else
{ //play the current audio
DirectSoundOut dso = sounds2[key_indexer];
targetMusics.Add(dso);
dso.Play();
key_indexer++;
}
So I am doing a simple piano and trying to traverse the collection where I stored the notes, but the SoundPlayer doesn't want to play them properly in "without debugging mode", playing only the last one. However when I put a breakpoint there it plays all of them
public static List<MusicNote> music = new List<MusicNote>(15);
public static void PlayAll()
{
SoundPlayer sp = new SoundPlayer();
for (int i = 0; i <= music.Count - 1; i++)
{
string text = music[i].pitch.ToString();
sp.SoundLocation = (#"c:\my path here\" + text + ".wav");
sp.Play();
sp.Stop();
}
}
Pitch is simply ordinal number to link to file.
Thanks in advance
U better use PlaySyn in order to tell your program to wait until the music complete
// Create new SoundPlayer in the using statement.
using (SoundPlayer player = new SoundPlayer())
{
for (int i = 0; i <= music.Count - 1; i++)
{
string text = music[i].pitch.ToString();
sp.SoundLocation = (#"c:\my path here\" + text + ".wav");
// Use PlaySync to load and then play the sound.
// ... The program will pause until the sound is complete.
player.PlaySync();
}
}
I think its better when you use PlaySync(); instead of Play();
Because then you don't need the Stop() methode.
Here a link to the docu of SoundPlayer
Why use PlaySync? If you just call the Play method in this program, the program will terminate before the sound plays. The Sync indicates that the program should pause while the sound plays.
I am building a wp8 app which could play poems line by line displayed in listbox.
Say I have 20 lines of Poems showing as 20 items in listbox. I have 20 mp3 files (one for each line), I used BackgroundAudioPlayer to play individual files and select each item (poem) in listbox. During playback of these mp3 files, there were delays of 1-3 seconds, so I found the full version of these mp3 files (20 files merged into one), reading poems line by line.
I am playing this mp3 file using BackgroundAudioPlayer. Playing as one file, I cannot select each item in listbox as I don't know the line number by playing one mp3 file.
Now what I want is to store the duration of 20 files in seconds, without storing and playing. The files are located in a link (http:123.com/1.mp3, /2.mp3, ...)
I used AudioTrack with absolute path and then used duration property, but it always returns zero. How can I get the duration of an mp3 file without playing them?
Edited:
In the background Agent I did below:
protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
{
switch (playState)
{
case PlayState.TrackReady:
TrackDuration tr = DataSource.Connection.Table<TrackDuration>().SingleOrDefault();
if (tr.IsGetTrackDuration)
{
if (player.Track != null)
{
player.Position = TimeSpan.FromSeconds(player.Track.Duration.TotalSeconds);
Recitation r = DataSource.Connection.Query<Recitation>("select * from Recitation where ID = " + player.Track.Title).SingleOrDefault();
r.AyaDuration = player.Track.Duration.TotalSeconds;
DataSource.saveRecitionDownloaded(r);
PlayNextTrack(player);
}
}
break;
}
NotifyComplete();
}
protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param)
{
switch (action)
{
case UserAction.Play:
PlayTrack(player);
break;
case UserAction.Seek:
if (null!=player.Track)
player.Position = (TimeSpan)param;
break;
}
NotifyComplete();
}
private void PlayNextTrack(BackgroundAudioPlayer player)
{
if (++currentTrackNumber >= audioTrack.Count)
return;
PlayTrack(player);
}
private void PlayTrack(BackgroundAudioPlayer player)
{
//If No Track then load Track
if (audioTrack.Count == 0)
{
//Load Tracks and Add them into Track Play List
}
if ((player.Track == null) || (player.Track.Title != audioTrack[currentTrackNumber].Title))
player.Track = audioTrack[currentTrackNumber];
if ((player.Track != null) && (player.PlayerState != PlayState.Playing))
player.Play();
}
The question is It plays some of the files which I don't want. (tr.IsGetTrackDuration) is always true, but I don't know why it plays some?
MusicProperties class has a property for the duration
MusicProperties musicProperties = await file.Properties.GetMusicPropertiesAsync();
outputText.AppendLine("Duration: " + musicProperties.Duration);
Ok I have a thought here. Under the AudioPlayer class, there is a TrackReady event that is set by default to play the track. Instead of playing by default, set a bool to true if you're simply wanting to obtain the duration, and false if you actually wish to play a track (when you're wanting to play the full mp3).
The bool value would have to be set in the main app before the track is set, and then read in the AudioPlayer each time the OnPlayStateChanged is called.
protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
{
//read GettingDuration value here
try
{
switch (playState)
{
case PlayState.TrackReady:
if (GettingDuration)
{
//store duration somehow and get the next track in line
}
else
{
player.Play();
}
break;
}
}
}