Using multi-channel audio on mobile
Multi channel audio is a very useful feature available on iOS and Android, which enables us to handle different pieces of audio separately by using separate 'channels'. This lesson will take you through the basics of using channel-based audio on mobile, and will show you how to use it to play multiple sounds simultaneously.
You can download the sample stack from this url: https://tinyurl.com/y846apdl
You can download all the necessary resources for this lesson from this url: https://tinyurl.com/y9pz3wkc
1. Getting set up
Firstly, we need to set up our stack so that we are ready to start playing audio. For this lesson, we will have four audio files that we use, named "background.wav", "noise1.wav", "noise2.wav", and "noise3.wav". We will want to put these audio files in the same folder as our stack, so the first thing we need to do is to create a new mainstack, and save it. Make sure you place it in it's own folder, by itself. Then, place the audio files in the same folder as the stack. You should now have a setup that resembles the above. As we are going to be running this app on a mobile device (or simulator), once this is done we also need to go into Standalone Application Settings, and under 'Copy Files', add in the four audio files that we have in the our application folder.
2. Playing an audio file
The first thing we are going to do is simply put a button on our stack, and script it to play one of our audio files. To do this, we will use the command mobilePlaySoundOnChannel
, which takes three parameters - the filepath to the sound, the name of the channel, and the type of playback we want. The script of the button we will use to play sound 'noise1.wav' will be:
on mouseUp
local tPath, tChannelName, tType
put (specialFolderPath("resources") & "/noise1.wav") into tPath
put "noise1" into tChannelName
put "now" into tType
mobilePlaySoundOnChannel tPath, tChannelName, tType
end mouseUp
So, in the above example, we are using the specialFolderPath function to build the path to our sound - specialFolderPath("resources"), when used on a mobile device, returns the path to the folder containing our application and associated files. Adding "/noise1.wav" to the end of this gives the path to our noise1.wav audio file, which we included in the Copy Files in step 1. We use "noise1" as the channel name - this could be anything we want, but we use "noise1" for clarity here. The final parameter, the type, can be one of three things: "now", which plays the audio file now and interrupts any other currently playing audio files, "next" which will queue the sound and play it after the current sound on that channel is finished, and "looping", which will repeatedly play the sound file on that channel until we stop it.
So, if we now start up the app in the simulator, and click the button, we should hear our sound file "noise1.wav" being played.
3. Playing multiple audio files
Now that we have code to play an audio file properly, we can create several more buttons and reuse it (with slight alterations) in each button, to play multiple audio sounds. Create 3 other buttons on the stack, and use the same code as above in each - but change "noise1" to the name of the audio file we want to play in each new button (noise2, noise3, and background). For example,
on mouseUp
local tPath, tChannelName, tType
put (specialFolderPath("resources") & "/background.wav") into tPath
put "background" into tChannelName
put "now" into tType
mobilePlaySoundOnChannel tPath, tChannelName, tType
end mouseUp
When you run this in the simulator or on a device, you should be able to click each button to play a separate sound, without interrupting each other.
4. Controlling audio playback
In our current setup, we are able to play the audio files, but we have no control over the playback. In some circumstances, we may want to be able to do things such as pause and resume the audio. Let's set up some controls to pause and resume our background.wav file, and alter the script of the button that plays 'background.wav' so that we can use it to both start the audio file from the beginning, or stop it completely.
We'll add two new buttons to pause and play, with the following scripts:
Pause:
on mouseUp
mobilePausePlayingOnChannel "background"
end mouseUp
Resume:
on mouseUp
mobileResumePlayingOnChannel "background"
end mouseUp
These buttons use two very simple commands which will pause or resume the sound on a given channel. The script of the button that plays 'background.wav' becomes this:
on mouseUp
local tPath, tChannelName, tType
if (mobileSoundOnChannel("background") is empty) or (mobilleSoundOnChannel("background") is "could not find channel") then
put (specialFolderPath("resources") & "/background.wav") into tPath
put "background" into tChannelName
put "now" into tType
mobilePlaySoundOnChannel tPath, tChannelName, tType
else
mobileStopPlayingOnChannel "background"
end if
end mouseUp
The mobileSoundOnChannel function is used to see if background.wav is already playing - if the function returns empty, no sound is playing on that channel. If the function returns 'could not find channel', the channel has not been created yet (it will automatically be created the first time we try to play a sound on it). If we find that it is already playing, we use the mobileStopPlayingOnChannel command, and specify the channel "background" to tell it to stop playing the sound.
For a full list of channel related syntax, search for "channel" in the livecode dictionary.
Ian
An important point is that you won't get any sound in IDE but have to run it through the simulator or device to test the sound being played.
albert
I am running the example and keep on getting this error
button "noise1": execution error at line 5 (Handler: can't find handler) near "iphonePlaySoundOnChannel", char 1
Could you please advise, I am evaluating livecode 5.5.1 in trial mode. Could this be the reason.
I have also change iphonePlaySoundOnChannel to mobileSoundOnChannel but still get the same error.
Thank you
Hanson Schmidt-Cornelius
Hi Albert,
No, your version of LiveCode being a trial version does not impact on the functionality you describe.
It is difficult to say exactly what is happening in your application without an example of the code with your possible modifications, that is causing the error and knowledge of the platform you are running your code on.
The "iphonePlaySoundOnChannel" command can only be used on iPhones, iPads and iPods, or their simulators.
"mobilePlaySoundOnChannel" can be used on iPhones, iPads, iPods and Android devices, or their simulators.
Kind Regards,
Hanson
Vicki
I'm trying to do this and get the same error as the person above: do I need to change the words "specialFolderPath" to my folder path? Here is the complete code:
on mouseUp
put (specialFolderPath("engine") & "/chant.mp3") into tPath
put "chant" into tChannelName
put "now" into tType
mobilePlaySoundOnChannel tPath, tChannelName, tType
end mouseUp
and I get the error code:
button "Button". execution error at line 5 (Handler: can't find handler) near "iphonePlaySoundOnChannel", char 1
Any help would be greatly appreciated!
Hanson Schmidt-Cornelius
Hi Vicki,
the reason you are getting the error message is because you are trying to run the code in the IDE. In order for you to run the code with mobilePlaySoundOnChannel ..., you need to run your application on a device or simulator.
Use the "Test" button to start the simulator or run it on an Android device. If you want to run the code on an apple device, then you have to build the standalone and then drop it onto the device.
Kind Regards,
Hanson
Vicki
Hello Hanson,
Thanks so much for getting back so quick!
Firstly, my 'test' button is disabled, I've looked at instructions for that and the location I've found for my IOS development SDK's is set to: /Applications/Xcode.app/Contents/Developer. Is that correct? Or do I need to purchase the commercial license first to have the test capability? (which I fully intend to do!).
Another question I have is: how to create multichannel looping audio tracks that automatically play in time with each other - whenever additional tracks are pressed to play (via a button). Just trying to figure that one out..
Forgive me, as I'm new to this!
thanks so much,
Vicki
Hanson Schmidt-Cornelius
Hi Vicki,
different versions of XCode give you access to different simulators, so you may want to include different versions of XCode.
If LiveCode did not complain, then the version you have included should be valid. The dialog in which you configured LiveCode for mobile deployment should also have informed you of what simulators are available.
If the "Test" button is grayed out then select the target from the drop down menu: "Development -> Test Target"
You do not need a commercial LiveCode license to test on mobile devices. You will need the commercial version if you wish to sell your products.
On the question of looping audio channels:
1. You can either use the "looping" parameter with mobilePlaySoundOnChannel or
2. Handle the soundFinishedOnChannel Message to determine when a sound finished and then use the message handler to start other sounds as needed.
Kind Regards,
Hanson
Oliver Kalleinen
Hi, is there a way to get the duration of a sound file that is playing on a channel? Similar to "get the duration of player" property Thanks. Oliver
Panos Merakos
Hello Oliver, unfortunately there is no direct way to do that for a sound file that is playing on a channel. You could use the mobile native player (using mobileControlCreate "player") and then set the filename with mobileControlSet myPlayer, "filename" and the get the duration with mobileContolGet(myPlayer, "duration"). And then, you could play the sound either using the mobile native player (mobileControlDo myPlayer, "play") or play it using mobilePlaySoundOnChannel.