Code Monkey home page Code Monkey logo

soundcanvas's Introduction

SoundCanvas

[Live Link][live_link] [live_link]: http://hirosvk.github.io/SoundCanvas

![screeshot1][scrrenshot1] [scrrenshot1]:./sound_canvas.jpg

Overview

SoundCanvas turns music into abstract art animation. Make music with the simple interface (you need no musical experience!), and art will appear on the canvas. Click [here][live_link] to play.

How to Play

Play Demo

The best way to get to know SoundCanvas is to watch demo tracks first. Choose a demo track and click "Watch Demo." Click "Stop" to stop the animation and music.

Create Music

Click 'Activate Canvas' and the back beat will begin. Play any notes by typing keys or by clicking the note buttons. Shapes will emerge on the canvas. Click "Stop" to stop the beat.

Change Settings

You can change tempo, scales, and beat pattern. Your new settings will take effect after clicking "Activate Canvas."

How it Works

SoundCanvas creates animation from your music based on rules, and it does not rely on randomization. The intervals of the notes you play determine colors. New color tiles are generated on every beat.

Technical Notes

SoundCanvas was made purely by vanilla JavaSripts(ES6) and HTML5(Canvas). All audio effects are produced programmatically through AudioContext.

The app is divided into two main components; 'Canvas' and 'MusicTracker'. Canvas takes care of the render logic of the triangular grid. 'MusicTracker' takes care of the playing and capturing of the notes being played. Both classes are managed by GameUI class, that handles UI.

Canvas

Canvas lays out triangular grid system on initialization of the Canvas object based on the dimensions set on the index.html file.

In each grid block lives Triangle object, which holds one or more ColorTile objects. The ColorTile object keeps its color and moving direction.

On every beat, MusicTracker emits an array of notes currently playing. Canvas receives the notes and generates a series of ColorTiles. The arrangement of the notes determines the colors, initial grid position, and moving directions of the new ColorTiles.

On each render, the Triangle object generates the new color by blending the colors of the all ColorTiles it holds. After every render, the ColorTiles move to the adjacent Triangles according to its moving direction. As they leave their current Triangle, they are given the color of the previous Triangle.

Since all Triangle contains a white Tile as default, ColorTile's color fades into whiter shade on each render. When it's color turns completely white, the ColorTile object will not be passed to the next Triangle to reduce the render load.

On the initial design, the canvas was clearRect'ed on every render, but the colors disappeared too quickly, and the Canvas did not appear responsive to the user's play. On the current implementation, clearRect is not called, and color on the grid is not updated until next new ColorTile comes in. This way, the some ColorTiles linger on the Canvas, and results in more responsive and engaging UX.

MusicTracker

MusicTracker handles higher level functions of music playing and notes capturing. Keyboard class and BeatMaker class are the two components of MusicTracker.

Note Capturing

MusicTracker keeps all the played notes in a queue (trackerStore). Every time any note is played, it is pushed to the array up to 6 notes (this functionality is handled in Keyboard class). As 7th note is added to the queue, the first in the queue is shifted out. BeatMaker calls resetStore() at the end of every bar, which resets to an empty array.

GameUI passes a function 'passNotesToUI' to MusicTracker when MusicTracker constructor is called. 'passNotestoUI' is invoked when every beat hits, passing the current content of the trackerStore to Canvas.

Music Playing

When the user clicks 'Activate Canvas' button, GameUI resets MusicTracker with the new options (tempo, scale, root, and track(demo track)). The reset() function will initializes new Keyboard and BeatMaker classes. It also removes previous keyboard event listeners. (notice that, in Keyboard class, before installing keyboard event listeners, references to the keydown/keyup are created. This is so that removeEventListenr can correctly remove the keyboard event listeners. keydown.bind(this) = keydown.bind(this) ==> false.) If the canvas is activated without demo track, track is undefined.

Keyboard initializes with scale, root, and HTMLElement. On initialize, it generates a set of available notes, and append keys to the HTMLElement with event listeners to enable playing through keyboard and mouse clicking.

MusicTracker calculates the interval between notes from the tempo and time signature, and calls setInterval with beatMaker.manageBeat. The BeatMaker functions plays the beat pattern dictated on beat_pattern.js file.

Playback

When the user selects a demo track and clicks "Watch Demo", GameUI calls the same MusicTracker.reset() function, with 'track'. Playback process is the same as playing, with an exception that Keyboard does not install keyboard event listeners and Keyboard.prototype.managePlayback is called. Keyboard.prototype.managePlayback employs the same process as the Beatmaker.prototype.manageBeat.

notes: First I setup setInterval only on the beat. As I implemented playback feature, I had to shifted up to MusicTracker class.

Playing notes through AudioContext

Each Note has an oscillatorNode connected to a gainNode, and to the audioContext.destination. When the Note object is created, oscillator starts emitting the sound with the gainNode's gain set to zero. When the note is played (though function start()), the gain is set to 0.3. When stop() is called, the gain is set back to zero.

notes: I first tried this just with oscillators; on start(), connect the oscillator to the destination, and disconnect on stop(). However, it created a harse unpleasant sounds on connect/disconnect. The current implementation works fine, but I plan to optimize it further by creating a new oscillator on every time the note plays.

Beat Patterns / Demo Track format

SoundCanvas's beat patterns are coded as a nested array of digits 1 and 0. Within the wrapping array, each array represent a bar, and each digit represent a 1/8 note. On 1, BeatMaker makes the KickDrum beat, while it does not on 0.

Demo tracks are written in the similar fashion, but contains more information. Each track is an object that has numbers as properties which represent the nth note in the scale. (in C major scale, C is 0, D is 1, E is 2, etc...) The properties have a nested array much like beat patterns, with each digit representing 1/8 note. Demo tracks also have other necessary information as properties such as beat pattern and scale that.

soundcanvas's People

Contributors

aastudent avatar

Watchers

Sam Rawstorne avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.