Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Fading out/Stopping Looped Music in Passage(s)

edited March 2015 in Help! with 2.0
Hello, I'm brand spanking new to Twine, but I'm a huge fan of computers and an even bigger fan of telling stories.

I'm using the Harlowe story format. I managed to get a sound to loop in the background over all my passages, but it has come to my attention that I need the sound to fade out and then stop for a few passages, and then fade in and loop once more. Help would be appreciated! Thank you!

Comments

  • You will need to explain exactly which of the number of different methods you used to play your sound.

    eg.
    Did you write your own javascript, if so can you show an example of the code?
    Did you use a HTML <audio> tag within a passage, if so could you supple an example of the passage.
    Did you use another person's javascript script, if so which one?
  • I used the following Javascript in the Edit Story Javascript field.
    var audio = document.createElement('audio');
    audio.src = 'music/rainforest_ambience-GlorySunz-1938133500.mp3';
    audio.loop = true;
    audio.play();
  • My advice is if you want to use sound within your story that you think about changing to the SugarCube story format and adding this script to your Story Javascript area.

    If you want to keep using Harlowe then the first thing you need to do is change your javascript so that there is some way to find the audio element you created so you can use it later. One way to do this is to give the audio element an ID and to append the element to the body, in the following example I have given the element a ID of nowplaying

    var audio = document.createElement('audio');
    audio.setAttribute('id', 'nowplaying');
    audio.src = 'music/new_stories.mp3';
    audio.loop = true;
    $("body").append(audio);
    audio.play();
    Now you can use javascript and jQuery to locate the audio element and then either change the music volume or pause it:
    note: audio volume ranges from 0.0 (none) to 1.0 (full). The second number in Fade in/out examples is the fade period.

    // Fade out - turn the volume down
    $('#nowplaying').animate({volume: 0}, 2000);

    // Fade In - turn the volume up
    $('#nowplaying').animate({volume: 1}, 2000);

    // Pause the music
    $('#nowplaying')[0].pause();
    Harlowe does not currently have an easy way to call javascript from within a passage, so you have to use a hack. Adding the following to a passage will fade out the music:

    The music fades out
    <div style="display: none;"><img src="!@#$" onerror="$('#nowplaying').animate({volume: 0}, 1000);" /></div>
    P.S.
    The following javascript encapsulates the above jQuery code convent into a Music namespace, it contains four methods:
    1. play(tune);  2. fade(newvolume, period);  3. pause();  4. stop();

    The following script was written in a couple of minutes, it is very rough and contains very little error checking. Add it to your Story Javascript area.

    // Music namespace.
    if (typeof Music == "undefined") {
    var Music = {
    play: function(tune) {
    var audio = $('#nowplaying');
    if (! audio.length) {
    audio = document.createElement('audio');
    audio.setAttribute('id', 'nowplaying');
    $("body").append(audio);
    }
    // setup the tune to play.
    audio.src = tune;
    audio.loop = true;
    audio.play();
    },
    // fade the music in / out. newvolume range between 0.0 -> 1.0
    fade: function(newvolume, period) {
    // assign defaults.
    newvolume = newvolume || 0;
    period = period || 1000;
    var audio = $('#nowplaying');
    if (audio.length)
    audio.animate({volume: newvolume}, period);
    },
    pause: function() {
    // find the audio element.
    var audio = $('#nowplaying');
    if (audio.length)
    audio[0].pause();
    },
    stop: function() {
    // find the audio element.
    var audio = $('#nowplaying');
    if (audio.length) {
    audio[0].pause();
    audio[0].currentTime = 0;
    }
    }
    };
    window.Music = Music;
    }
    To play a tune use the Music.play(tune) method, you can add it to the end of your Story Javascript:

    Music.play('music/new_stories.mp3');
    To fade in/out (change volume), add something like the following to one of your passages:

    <div style="display: none;"><img src="!@#$" onerror="Music.fade(0,3000);" /></div>
    To pause or stop the music,  add something like the following to one of your passages:

    <div style="display: none;"><img src="!@#$" onerror="Music.pause();" /></div>

    or

    <div style="display: none;"><img src="!@#$" onerror="Music.stop();" /></div>
  • Giving the audio element an ID and the hack worked! The sound is fading in and out as desired! Thank you so much!  ;D
  • greyelf wrote: »
    Harlowe does not currently have an easy way to call javascript from within a passage, so you have to use a hack. Adding the following to a passage will fade out the music:

    The music fades out
    <div style="display: none;"><img src="!@#$"; onerror="$('#nowplaying').animate({volume: 0}, 1000);" /></div>

    To fade in/out (change volume), add something like the following to one of your passages:
    <div style="display: none;"><img src="!@#$"; onerror="Music.fade(0,3000);" /></div>

    To pause or stop the music, add something like the following to one of your passages:
    <div style="display: none;"><img src="!@#$"; onerror="Music.pause();" /></div>
    or
    <div style="display: none;"><img src="!@#$"; onerror="Music.stop();" /></div>
    Harlow now supports the usage of HTML script elements within passage, so the above can be replaced with:
    The music fades out
    <script>$('#nowplaying').animate({volume: 0}, 1000);</script>
    
    To fade in/out (change volume), add something like the following to one of your passages:
    <script>Music.fade(0,3000);</script>
    
    To pause or stop the music,  add something like the following to one of your passages:
    <script>Music.pause();</script>
    or
    <script>Music.stop();</script>
    

    I would also change the namespace from Music to Audio to make it more generic.
  • I have a question to add to this: I can get the namespace working fine, and I can start the start/stop/pause/fade the audio from any passage in the story, but once I use the Music.play() function I can never seem to use it again.

    As in, if I begin playing the music with
    <script>Music.play();</script>
    
    then stop it with
    <script>Music.pause();</script>
    
    then try to start it again with
    <script>Music.play();</script>
    
    it gives me an error that "the page's code has got itself in a mess (script error)". It doesn't matter if I'm pausing or stopping the audio.

    Is this something to do with the Play function? Or do I only have the option of fading the music in/out?
  • As I explained in the comment just before the Music code example that code is very rough and does not contain any error catching, nor does it contain a function to resume a tune that has paused. The example was just meant to be a starting point for the OP to build their own Music/Sound API for Harlowe.
    Cakebread wrote: »
    As in, if I begin playing the music with
    <script>Music.play();</script>
    
    The Music.play() function in my example expects you to pass it the name of the tune you want it to play, so the call should look something like:
    <script>Music.play('music/new_stories.mp3');</script>
    

    The following is a slightly less rough example of a Sound API which can be used as a starting point. It includes a resume function and the play function has been fixed so that it will not fail when called a second time.

    warning: The following still contains very little error checking and has not been fully tested so use at your own risk.
    // Sound namespace.
    if (typeof Sound == "undefined") {
    	var Sound = {
    		play: function(tune) {
    			if (! tune) {
    				// no tune, no play.
    				return;
    			}
    			var audio = $('#nowplaying')[0];
    			if (typeof audio === 'undefined') {
    				audio = document.createElement('audio');
    				audio.setAttribute('id', 'nowplaying');
    				$("body").append(audio);
    			}
    			// setup the tune to play.
    			audio.src = tune;
    			audio.loop = true;
    			audio.volume = 1;
    			audio.play();
    		},
    		// fade the music in / out. newvolume range between 0.0 -> 1.0
    		fade: function(newvolume, period) {
    			// assign defaults.
    			newvolume = newvolume || 0;
    			period = period || 1000;
    			var audio = $('#nowplaying');
    			if (audio.length == 1) {
    				audio.animate({volume: newvolume}, period);
    			}
    		},
    		pause: function() {
    			// find the audio element.
    			var audio = $('#nowplaying')[0];
    			if (typeof audio != 'undefined') {
    				audio.pause();
    			}
    		},
    		resume: function() {
    			// find the audio element.
    			var audio = $('#nowplaying')[0];
    			if (typeof audio != 'undefined' && audio.paused) {
    				audio.play();
    			}
    		},
    		stop: function() {
    			// find the audio element.
    			var audio = $('#nowplaying')[0];
    			if (typeof audio != 'undefined') {
    				audio.pause();
    				audio.currentTime = 0;
    			}
    		}
    	};
    	window.Sound = Sound;
    }
    
    The following is an example of the usage of the above rough Sound API, the example assumes that the tune/sound mp3 files are in a media sub-folder:
    (link-repeat: "Play Tune")[<script>Sound.play('media/tune.mp3');</script>]
    (link-repeat: "Play Sound")[<script>Sound.play('media/sound.mp3');</script>]
    
    (link-repeat: "Fade Out")[<script>Sound.fade(0,3000);</script>]
    (link-repeat: "Fade In")[<script>Sound.fade(1,3000);</script>]
    (link-repeat: "Pause")[<script>Sound.pause();</script>]
    (link-repeat: "Resume")[<script>Sound.resume();</script>]
    (link-repeat: "Stop")[<script>Sound.stop();</script>]
    
Sign In or Register to comment.