A universal 'mute' button possible?

I found a possible reason... it doesn't autoplay on iOS. Interesting. :thinking:

Also, straight JavaScript is all that's needed...

I knew there was an easier way to do this. It seemed odd that I'd need to add HTML to the scene if I wasn't even going to show an audio player.

So, I’ve been working on audio because of Annoyed Tomatoes. One of the features is volume control – for both background music and sound effects.

https://photics.com/games/annoyed-tomatoes

mv = 0.3;

var music = new Audio('${resourcesFolderName}/title-screen-dark-feelings.m4a');
music.volume = mv;
music.loop = true;
music.play();

The mv variable is the Music volume. So, when the background music is played, it plays at the preferred volume. For the theme of this thread, just set the value to “0” for no sound… or use music.pause();

Easy, right?!

Well, my projects aren’t that simple. I’m using a loop. For some reason, when I play the audio with Hype’s scene actions, there’s no delay at the end of a loop. But when I play it with the above JavaScript code, there’s a noticeable delay. I’m still figuring that out.

Well, my projects aren't that simple. I'm using a loop. For some reason, when I play the audio with Hype's scene actions, there's no delay at the end of a loop. But when I play it with the above JavaScript code, there's a noticeable delay. I'm still figuring that out.


Hi Michael! - Here's some info about the "gap" in the looping...
1 Like

I was just searching this topic and I think Hype is using the Web Audio API...

Apparently Web Audio gets rid of the gap, which I think is what Howler.js is using. It says so right in the title... "Modern Web Audio Javascript Library"

Since most modern browsers seem to support Web Audio, I figured I'd just use Web Audio. I started looking at how to add an audio file with pure JavaScript. I was like nope... not tonight. That's a lot harder. HA HA!

Howler.js and Gapless-5 appear to be good solutions though... and the audio not playing on iPhone is an Apple thing.

@Photics
Maybe we move this discussion to a different topic? I think this parallel discussion is hijacking the thread.

Hello Jim,

Thanks for taking the time to answer this so thoroughly.

Yes, the narration track on the left verbalizes the text on the left, and is actually timed to some of the moving images to the right. There is no ancillary info.

The presentation will be on a ipad hosted by ‘Kiosk Pro’.

Each separate scene has its own .mp3 track, and as I mentioned, is activated by the NEXT button of the previous scene. So the NEXT button in scene 4 for example, will activate scene 5 narration as the presentation changes from scene 4 to 5.

The idea of the MUTE button (which I’m personally not crazy about, but is what the client is asking for) is that if a visitor chooses not to listen to the narration for whatever reason, but just read it at his/her own pace, he/she can turn the whole thing off.

The MUTE button will simply be placed in the opening splash screen. Once MUTE is pressed, the whole presentation is silent. If the person changes his/her mind, he/she must navigate back to the splash screen and unmute.

As you mention, there might be compilations, but that will to be the way it is. We would prefer not to use a mute option at all, but…

So I guess, my answer to your question, is that it is a ‘true mute’.

This project is actually due on Monday. If you can let me know how to make a MUTE button and an UNMUTE button (to be placed on the splash page) that’ll be great. I understand that each scene might then have to fiddled around with by adding code, but that’s ok.

I’m not a coder, so simple steps please. : )

Much thanks!

RH

@rh009

Thank You for your reply so this gives me a better idea of your goal.

The main reason why I have gone into such detail in these last several posts is to find out exactly what You need and so make the code as specific & simple as possible - so it is easy for You to understand and be able to make basic changes to the code if necessary.

If the viewers are making a choice on the Splash screen (and only there) I think it is more of an “on”~“off” switch, otherwise we have a mess on our hands. i.e. they leave Scene 3 - go to the splash screen and then come back to Scene 3 - or maybe not - perhaps they go to Scene 4, etc. So why not just start things from the beginning of a sound track when ever a Scene is opened - the viewer already has to disrupt their experience by having to leave a Scene to turn the volume on or off.

I think, following the gist of my first post above, we would implement a “soundStatus” variable.

Initially this variable would be set to a default of “on” - the soundtrack for each scene would play when the Scene opened - and turn off when the Scene closes, of course.

If the viewer chose “off” at the splash screen the soundStatus variable would be set to “off” and the soundtracks do not play.

This set-up would work using the “On Scene Load” event handler. When a scene opened it would check the soundStatus variable to see whether or not to play the sound track.

We also would employ the “On Scene unLoad” event handler which would stop playing the soundtrack when the viewer left a Scene - whether or not a soundtrack was actually playing. There is no penalty for turning a sound off even if it is already off - and our code is one notch simpler as we do not need to check the “soundStatus” variable.

Does this approach sound good to You?

Hi Jim,

Thank you again! Yes, I believe this suits our needs.

If you can be so kind as to provide the codes, where to place them, how to customize, etc. that’ll be wonderful.

I’m not a coder, so simple instructions would be awesome.

RH :slight_smile:

I will create a basic Hype project that demonstrates the entire set-up (code, placing of code, etc. using 3 dummy scenes) which You will be able to adapt to your needs. I will not be able to get to this until tonight (California time) and will communicate via private message when it is finished.

Wonderful! :grinning:

No Script, just work with two versions of each back/next-Button. One with and the Other without an Action playing the sound. So a mutebutton will just run a Timeline to Show just the desired Button. Custombehaviours and Symbols may be a good help …

this should work toomuteSounds.hype.zip (445.1 KB)

1 Like

Can I just interject here :slight_smile:

I would (if it were me) just create a persistent symbol (because it lives outside the scene structure) and place my buttons inside it. That way the buttons would be available across all scenes and any interaction would be contained to the symbol so no need to check anything on scenes, etc. Unless you want to (I’ll come back to that ;))

So, here is my logic:

  • Create a persistent symbol. Inside create 3 buttons. Mute, Play, Pause. Give them ID’s. My suggestions are muteBtn, playBtn, pauseBtn but it doesn’t matter except the code below must change.
  • Inside the symbol and in the symbol inspector (CMD-2) choose “on Symbol Load” -> Action: “Run Javascript…”, Function: “New Function…” and in the function window type the following code (or copy and paste): Basically, this sets 2 global variables. isMuted which is set to false and audio which is assigned a new Audio object with a URL for the audio.
isMuted = false;
audio = new Audio('http://traffic.libsyn.com/effortlessenglish/Models_Etc.mp3'); //new Audio('${resourcesFolderName}/myAudio.mp3');
  • Then, highlight any of the buttons and in the Actions inspector (CMD-6) choose “on Mouse Click” -> Action: “Run Javascript…”, Function: “New Function…” and in the function window type the following code (or copy and paste again): Here we are using just one function and depending on the button’s ID we call the associated audio methods. Note, the Audio object has a “muted” property that is either true or false.
if (element.id == "playBtn"){ //ID assigned to play button
console.log("play pressed")
	audio.play();
} else if (element.id == "pauseBtn"){ //ID assigned to pause button
	console.log("pause pressed")
	audio.pause();
} else if (element.id == "muteBtn"){ //ID assigned to mute button
	console.log("mute pressed")
	if (!isMuted){ // check our global variable to check if muted or not.
		console.log("muted")	
		audio.muted = true;
		isMuted = true;
	} else if (isMuted) {
		console.log("not muted")
		audio.muted = false;
		isMuted = false;
	}
}
Files

Demo

globalAudioControls.zip (38.7 KB)


The above technique will enable you to control one instance of audio over the entire document.

If you wanted to delve deeper, you could create variables in each scene to find out where the user is and use this variable to set the audio to play from that point. Using the currentTime property of the audio object. I’ll let Jim work on that if he wants :wink:

2 Likes

Regarding the other diversion within the thread. I have some documents using webAudio in Hype if you want @Photics I can share them with you and show you how you can use the technique to have seamless looped audio. PM me.

anyone else with good suggestions¿ … :wink:

Hello Jim and everyone else,

Thank you for all the suggestions! Now this is what I call a ‘community’!

Let me try out the various solutions, and see what’s best. Stay tuned…

RH :slight_smile:

I moved the conversation here... Annoyed Tomatoes

I'm using howler.js... https://howlerjs.com ...which is nice.

1 Like

It's not just a 'community' it's a Block Party! ...especially this thread.

Last night I sent via PM the following file to @rh009

Demo Project: universalMute_JHSv2.hype.zip (197.8 KB)
Online Demo here.

As per the OP's request the sound controls are only located on the "Splash" screen. When the project opens a default is set to play the soundtrack for each scene ("Head HTML")... audioSound = "true".

There are two buttons "Yes" & "No" for the Playing~Not Playing of the soundtracks. I did not use a true mute (volume "0") as the viewer would have to come back to the Splash screen to make changes - and then go back to a Scene - a disruptive procedure. Whereas a mute control on the individual Scenes themselves would have made more sense for using an actual mute.

The "On Scene Load" handler runs the following sceneAudioSetting function:

 if(audioSound == "true") {
  var whatScene = hypeDocument.currentSceneName();
  whatScene = whatScene.slice(-2);		
  var sceneAudio = '${resourcesFolderName}/audioTrack' + whatScene + '.mp3';
  window.sceneNarration = new Audio(sceneAudio);
  sceneNarration.play();	
 }

The Scene names end in two digits indicating the Scene Number (e.g. myScene_01, yosemite02, etc.)
This number is used to match the Scene and the soundtrack which also has the same digits somewhere in the name.

There is no "else if" construction since if the soundtrack is set to not play (audioSound = "false") we don't need to bother with it.

4 Likes

Hi
I tried Jims universalMute and its really awesome!
Its nearly exactly what i need in my project but there is some problems that i can’t get my head around.

This setup will not play the audio on any iOS divice. I know that i have to trigger the audio but i can’t figure out how.
If i use Play Sound on Scene load i can get it to work on iOS but when Scene Load runs the javascript in the example it does not play.

The other thing is that it stops the sound and start the sound from the beginning. Is it possible to mute it instead?

Does anyone know how to alter this great setup so that it works om iOS?

PS. I am not a programer :slight_smile:
thanks
Rickard

@Rickardax

To my knowledge there is no way to autoplay audio or to mute audio for iOS devices using JavaScript.

Here are some links on the topic:
Apple iOS-Specific Considerations and apple insider.

What I put together for You is a Demo: universalMute_iOS_JHSv1.zip (95.3 KB)

This Demo autoplays if it is on a Desktop.

There is also a “Play”~“Pause” toggle button. On the Desktop version (which autoplays) this toggle state is set to “Pause”. When the demo is running on an iOS device the toggle button state is set to “Play”.

The “Mute” button only shows up on the Desktop version since a “Mute” control is non-functional on an iOS device.

There is only one Scene in the Demo.

"Head HTML" setting is the same as in the post of my previous Demo (2 weeks ago from this post) with the “audioSound” variable set to “true”.

The Functions…

sceneAudioSetting - as in my previous Demo above (2 weeks ago from this post).

muteToggle - checks the name of the button’s innerHTML. If the innerHTML of the button is currently “Mute” the volume is set to “0” and the innerHTML is switched to “unMute”. If the innerHTML is “unMute” the volume is set to “0.8” (80%) and the innerHTML is set to “Mute”.

iOSPlayPauseToggle - same type of set-up as with the muteToggle except the innerHTML toggles between “Play” & “Pause” of the name in the Play~Pause button with the respective action of playing or pausing the audio track.

iOSCheck - does exactly that (“On Scene Load” event handler). If an iOS device is detected then the “Mute” button is hidden (it’s of no use on iOS) and the “Play”~“Pause” toggle button is set to “Play” as the user must deliberately start the audio track; for a Desktop the default is “Pause” as the audio track autoplays.