Hyperlapse » Adding the music

Adding the music

Find the four WAV files and drag them to Framer’s editor, like you would with an image or video file. Their names are: music_1.wav, music_2.wav, music_3.wav and music_4.wav

Each music clip is four seconds long and can be looped to play continuously.

You’ll have this:

music_1 = new Audio("sounds/music_1.wav")
music_1.play()
music_2 = new Audio("sounds/music_2.wav")
music_2.play()
music_3 = new Audio("sounds/music_3.wav")
music_3.play()
music_4 = new Audio("sounds/music_4.wav")
music_4.play()

…and all sounds playing simultaneously.

Let’s try to play only one of the four tracks repeatedly. How would it sound if we loop the first track?

Delete the code for music_2 to music_4 (or comment it out) and make the first one, music_1, loop, like this:

music_1 = new Audio("sounds/music_1.wav")
music_1.loop = yes
music_1.play()
Download Framer project

It’s now less of a cacophony, but still, not perfect. You will hear a noticeable gap every four seconds.

This gap is not a bug, but just a limitation of the HTML5 <audio> element that Framer uses for its Audio objects.

Fortunately, the HTML5 audio tag isn’t the only way to play sound; there’s also the Web Audio API. All the major browsers support it, and in addition to just playing audio you can also synthesize sounds, mix sounds, crossfade, pass them through filters—all kinds of cool stuff. You can even simulate a phone’s vibration with it.

But it’s also complicated to use. That’s why we’ll tap into Web Audio API’s power the easy way: by adding an existing JavaScript library as a module.

We’ll use howler.js. Let’s add it to our Framer project.

  • Download the ZIP from github.com/goldfire/howler.js (‘Clone or download’ button)
  • Unzip it.
  • Find the howler.js file in dist, and copy it to the modules folder inside your project’s folder.

Now find the myModule.coffee file in the modules folder and open it in a text editor.

Delete the example code (you can leave in the lines with # comments at the top) and type this:

exports.howler = require "howler"

Save the file. You’re now ready to use Howler.js in your Framer project.

Go back to Framer and add this line at the beginning of your code.

# Howler.js for playing audio with the Web Audio API
# https://howlerjs.com/
howler = require('myModule').howler

(Importing a module should happen at the start of a project, to make sure that it’ll already be loaded when you’re about to use it. It also makes it obvious that a module is used in the project.)

All set. You can now return to the end of your Framer document, make a Howl object for every audio file, and set them to loop when playing.

# The music in 4 looping tracks
music_1 = new Howl
    src: ["sounds/music_1.wav"]
    loop: yes
music_2 = new Howl
    src: ["sounds/music_2.wav"]
    loop: yes
music_3 = new Howl
    src: ["sounds/music_3.wav"]
    loop: yes
music_4 = new Howl
    src: ["sounds/music_4.wav"]
    loop: yes

(We dragged in the WAV files earlier, so they are already in the project’s sounds folder.)

Now test the playback. It should play a perfect loop.

music_1.play()
Download Framer project

We’ll start the playback of all four tracks together while muting all but the first track. This way they will still be in sync when we unmute the second, third and fourth track.

Add the code that starts the music to the Utils.delay 5.2 block (in the # Start the first video section).

# Start the first video
Utils.delay 5.2, ->
    Video_1_Bridge.player.play()
    # and preload the other videos
    Utils.delay 1, ->
        Video_2_Clouds.player.load()
        Video_3_train.player.load()
        Video_4_people.player.load()
    # Start the music
    music_1.play()
    music_2.play()
    music_3.play()
    music_4.play()
    # … but mute 3 tracks
    music_2.mute yes
    music_3.mute yes
    music_4.mute yes
Download Framer project

(Note that this code would not work without the delay. The music_1, music_2, music_3 and music_4 objects aren’t yet created at this point, but they will be when this code is triggered… 5.2 seconds later. When you type music_1.play() outside of the delay block it will generate an error.)