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
Daniel Brigham

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. 

David Hall

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

 

David Hall

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

OWEN HOLT

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;
};

David Hall

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

OWEN HOLT

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.

  1. Create a folder (location doesn't matter)
  2. Add all of your audio files into the folder.
  3. Add a blank HTML page and be sure it is saved as index.html
    You don't need any content on the index.html page.  The following tags are enough:
    <html>
    <head></head>
    <body></body>
    </html>
  4. In StoryLine, add a scene that isn't connected to any other scenes.
  5. In the default slide in that scene, insert a web object.
  6. Click the folder next to the address input and navigate to the folder containing your files.
    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.
  7. Publish for WEB
  8. Open the folder containing your published content. You should see a sub-folder called story_content
  9. Open the folder titled story_content.  You should see a sub-folder called WebObjects
  10. Open the WebObjects folder. You should see a folder with a unique alpha-numeric name.
    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.
  11. Open the folder and you will see your audio files and the blank index.html.
    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
  12. Now that you know the path to your files, update your JavaScript as needed and republish.
David Hall

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

OWEN HOLT

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:

  1. Delete from the code ALL "autoplay = true" statements. 
    (audio1.autoplay = true; audio2.autoplay = true; etc.)
  2. At the bottom of your code AFTER all of your "head.appendChild" statements, add JavaScript to play your files. Use the variable names for your audio elements.  In my original  example it would be:
    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.

David Hall

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

OWEN HOLT

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.

David Hall

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.