How to know if a music file has finished playing? - cocos2d-x

In cocos2d-x, you can play music by doing the following:
auto audio = SimpleAudioEngine::getInstance();
// set the background music and play it just once.
audio->playBackgroundMusic("mymusic.mp3", false);
But how do we know if the music has finished playing ? The game could be interrupted by a phone call (triggering other code that pauses the game and the music) or paused by the user.
Is there anyway to know if the file has finished playing ? I know we can keep some kind of timer to keep track of the duration the song has been playing but that seems hacky, and this is a common use case, especially if we want to queue a playlist.

It looks like you'll have to test audio->isBackgroundMusicPlaying() in your update() methods.
There ought to be a delegate, or some other kind of callback, which will tell you such things. I guess you could subclass SimpleAudioEngine to add this.
EDIT There is experimental::AudioEngine which offers a didFinishCallback:
static void setFinishCallback(int audioID, const std::function<void(int, const std::string &)> &callback);
However you need to be aware that I don't think it supports all platforms, so use with caution.

Related

Memory Efficient Code with WebAudio API

I am developing an HTML5 game and using Web Audio API for sounds. I am having an issue in which sounds start slowing down as game progress and game also starts feeling jerks which i guess is due to java-script GC doing memory cleanup.There are two types of sound i am playing in the game:
1) Background sound which continuously loop
2) Jump sound, hit sound etc occurs due to some event in the game which occurs very frequently. For example: firing multiple bullets from gun.
Not sure what i am doing wrong, please help. Please refer below code
function play(){
this.startTime = this.actx.currentTime;
this.soundNode = this.actx.createBufferSource();
this.soundNode.buffer = this.buffer;
this.soundNode.connect(this.volumeNode);
//If there's no reverb, bypass the convolverNode
if (this.reverb === false) {
this.volumeNode.connect(this.panNode);
}
//If there is reverb, connect the `convolverNode` and apply
//the impulse response
else {
this.volumeNode.connect(this.convolverNode);
this.convolverNode.connect(this.panNode);
this.convolverNode.buffer = this.reverbImpulse;
}
this.panNode.connect(this.actx.destination);
this.soundNode.loop = this.loop;
this.soundNode.playbackRate.value = this.playbackRate;
this.soundNode.start(
this.startTime,
this.startOffset % this.buffer.duration
);
this.playing = true;
}
There's nothing in your code that stands out as specifically memory intensive, apart from the use of the convolver (which can be really expensive and cause bad performance on lower-end devices). I'd try this though:
Try disabling your audio (don't run any of the audio code, don't just mute it). Do you still have the janks in the game visuals? If so, it's not your audio that's the culprit.
Try running your audio but always run it without the convolver. If the jank disappears, the convolver is your culprit. The only thing I could think of there is to try setting the convolver buffer only once and not every call to play().
Try running different profiles in Chrome Dev Tools (JS, Memory, Paints etc.) and try to figure out where the janks come from. https://developer.chrome.com/devtools/docs/cpu-profiling
Good luck!

setInterval with play() in flash as3?

I'm trying to play a sound (notification sound) in my flash application and I need to play the sound until the user clicks on something else to stop it.
I can play the sound properly but the issue is that it will only play once but i need it to play constantly (a short delay between each play maybe?).
my current code is this:
var mySound:Sound = new Sound();
mySound.load(new URLRequest("iphonenoti_cRjTITC7.mp3"));
mySound.play();
so I thought I can use setInterval(mySound,5000); in my code but this doesn't work which means it doesn't play the sound on the loop!
could someone please advise on this?
Thanks in advance.
Well, reading the Documentation of setInterval it states that the first parameter should be a function. In your code, you are passing an Object of the type Sound.
So, there are a couple of options, I'll show you the quickest and dirtiest one.
Instead of setInterval(mySound,5000); you write setInterval(mySound.play,5000);

How to put music in individual scenes and have it change when i select a new scene

Alright I've managed to make an almost web page style thing in flash. I have all the coding to navigate the pages finished, but now I'm having the issue of when I change pages my main page music continues while the other pages music begins. I.,m unsure of how to code this. can anyone help? also I already have click sound effects going for my buttons and they seem to be working fine. Don't know if that helps at all. I'm also using flash cs6 and don't want to go to cc, because the removal of the bone tool.
To stop a sound, you will need to use a SoundChannel object when you tell the sound to play. Then, with the reference to the SoundChannel, you can stop the sound before you exit the section.
// save this reference for later so you can stop the sound when you want..
var mySoundChannel:SoundChannel = mySound.play(); // Get a sound channel.
// Call this later
mySoundChannel.stop();
Without a SoundChannel to control it, the sound object will do its default behavior, which is to play to completion.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/SoundChannel.html

Actionscript to play/pause audio on different buttons

I've created a few buttons in Flash. I'm trying to make it so that if you click one button, the audio starts playing for that button. If you click another button, the active audio stops and the new audio of the button you clicked last start playing.
Any help please?
What you're describing is actually quite easy to do.
First things first, I recommend importing the audio into your Flash project. Alternatively, there is a way to play it directly from an external file. This is beyond the scope of my answer, so if you need help on that, you should post a question specifically covering it.
Assuming you have imported the audio file into your Flash project's library, make an as3 instance of it. (Right click the file in the library, click Properties --> ActionScript [tab] --> [Check] Export for ActionScript & [Enter name in] Class)
Now, create a definition of the sound in your code. (Assuming your two sounds were named "mySound1" and "mySound2" in the Class field of the previous step.)
var mySound1:Sound = new mySound1();
var mySound2:Sound = new mySound2();
Now, define your sound channel.
var mySoundChannel:SoundChannel = new SoundChannel();
There are two alternate ways of stopping one sound and playing another. The first is to create one function that does both every time. The second method is to create two formulas, one for "play" and one for "stop". You will need to decide which method works best for you. I'll use the two-function method below:
function stopSound():void
{
//This stops all sound in the sound channel.
//If there is nothing playing, nothing happens.
mySoundChannel.stop();
}
//In this function, we create an argument that allows us to tell the function
//what sound to we want it to play.
function playSound(soundname:String):void
{
mySoundChannel = this[soundname].play(0, 0);
}
[Note, you can tweak the play() properties to meet your needs, doing things like starting in the middle of the song, or looping it forever. 0,0 starts at the beginning, and doesn't loop. See the documentation for this.]
Now you hook up the event listeners for the buttons. (If you need help with event listeners, read the documentation.)
myButton1.addEventListener(Mouse.CLICK, btn1Click);
myButton2.addEventListener(Mouse.CLICK, btn2Click);
function btn1Click(evt:Event):void
{
stopSound();
playSound(mySound1);
}
function btn2Click(evt:Event):void
{
stopSound();
playSound(mySound2);
}
This should be enough information to get you started. In my game core, I actually have a custom class for dealing with sound playback that gives me the ability to repeat sounds, change volume, and keep sounds from conflicting with each other. I say that to emphasize that you can do quite a bit with the sound class. Do some digging in that documentation for ideas and help.
You may also consider putting a try-catch statement in the playSound function, since it will throw an reference error if you pass a name for a sound that doesn't exist.

Sound plays multiple times at once

I'm having trouble with sound in Flash. I may have went about coding the wrong way, because most of my codes are on frames.
So, I have these two variables
var outsideDay:Sound = new daysong();
var outsideNight:Sound = new nightsong();
And I want to play these songs on a specific frame. However, the sounds play sporadically, like 50 times at once. I think it's because I have other codes that link to the frames with a Enter_Frame function. How can I get the sounds to loop and not play multiple times at once?
Have you dropped the sound anywhere on the timeline in any frame? If so remove that frame.
Also, if you have your code declared on a keyframe that does not have a stop(); call on it, likely it is hitting that frame over and over again, when it "enters" it. Try adding stop(); either at the beginning of your code or at an ending key-frame, wherever it makes most sense for your project.
After trying those two things, another method I have learned to love that may come in handy is:
flash.media.SoundMixer.stopAll();
This will stop all sounds so that whatever sounds you start to play after making this call will not have other previously started sounds to contend with.
This sound tutorial may also be of use to you.
Let us know how it goes, or if any of this stuff helped.