Multiple audio layers - how to allow mute/unmute on each layer
Feb 25, 2019
Dear Community,
I have a Story which I'm hoping will teach musicians their parts for a particular song. To do this, I'm hoping they can hear all the instruments of the song together but be able to remove (mute) and add (unmute) any instrument within the song to be able to hear how their parts and the other parts sit together.
So, what I’m hoping it will do is play the track from start to finish and the user can mute/unmute the various instruments, as they choose, throughout the track.
I have had a go at this with some success. I have audio of each individual instrument. When played, all tracks play in time with each other and I can mute tracks. However, when any track is unmuted, it plays that piece of audio from the beginning, putting it out of sync with the other instruments.
I’m wanting the user to be able to mute any instrument(s) and when they unmute the instrument it will be at the location of the song that the other instruments are at. So, literally silencing individual instruments for a duration of the song until it’s chosen to unsilence them.
Does anyone have any thoughts on how I could achieve this?
With thanks,
Dave
14 Replies
A few more details would help. How are you playing them? Is it triggered by timeline start across multiple layers or all on the same layer? How are you muting them? Are you simply stopping and starting the objects timeline? Have you employed any JavaScript?
Hi, Dave:
An intriguing idea. If you put audio files on separate layers, I think they'll start from the beginning of the file, which you don't want.
I believe you'd have to get all the audio files on the base slide timeline. Then maybe create triggers based on what you want: like play tracks 1 and 2, IF the user selects X. Might be worth experimenting a bit.
Hi Owen,
thanks for the reply.
Each audio file has its own layer. Each layer of audio begins at the same time (putting the audio in sync) when the timeline starts. So, as you suggest, it is triggered by timeline start across multiple layers.
Each layer is being muted by clicking an object which hides the layer. To correct what I said earlier, I think each bit of audio picks up from where it was when it was "muted" (hidden) rather than going back to the start of its timeline.
When I looked into this initially, some vaguely similar discussion did mention Javascript. My initial post in another forum regarding this asked whether Javascript would be necessary. Alyssa Gomez was helpful in trying to assist and my own experimenting narrowed down where I was getting stuck but we headed down a track away from js. She suggested I post here, which is where I'm currently at.
So, no, I haven't employed JavaScript, and to borrow from my initial post in the other forum, "if there is a solution, and it involves using Javascript, is there a beginners resource for including that?"
Let me know if any other information would be helpful, Owen.
Thanks again for the response,
Dave
Hi Daniel,
many thanks for the idea. I'll experiment with that.
To correct my initial post, I think the audio files are picking up from where they were "muted" (or hidden) rather than going back to the start of the timeline. Having audio on individual layers seemed to be the only way to be able to mute it.
I'll give your idea a go as well though, Daniel.
Thanks again,
Dave
JavaScript can handle this. Don't be afraid of a little coding.
Demo
The first thing you want to do is use JavaScript to add the audio files directly to the HTML5 page as audio elements. You also want to set some attributes like ID, autoplay, loop etc. Be sure each element audio file has its own unique variable and that each audio element you create has a unique ID. The code would look something like the following, which is adding and starting 2 audio elements. Execute this at the timeline start of your page.
var audio1 = document.createElement("audio");
audio1.type = "audio/mp3";
audio1.src='location of your .mp3';
audio1.id='audio1';
audio1.loop = true;
audio1.autoplay = true;
var audio2 = document.createElement("audio");
audio2.type = "audio/mp3";
audio2.src='location of your next .mp3';
audio2.id='audio2';
audio2.loop = true;
audio2.autoplay = true;
var head=document.getElementsByTagName('body')[0];
head.appendChild(audio1);
head.appendChild(audio2);
The code to mute the audio is actually just controlling the volume level of each sound element.
In my example, I'm also using a StoryLine variable to determine the state of the button for each sound as well as to determine of the volume should be set to 0 or 1 (1 being equal to 100%).
It looks something like this:
var player = GetPlayer();
var toggle = player.GetVar("Audio1");
if (toggle === 1) {
var audio = document.getElementById('audio1');
audio.volume = 1.0;
} else if (toggle === 0) {
var audio = document.getElementById('audio1');
audio.volume = 0.0;
};
This post was removed by the author
Hi Owen,
only two-months to get back to this! I was hoping it would have been a lot earlier and apologise for not sending thanks for your help sooner.
I'm so close. I feel it. Thank you for your guidance into the world of Javascript. Copying your examples, I've been able to hopefully get most of it right. Each time I go back and look I'm seeing slight differences and have whittled down those differences to the point that, as far as I can tell, all is the same as your example. But I think there's one element that I'm missing (and am not seeing) that is not allowing any of it to work.
One big obvious difference I've just identified is that our zip files are significantly different. I did notice this with mine earlier (that they were way too small so I wasn't sure if it was supposed to include the audio files in the zip file or was adding them in some other way). You provided two audio files in your example and mine has 9. When published, my zip file is 1.17mb. Yours is 73.1mb. Also, yours works even when I publish and embed it. So, I suspect the audio just isn't being included in the zip files of my interactive?
I believe the audio location is identified in the Javascript associated with the slide itself ("Execute JavaScript When the timeline starts").
In your example, a location of a file is: 'story_content/WebObjects/5b6YVw28ThU/Ralph Stanley O Death.mp3'
In my version, an example location is: 'audio/Ozi Interactive/Audio/Bell - close_1.mp3'
I've also tried 'Ozi Interactive/Audio/Bell - close_1.mp3' and 'Audio/Bell - close_1.mp3' but it still doesn't seem to be adding the audio to the zip file (based on the zip file size when published). I also tried this only with the first two audio file locations in the JavaScript mentioned above in case it made no difference and I would have to go back and fix all 9. I presume if I had the location correct for even 1 or 2 it would add those to the zip file?
Could the location I noted be incorrect? The .story file is in 'audio\Ozi Interactive'. Is there a setting that I should be choosing to tell it to add audio to the zip file?
In case it's useful, here is an example in that JavaScript noted above of one audio file:
---
var agogosound = document.createElement("audio");
agogosound.type = "audio/mp3";
agogosound.src='audio/Ozi Interactive/Audio/Bell - close_1.mp3';
agogosound.id='agogo';
agogosound.loop = true;
agogosound.autoplay = true;
---
The section at the end of that JavaScript, again using only the audio file above as an example, is:
---
var head=document.getElementsByTagName('body')[0];
head.appendChild(agogosound);
---
Thanks again for the guidance, Owen.
Regards,
Dave
I'm using a (complex?) trick of turning a web object embedded in a "hidden" slide to act as a sort of asset briefcase. Here is how it works.
You don't need any content on the index.html page. The following tags are enough:
<html>
<head></head>
<body></body>
</html>
StoryLine interprets this as a local page that might point to additional assets that are required for the page to run so it inventories everything in the folder at the time you add the web object. This is important to understand because any changes you make to these files won't get picked up by SL after this point. If you add or change any of the audio files, you need to delete the web object and add it again to get an updated version of the folder and it's contents.
This is unique for your web object. If you make changes as detailed in step 6 above and republish, the name of this folder WILL change and any path references to the items in this folder will need to be updated.
The folder structure is created by StoryLine and your audio files now follow all of the other project assets. You will notice that the path follows exactly the folders I detailed starting in step 8 above. In my case, story_content/WebObjects/5b6YVw28ThU/Ralph Stanley O Death.mp3
It works! All audio parts can be heard. Thanks so much, Owen.
I hear that I'll need to do some playing around with timing. On first listen none (or few) of the audio parts were in time. Listening in other software, I hear that they should all play in time. However, when I later refreshed it, they were closer, if not spot on.
So, I think I'll have to do some playing around. I suspect what I'm trying to achieve may be slightly unique so I'm not too sure how many would have discussed this on the forums before. Still, it's fun to play with. :-)
Thanks again for getting me over the hardest parts, Owen. I would have hit real barriers without your help.
Regards,
Dave
Ah, I failed to account for the delay writing multiple files to the document element might cause. The code I gave you creates an element to auto play then adds it to the html before moving on to the next element. That little bit of processing time adds up with each element and becomes noticeable because each sound starts as soon as they are written but before the next one is added.
Try this as a start to tighten up the timing:
(audio1.autoplay = true; audio2.autoplay = true; etc.)
audio1.play(); audio2.play();
This change adds all of the elements to the page but doesn't play them as they are added. Once everything has been added, it then fires off the play command.
If this doesn't sync it up completely, it will at least get you closer and maybe close enough. I'm experimenting with a slightly different approach to see if I can't get it exactly synced up for you.
Thanks once again, Owen. The additional help is truly appreciated.
This seemed to have a similar effect to the earlier version. The audio files were slightly out the first run but, after reloading a couple of times and "Resuming" it had all parts in sync. From memory, the earlier version acted in the same way but "Restart" seemed to have more luck accurately re-syncing the files. That could have been my imagination, though.
Dave
Maybe try splitting up the code. Move all of the code that adds the audio files to the html document to fire at timeline start on your opening slide and then add the JavaScript "play" code (audio1.play(); audio2.play();...etc.) to your next slide. In theory, this could have the same effect as a refresh or reload by giving the assets a little extra time to load.
I'll give that a try as well, Owen. Thank you.
I may have to put this project to rest for a little while but wanted to thank you again for all of your help, Owen. It is definitely functioning, if not quite in the neatest way. It was a proof of concept and it has definitely shown the potential. You taught me a lot along the way, also.
I hope to pick it up again in the not too distant future so might bring this thread back to life then.
Many thanks again, Owen,
Dave
👍
This discussion is closed. You can start a new discussion or contact Articulate Support.