Dynamically generating a .wav in JavaScript

I’ve put together a sine waveform generator that generates .wav files on the fly in pure JavaScript and plays the .wav file using whatever plugin your browser has installed. It works under Firefox, Opera, Safari, and Google Chrome, but I haven’t tested it in Internet Explorer. You can increase the size of the generated .wav file by changing around the parameters, but be aware that it will stop working if the size of the .wav file grows too large. Most likely, the plugin that you will need is Quicktime, since that seems to register itself as the default player on many systems.

A view of generated waveform (ignore the static)

A view of the generated waveform (ignore the static)

If you missed the link in my post:
http://sk89q.therisenrealm.com/experiments/jswav/

In addition, I’ve made a JavaScript song player that generates each note individually and plays them in order. However, a new .wav is generated for every note due to the length limit of data URIs.

Tags: , ,

16 Responses to “Dynamically generating a .wav in JavaScript”

  1. Kris Kowal says:

    I’m porting your example code into my Chiron library. I’m breaking it into a struct.js and wav.js module with more discrete functions so people can make unit tests. I’ve added the base64 code you found to my list of base64 encoders for the upcoming deathmatch.

    In the mean time, I think you could make use of this function, perhaps to generate your lookup table on the fly, or to memoize, whatever you like:

    /*** notes
    */
    exports.notes = {
    ‘Ab’: -1, ‘A’: 0, ‘A#’: 1, ‘Bb’: 1, ‘B’: 2, ‘C’: 3, ‘C#’: 4, ‘Db’: 4, ‘D’: 5,
    ‘D#’: 6, ‘Eb’: 6, ‘E’: 7, ‘F’: 8, ‘F#’: 9, ‘Gb’: 9, ‘G’: 10, ‘G#’: 11
    };

    /*** frequency
    */
    exports.frequency = function (octave, note) {
    if (typeof note == ’string’) note = notes[note];
    return 440 * Math.pow(2, (octave - 4) + note / 12);
    };

    What would it take to create polyphony or other wave forms?

  2. sk89q says:

    Yeah, that’s a better way to do it. I copied the list of note frequencies from an old piece of Python code that I wrote (or generated, I think), so I didn’t bother with creating the lookup table on the fly.

    As for other wave forms or more complicated sounds, you’d have to consult an audio engineer. I don’t have any substantial knowledge in audio signals. The only other simple waveform that I know of that you can do is the sawtooth wave, but it’s only emulation (it doesn’t sound as nice). The function for that is floor(x) - x.

    Wikipedia has great articles on the basic waveforms:
    http://en.wikipedia.org/wiki/Sine_wave
    http://en.wikipedia.org/wiki/Sawtooth_wave
    http://en.wikipedia.org/wiki/Triangle_wave
    http://en.wikipedia.org/wiki/Square_wave

    • JML says:

      i extend your code to integrate other waves form

      Oscilator 1 Shape

      Sinus
      Square
      Saw tooth
      Spike
      White Noise
      Ramp

      function genSignal(shape,value)
      {
      var signal = 0;
      if (shape == 1)
      {
      signal = Math.sin((2 * Math.PI) * value);
      }
      else if (shape == 2)
      {
      if (value < -0.5)
      {
      signal = 1.0;
      }
      else
      {
      signal = -1.0;
      }
      }
      else if (shape == 3)
      {
      if ( value < -0.5 )
      {
      signal = -1 + ( value + 1 )*4;
      }
      else
      {
      signal = 1 - (value + .5)*4;
      }
      }
      else if (shape == 4)
      {
      if ( value -0.47)
      {
      signal = 1;
      }
      else
      {
      signal = -1;
      }
      }
      else if (shape == 5)
      {
      signal = Math.random();
      }
      else if (shape == 6)
      {
      signal = 1 + value*2;
      }
      return signal;
      }

      we also can insert ADSR envelope, lfo modulation and ocsilateur composition.

  3. [...] SK has shown that it’s possible to generate wave file in Javascript and play it. All this happens in the browser and without requiring Flash. He’s built a sine wave generator and a song player. [...]

  4. [...] SK has shown that it’s possible to generate wave file in Javascript and play it. All this happens in the browser and without requiring Flash. He’s built a sine wave generator and a song player. [...]

  5. Rasmus Fløe says:

    Very cool!

    If you need extra performance generating the wavs you may try the following.

    Firefox and Safari (and I’m guessing Chrome also) have native base64 encoder/decoder functions; btoa (encode) and atob (decode).

    dec2hex seems very quirky. The native Number method toString() with a radix seems a bit more solid: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/toString

    String.fromCharCode accepts multiple arguments so instead of:

    case “V”:
    output += String.fromCharCode(arg & 255) +
    String.fromCharCode((arg >> 8) & 255) +
    String.fromCharCode((arg >> 16) & 255) +
    String.fromCharCode((arg >> 24) & 255);
    break;

    you could do:

    case “V”:
    output += String.fromCharCode(
    arg & 255,
    (arg >> 8) & 255,
    (arg >> 16) & 255,
    (arg >> 24) & 255
    );
    break;

  6. sk89q says:

    Ah, thanks for the comment. I’ll update the code accordingly.

  7. [...] SK has shown that it’s possible to generate wave file in Javascript and play it. All this happens in the browser and without requiring Flash. He’s built a sine wave generator and a song player. [...]

  8. Paulie says:

    That’s fantastic! If only there wasn’t such a strict size limitation this would be a great way to generate tunes on the fly.

    Do you think there is a way to save that data to a file and then play it back? I suppose it could be AJAXed back to the server, saved, then retrieved, but then one might as well generate it on the server to start with.

    Doing separate WAV files is ok, but doesn’t give quite enough control.

    Great job! I’m going to start playing around with this.

  9. sk89q says:

    I’m not aware of any way to save the files to the computer.

  10. JML says:

    Very good job!!

    When we see that web2 success is partly due to music community. It’s very strange that standard web technology (xHTML …) deals so bad with sounds management where text, image and even vector graphics are so easily accessible thru javascript/svg/canvas
    It is simple, most of web browser use plugin to play music and no one integrate sounds génerator (synthesis).

  11. [...] Cameron Adams ????????JavaScript???JS-909 ?JS-909??????Flash????????????????????????????Flash????????????????? sk89q ???sine waveform generator ????????WAV??? [...]

  12. [...] ?????????????WAV?????sk89q???????????????????MIDI??? [...]

  13. L_jr says:

    Does it exist an example of generating any complex type of image (like GIF, BMP or JPG and not XBM) in Javascript?

Leave a Reply