GithubHelp home page GithubHelp logo

rserota / wad Goto Github PK

View Code? Open in Web Editor NEW
1.9K 49.0 159.0 4.81 MB

Web Audio DAW. Use the Web Audio API for dynamic sound synthesis. It's like jQuery for your ears.

License: MIT License

JavaScript 98.67% HTML 0.21% CSS 1.12%
javascript midi-device midi audio daw microphone panning sound

wad's Introduction

WadJS npm npm

A Javascript library for manipulating audio. It's like jQuery for your ears.

Wad Logo

Table of Contents

  1. Installation
  2. Introduction
  3. Panning
  4. Filters
  5. Microphone Input
  6. Configuring Reverb
  7. Audio Sprites
  8. Logging
  9. Sound Iterator
  10. Tuna Effects
  11. Audio Listener
  12. Play Labels
  13. External Fx
  14. Presets
  15. Polywads
  16. Compression
  17. Recording
  18. Audio Meter
  19. Pitch Detection
  20. MIDI Input
  21. Access to the Audio Context
  22. Cross-browser Compatibility
  23. Acknowledgements
  24. How to Contribute
  25. API Documentation
  26. Showcase

Installation

To use WadJS in your project, simply include the script in your HTML file.

<script src="https://unpkg.com/web-audio-daw"></script>

WadJS is also available as an npm module.

npm install web-audio-daw
import Wad from 'web-audio-daw';

Introduction

To do anything with WadJS, you'll first need to create a wad, which can represent anything that makes sound, such as an mp3 file, an oscillator, or even live microphone input. The simplest use case is loading and playing a single audio file.

const bell = new Wad({source : 'https://www.myserver.com/audio/bell.mp3'});
bell.play();
bell.stop();

You can also create oscillators using the same syntax, by specifying 'sine', 'square', 'sawtooth', 'triangle', or 'noise' as the source.

const saw = new Wad({source : 'sawtooth'});
saw.play();

The Wad constructor and the play() method both accept many optional arguments. Skim through the API documentation to learn more.

Panning

WadJS supports two types of panning: stereo-panning, and 3d-panning. Stereo-panning works the same way panning works in most audio software. With stereo panning, you can specify the left/right balance of the sound using a number between 1 and -1. A value of 1 means the sound is panned hard-right, and a value of -1 means the sound is panned hard-left.

With 3d-panning, you don't directly set the left/right stereo balance. Rather, the panning setting describes the distance of the sound source from the audio listener. Any time you would pass in a panning parameter (either to the constructor, the play() method, or the setPanning() method), you can pass it in as a three element array to specify the X, Y, and Z location of the sound. You can set the panning to arbitrarily high or low values, but it will make the sound very quiet, since it's very far away. When using 3d-panning, there are two different panning models that can be used. The HRTF panning model is higher quality, but the equalpower panning model is more performant. If not specified, the equalpower panning model is used.

const saw = new Wad({
    source        : 'sawtooth',
    panning       : [0, 1, 10],
    panningModel  : 'HRTF',
    rolloffFactor : 1 // other properties of the panner node can be specified in the constructor, or on play()
})

Filters

The filter constructor argument can be passed an object or an array of objects. If an array is passed, the filters are applied in that order. Whichever form is passed to the constructor should also be passed to the play argument.

const saw = new Wad({
    source: 'sawtooth',
    filter: [
        {type : 'lowpass', frequency : 600, q : 1, env : {frequency : 800, attack : 0.5}},
        {type : 'highpass', frequency : 1000, q : 5}
    ]
})

Microphone Input

You can also use microphone input as the source for a Wad. You can apply reverb or filters to the microphone input, but you cannot apply an envelope or filter envelope. If a Wad uses the microphone as the source, it will constantly stream the mic input through all applied effects (filters, reverb, etc) and out through your speakers or headphones as soon as you call the play() method on that Wad. Call the stop() method on a microphone Wad to disconnect your microphone from that Wad. You may experience problems with microphone feedback if you aren't using headphones.

const voice = new Wad({
    source  : 'mic',
    reverb  : {
        wet : .4
    },
    filter  : {
        type      : 'highpass',
        frequency : 500
    },
    panning : -.2
})

// You must give your browser permission to use your microphone before calling play().
voice.play()

If voice.play() is called with no arguments, it uses the arguments from the constructor. However, if it is called with any arguments, all arguments from the constructor are discarded (except for source), and the arguments passed to voice.play() are used instead.

Configuring Reverb

In order to use reverb, you will need a server to send an impulse response. An impulse response is a small audio file, like a wav or mp3, that describes the acoustic characteristics of a physical space. You can make your own impulse response, but it might be easier to just find one online. There's also an impulse response included in the test folder that you can use.

Audio Sprites

If your project contains many short audio clips, you may be able to achieve better performance by loading them as a single, longer audio clip, and play sections from that longer clip as needed.

const helloWorld = new Wad({
    source: 'https://www.myserver.com/audio/hello-world.wav',

    // add a key for each sprite 
    sprite: {
        hello : [0, .4], // the start and end time, in seconds
        world : [.4,1]
    }
});

// for each key on the sprite object in the constructor above, the wad that is created will have a key of the same name, with a play() method. 
helloWorld.hello.play();
helloWorld.world.play();

// you can still play the entire clip normally, if you want. 
helloWorld.play(); 

// if you hear clicks or pops from starting and stopping playback in the middle of the clip, you can try adding some attack and release to the envelope. 
helloWorld.hello.play({env:{attack: .1, release:.02}})

Logging

WadJS can log various warnings and notices to the console, but these are disabled by default. To view these messages in the console, you can increase Wad's verbosity.

Wad.logs.verbosity = 0 // WadJS will print nothing to your console. This is the default setting. 
Wad.logs.verbosity = 1 // View some notices and warnings, e.g. audio context started, midi devices connected, etc. These logs should not print more than once.
Wad.logs.verbosity = 2 // View all notices and warnings, including those from play() and stop(). These logs might print many times. 

Sound Iterator

The SoundIterator object is used for playing sounds in a random order or repeatedly through a loop. It is good for footstep sounds, for example.

const iterator = new Wad.SoundIterator({
    files: [new Wad({source:'square'}), new Wad({source:'triangle'})], // Takes Wad objects, or files that would be passed to source. If it is passed a file that is not a Wad object, then it will create a generic Wad object with the passed file as the source.
    random: false, // either play a random order (true), or play in the order of the list (false)
    randomPlaysBeforeRepeat: 0, // This value says the amount of plays that need to happen before a sound can be repeated. This only works if the length of the iterator is 3 or more, and this value is max 1 less than the length of the sound list.
})

The methods are:

iterator.play(args) // Plays the next sound in the list, or next random sound following the random rules. The passed args are the normal args that can be passed to Wad.play(). The function returns a Promise.
iterator.add(sound) // Pass in either a Wad object or an object that would be passed as a source in a new Wad. It returns the SoundIterator object to be chained.
iterator.remove(sound) // pass in the Wad instance you want to have removed from the iterator. Only Wad objects that were added as Wad objects can be removed.

Tuna Effects

Tuna, everyone's favorite Web Audio effects library, is included in WadJS. This makes it super easy to add effects from Tuna to any Wad or PolyWad.

let itBeTuna = new Wad({
    source : 'sine',
    tuna   : {
        Overdrive : {
            outputGain: 0.5,         //0 to 1+
            drive: 0.7,              //0 to 1
            curveAmount: 1,          //0 to 1
            algorithmIndex: 0,       //0 to 5, selects one of our drive algorithms
            bypass: 0
        },
        Chorus : {
            intensity: 0.3,  //0 to 1
            rate: 4,         //0.001 to 8
            stereoPhase: 0,  //0 to 180
            bypass: 0
        }
    }
})

For more information about the various Tuna effects and the arguments they take, check out the Tuna wiki.

Audio Listener

WadJS wraps the AudioListener to provide uniformity across browsers. The AudioListener is only useful when using 3D panning. You can use both the standard listener.positionX.value or the setPosition function to move the listener. The default position and orientation is: positionX=0, positionY=0, positionZ=0, forwardX=0, forwardY=0, forwardZ=-1, upX=0, upY=1, upZ=0.

  • Wad.listener.setPosition(x,y,z) -> setPosition moves the listener to the specified coordinates. Take note that the web audio API has X move left and right, y move up and down, and z move forward and back. So if one is moving around a flat environment, then x and z will want to be used, and not X and Y.
  • Wad.listener. setOrientation(forwardX, forwardY, forwardZ, upX, upY, upZ) -> This takes two direction vectors. Neither vector's coordinates have units. The first vector is the direction the user's nose is facing. The second vector is the direction of the top of the listener's head.
  • Wad.listener.getPosition() -> returns a 3 element list of the user's positionX.value, positionY.value, and positionZ.value.
  • Wad.listener.getOrientation() -> returns a six element array of: forwardX.value, forwardY.value, forwardZ.value, upX.value, upY.value, and upZ.value.
  • To set or get a value directly, do: listener.positionX.value.
Wad.listener.setPosition(1,0,0)
console.log(Wad.listener.positionX.value)
Wad.listener.forwardZ.value += 1
console.log(Wad.listener.getPosition()[0])

Play Labels

When you call stop() on a Wad, it will only stop the most recently triggered note. If you want to retain control over multiple notes that played from the same Wad, you can label those notes when play() is called. When stop() is called, you can pass in a label argument to stop all currently sustained notes with that label.

saw.play({pitch : 'A4', label : 'A4'}) // The label can be any string, but using the same name as the note is often sensible.
saw.play({pitch : 'G4', label : 'G4'})
saw.stop('A4') // The first note will stop, but the second note will continue playing.

External FX

Sometimes you might want to incorporate external libraries into Wad, for example FX or visualizers. You can override the constructExternalFx and setUpExternalFxOnPlay methods to add those nodes to the wad chain. In the following example the values are hardcoded, but they could easily have been passed as arguments to play.

//For example to add a Tuna chorus you would put this somewhere in your own code, and also include the Tuna library:

Wad.prototype.constructExternalFx = function(arg, context){
    this.tuna   = new Tuna(context);
    this.chorus = arg.chorus;
};

Wad.prototype.setUpExternalFxOnPlay = function(arg, context){
    const chorus = new tuna.Chorus({
        rate     : arg.chorus.rate     || this.chorus.rate,
        feedback : arg.chorus.feedback || this.chorus.feedback,
        delay    : arg.chorus.delay    || this.chorus.delay,
        bypass   : arg.chorus.bypass   || this.chorus.bypass
    });
    chorus.input.connect = chorus.connect.bind(chorus) // we do this dance because tuna exposes its input differently.
    this.nodes.push(chorus.input) // you would generally want to do this at the end unless you are working with something that does not modulate the sound (i.e, a visualizer)
};

Presets

If you'd like to use a pre-configured Wad, check out the presets. They should give you a better idea of the sorts of sounds that you can create with WadJS. For example, you can create a Wad using the preset 'hiHatClosed' like this:

const hat = new Wad(Wad.presets.hiHatClosed);

PolyWads

In many cases, it is useful to group multiple Wads together. This can be accomplished with a PolyWad, a multi-purpose object that can store other Wads and PolyWads. There are two main cases where you might want to group several Wads together. One case is when you want to make a complex instrument that uses multiple oscillators. Other audio synthesis programs often have instruments that combine multiple oscillators, with names like 'TripleOscillator' or '3xOSC'.

const sine     = new Wad({ source : 'sine' })
const square   = new Wad({ source : 'square' })
const triangle = new Wad({ source : 'triangle' })

const tripleOscillator = new Wad.Poly()

tripleOscillator.add(sine).add(square).add(triangle) // Many methods are chainable for convenience.

tripleOscillator.play({ pitch : 'G#2'})
tripleOscillator.setVolume(.5)
tripleOscillator.stop() // play(), stop(), and various setter methods can be called on a PolyWad just as they would be called on a regular Wad.

tripleOscillator.remove(triangle) // It's really just a double-oscillator at this point.

The second main case in which you would want to group several Wads together is to make a mixer track, where several Wads share a set of effects and filters.

const mixerTrack = new Wad.Poly({
    filter  : {
        type      : 'lowpass',
        frequency : 700,
        q         : 3
    },
    panning : 1
})

mixerTrack.add(tripleOscillator).add(triangle)
tripleOscillator.play({ pitch : 'Eb3'}) // This note is filtered and panned.

Compression

If you want to make a song that sounds rich and modern, it often helps to compress the dynamic range of the song. A compressor will make the loudest parts of your song quieter, and the quietest parts louder.

const compressor = new Wad.Poly({
    compressor : {
        attack    : .003 // The amount of time, in seconds, to reduce the gain by 10dB. This parameter ranges from 0 to 1.
        knee      : 30   // A decibel value representing the range above the threshold where the curve smoothly transitions to the "ratio" portion. This parameter ranges from 0 to 40.
        ratio     : 12   // The amount of dB change in input for a 1 dB change in output. This parameter ranges from 1 to 20.
        release   : .25  // The amount of time (in seconds) to increase the gain by 10dB. This parameter ranges from 0 to 1.
        threshold : -24  // The decibel value above which the compression will start taking effect. This parameter ranges from -100 to 0.
    }
})

Recording

PolyWads can be created with a recorder, which can save the output of the PolyWad to an audio file.

    const voice = new Wad({source: 'mic'})
    const polywad = new Wad.Poly({
        recorder: {
            options: { mimeType : 'audio/webm' },
            onstop: function(event) {
                let blob = new Blob(this.recorder.chunks, { 'type' : 'audio/webm;codecs=opus' });
                window.open(URL.createObjectURL(blob));
            }
        }
    })
    polywad.add(voice)
    voice.play()
    polywad.recorder.start()
    // make some noise
    polywad.recorder.stop() // a new window should open, where you can download the file you just created

The options that are specified above get passed directly into the MediaRecorder constructor. The onstop method that is specified above is used to handle the onstop event of the MediaRecorder. Methods from the MediaRecorder (start, stop, pause, resume, requestData) have been aliased to polywad.recorder for convenience. The MediaRecorder itself can be accessed at polywad.recorder.mediaRecorder. Read more about these here. The snippet above shows the default values for options and onstop, so that polywad could have been created simply like this:

    const polywad = new Wad.Poly({ recorder: {} })

Alternatively, you can use the recorded audio as the source for a new Wad.

    const recordings = [];
    const voice = new Wad({source: 'mic'});
    const polywad = new Wad.Poly({
        recorder: {
            options: { mimeType : 'audio/webm' },
            onstop: function(event) {
                let blob = new Blob(this.recorder.chunks, { 'type' : 'audio/webm;codecs=opus' });
                recordings.push(new Wad({source:URL.createObjectURL(blob)}))
            }
        }
    });
    polywad.add(voice);
    voice.play();
    polywad.recorder.start(); // make some noise
    polywad.recorder.stop(); 
    recordings[0] && recordings[0].play()

Audio Meter

PolyWads can be created with an audio meter, which reports the volume level of the PolyWad's output, and can tell you if it's clipping.

    const sawtooth = new Wad({source:'sawtooth', env:{hold:1, release:.2}})
    const triangle = new Wad({source:'triangle', env:{hold:1, release:.2}})
    const polywad = new Wad.Poly({
        audioMeter: {
            clipLevel: .98, // the level (0 to 1) that you would consider "clipping".
            averaging: .95, // how "smoothed" you would like the meter to be over time. Should be between 0 and less than 1.
            clipLag: 750, // how long you would like the "clipping" indicator to show after clipping has occured, in milliseconds.
        },
    })
    polywad.add(sawtooth).add(triangle)

    setInterval(function(){
        console.log("Volume: ", Math.round(polywad.audioMeter.volume * 1000))
        console.log("Clipping: ", polywad.audioMeter.checkClipping())
    }, 50)
    polywad.play()

Pitch Detection

PolyWads can detect the frequency of their input.

const voice = new Wad({source : 'mic' }); // At this point, your browser will ask for permission to access your microphone.
const tuner = new Wad.Poly();
tuner.setVolume(0); // If you're not using headphones, you can eliminate microphone feedback by muting the output from the tuner.
tuner.add(voice);

voice.play(); // You must give your browser permission to access your microphone before calling play().

tuner.updatePitch() // The tuner is now calculating the pitch and note name of its input 60 times per second. These values are stored in <code>tuner.pitch</code> and <code>tuner.noteName</code>.

const logPitch = function(){
    console.log(tuner.pitch, tuner.noteName)
    requestAnimationFrame(logPitch)
};
logPitch();
// If you sing into your microphone, your pitch will be logged to the console in real time.

tuner.stopUpdatingPitch(); // Stop calculating the pitch if you don't need to know it anymore.

MIDI Input

WadJS can read MIDI data from MIDI instruments and controllers, and you can set handlers to respond to that data. When WadJS initializes, it tries to automatically detect any connected MIDI devices, and creates a reference to it in the array Wad.midiInputs. To handle MIDI data, assign a MIDI handler function to a MIDI device's onmidimessage property. By default, Wad is configured to log MIDI messages to the console, which should be sufficient if you are quickly testing your devices. If you want to quickly set up a MIDI keyboard to play a Wad, assign a Wad of your choice (or any object with play() and stop() methods) to Wad.midiInstrument.

Wad.midiInstrument = new Wad({source : 'sine'});

If you want to get creative with how WadJS handles MIDI data, I strongly encourage you to write your own MIDI handler functions. For example, note-on velocity (how hard you press a key when playing a note) usually modulates the volume of a note, but it might sound interesting if you configure note-on velocity to modulate the attack or filter frequency instead.

const midiMap = function(event){
    console.log(event.receivedTime, event.data);
}

Wad.assignMidiMap(midiMap)

If you have multiple MIDI devices that you would like to use simultaneously, you will need multiple MIDI handler functions. The second argument to Wad.assignMidiMap is used to specify the index of the MIDI device you would like to assign to.

    Wad.assignMidiMap(anotherMidiHandlerFunction, 1)  
    Wad.midiInputs[1].onmidimessage = anotherMidiHandlerFunction 

Wad.assignMidiMap can also accept success and failure callbacks as its third and fourth arguments, to handle cases where the MIDI device you are trying to assign to cannot be found.

Access to the Audio Context

When WadJS loads initially, it automatically creates an Audio Context. It shouldn't be necessary to access the Audio Context directly, but if you need it for some reason, it is exposed at Wad.audioContext. If you are using A-Frame in your application and WadJS detects an <a-scene> element on the page, WadJS will use A-Frame's Audio Context and Audio Listener, instead of creating its own.

Cross-Browser Compatibility

WadJS works best in Chrome, decently in Safari for iOS, and it works poorly in Firefox. I have not tested it in any other browsers. I would greatly appreciate contributions to help WadJS run optimally in any browser that supports Web Audio, especially mobile browsers.

Acknowledgements

The synthesizer icon at the top of this readme was created by Anatolii Badii from Noun Project.

How to Contribute

There are many ways that you can help make WadJS better, including testing it in different environments and raising issues. However, if you'd like to contribute code to WadJS, here are some tips and guidelines:

  1. Fork the repo.
  2. Add/edit source files in /src.
  3. Build the project with npm run build, or build automatically after changes with npm run watch.
  4. Webpack output is written to /build.
  5. Follow the style rules in .eslintrc (use tabs and semicolons). You can check/fix your style with npm run lint.
  6. WadJS does not have automated tests, but there is a manual testing page in /test. If you add or modify a feature in WadJS, please change the test page so that I can easily hear what you did. The test code is also built when your run npm run build.
  7. Submit a pull request.

API Documentation

new Wad(args)

Property Type Default Description
args object none (required) One big object with all of the arguments for creating this wad.
args.source string none (required) To make a wad that plays an audio clip, set this to the url for the audio file. To make a wad that plays an oscillator, set this to 'sine', 'square', 'sawtooth', 'triangle', or 'noise'. To create a wad that processes your microphone input, set this to 'mic'.
args.volume number 1 Peak volume can range from 0 to an arbitrarily large number, but you probably shouldn't set it higher than 1.
args.loop boolean false If true, the audio will loop. This parameter only works for audio clips, and does nothing for oscillators.
args.useCache boolean true If false, the audio will be requested from the source URL without checking the audio cache.
args.rate number 1 How fast the audio clip plays, relative to its normal speed.
args.offset number 0 Where in the audio clip playback begins, measured in seconds from the start of the audio clip.
args.pitch string or number 'A4' Set a default pitch on the constructor if you don't want to set the pitch on play(). Pass in a string to play a specific pitch (12-TET, A440), or pass in a number to play that frequency, in hertz.
args.detune number 0 Set a default detune on the constructor if you don't want to set detune on play(). Detune is measured in cents. 100 cents is equal to 1 semitone.
args.panning number or array 0 Placement of the sound source. Pass in a number to use stereo panning, or pass in a 3-element array to use 3D panning. Note that some browsers do not support stereo panning.
args.panningModel string 'equalpower' See panning section.
args.rolloffFactor number 1
args.env object see below This is the ADSR envelope - attack, decay, (hold), sustain, release.
args.env.attack number 0 Time in seconds from onset to peak volume. Common values for oscillators may range from 0.05 to 0.3.
args.env.decay number 0 Time in seconds from peak volume to sustain volume.
args.env.sustain number 1 Sustain volume level. This is a percent of the peak volume, so sensible values are between 0 and 1.
args.env.hold number 3.14 Time in seconds to maintain the sustain volume level. If set to -1, the sound will be sustained indefinitely until you manually call stop().
args.env.release number 0 Time in seconds from the end of the hold period to zero volume, or from calling stop() to zero volume.
args.filter object or array none Pass an object to add a filter to this wad, or pass an array of objects to add multiple filters to this wad.
args.filter.type string 'lowpass' What type of filter is applied. Choose one of 'lowpass', 'highpass', 'bandpass', 'lowshelf', 'highshelf', 'peaking', 'notch', or 'allpass'.
args.filter.frequency number 600 The frequency, in hertz, to which the filter is applied.
args.filter.q number 1 Q-factor. No one knows what this does. The default value is 1. Sensible values are from 0 to 10.
args.filter.env object none The filter envelope.
args.filter.env.frequency number 800 If this is set, filter frequency will slide from filter.frequency to filter.env.frequency when a note is triggered.
args.filter.env.attack number 0.5 Time in seconds for the filter frequency to slide from filter.frequency to filter.env.frequency.
args.reverb object none Add reverb to this wad.
args.reverb.wet number 1 The volume of the reverberations.
args.reverb.impulse string none A URL for an impulse response file.
args.delay object none Add delay to this wad.
args.delay.delayTime number 0.5 Time in seconds between each delayed playback.
args.delay.wet number 0.25 Relative volume change between the original sound and the first delayed playback.
args.delay.feedback number 0.25 Relative volume change between each delayed playback and the next.
args.vibrato object none A vibrating pitch effect. Only works for oscillators.
args.vibrato.shape string 'sine' Shape of the lfo waveform. Possible values are 'sine', 'sawtooth', 'square', and 'triangle'.
args.vibrato.magnitude number 3 How much the pitch changes. Sensible values are from 1 to 10.
args.vibrato.speed number 4 How quickly the pitch changes, in cycles per second. Sensible values are from 0.1 to 10.
args.vibrato.attack number 0 Time in seconds for the vibrato effect to reach peak magnitude.
args.tremolo object none A vibrating volume effect.
args.tremolo.shape string 'sine' Shape of the lfo waveform. Possible values are 'sine', 'sawtooth', 'square', and 'triangle'.
args.tremolo.magnitude number 3 How much the volume changes. Sensible values are from 1 to 10.
args.tremolo.speed number 4 How quickly the volume changes, in cycles per second. Sensible values are from 0.1 to 10.
args.tremolo.attack number 0 Time in seconds for the tremolo effect to reach peak magnitude.
args.tuna object none Add effects from Tuna.js to this wad. Check out the Tuna.js documentation for more information.

Wad.prototype.play(args)

Property Type Default Description
args object none One big object with all of the arguments for playing this wad.
args.volume number 1 This overrides the value for volume passed to the constructor, if it was set.
args.wait number 0 Time in seconds between calling play() and actually triggering the note.
args.loop boolean false This overrides the value for loop passed to the constructor, if it was set.
args.offset number 0 This overrides the value for offset passed to the constructor, if it was set.
args.rate number 1 This overrides the value for rate passed to the constructor, if it was set.
args.pitch string 'A4' This overrides the value for pitch passed to the constructor, if it was set.
args.label string none A label that identifies this note. See 'play labels' for more information.
args.env object See above This overrides the value for env passed to the constructor, if it was set.
args.panning number or array 0 This overrides the value for panning passed to the constructor, if it was set.
args.filter object or array none This overrides the value for filter passed to the constructor, if it was set.
args.delay object none This overrides the value for delay passed to the constructor, if it was set.

If you intend to include a filter envelope or panning as an argument on play(), you should have set a filter envelope or panning when the wad was first instantiated. Pitches can be named by the note name, followed by the octave number. Possible values are from A0 to C8. Sharp and flat notes can be named enharmonically as either sharps or flats (G#2/Ab2). Check the Wad.pitches attribute for a complete mapping of note-names to frequencies.

The play() method returns a promise which resolves the wad itself, once the wad has finished playing. This makes it easy to play sounds sequentially in an async function.

const tick = new Wad({source : 'https://www.myserver.com/audio/clockTick.wav'})
const tock = new Wad({source : 'https://www.myserver.com/audio/clockTock.wav'})

const tickTock = async function(){
    await tick.play()
    await tock.play()
    await tick.play()
    await tock.play()
}
tickTock();

The time it takes for the promise to resolve, in milliseconds, can be read on the wad at tick.duration. The duration property is calculated based on the wad's volume envelope (env), the duration of the audio file, and the rate parameter. Note that there are other ways to manipulate the duration of the sound (for example, offset) that can cause the duration parameter to be misleading.

Wad.prototype.stop(label)

Property Type Default Description
label string none If you want to stop a note playing from this wad that is not the most recently triggered note, you can pass in the label of the notes you want to stop.

Wad.prototype.pause(label), Wad.prototype.unpause(args)

Audio clips (not oscillators) can be paused and unpaused during playback.

fullSong.play()
fullSong.pause()
// wait...
fullSong.unpause()

The pause method accepts the same arguments as stop. The unpause method accepts the same arguments as play.

Wad.prototype.setVolume(volume, timeConstant, label)

Property Type Default Description
volume number none (required) New volume setting.
timeConstant string none Time in seconds for 63% of the transition to complete.
label string none If you want to apply this change to a note playing from this wad that is not the most recently triggered note, you can pass in the label of the notes you want to stop.

Change the volume of a wad at any time, even during playback.

Wad.prototype.setPitch(pitch, timeConstant, label)

Property Type Default Description
pitch string none (required) New pitch setting.
timeConstant string none Time in seconds for 63% of the transition to complete.
label string none If you want to apply this change to a note playing from this wad that is not the most recently triggered note, you can pass in the label of the notes you want to stop.

Change the pitch of a wad that uses an oscillator as its source at any time, even during playback.

Wad.prototype.setDetune(detune, timeConstant, label)

Property Type Default Description
detune number none (required) New detune setting.
timeConstant string none Time in seconds for 63% of the transition to complete.
label string none If you want to apply this change to a note playing from this wad that is not the most recently triggered note, you can pass in the label of the notes you want to stop.

Change the detune of a wad that uses an oscillator as its source at any time, even during playback.

Wad.prototype.setPanning(panning, timeConstant)

Property Type Default Description
panning object or array none (required) New detune setting.
timeConstant string none Time in seconds for 63% of the transition to complete.

Change the panning of a wad at any time, even during playback.

Wad.prototype.setRate(rate)

Property Type Default Description
rate number none (required) New rate setting.

Change the rate of a wad that uses an audio clip as its source.

Wad.prototype.setReverb(wet)

Property Type Default Description
wet number none (required) New reverb.wet setting.

Change the volume of the reverb of a wad.

Wad.prototype.setDelay(delayTime, wet, feedback)

Property Type Default Description
delayTime number 0 New delay.delayTime setting.
wet number 0 New delay.wet setting.
feedback number 0 New delay.feedback setting.

Change the delay settings of a wad.

Wad.prototype.reverse()

Reverses a wad that uses an audio clip as its source.

Wad.setVolume(volume)

Property Type Default Description
volume number none (required) New volume setting for all wads.

Wad.stopAll(label)

Property Type Default Description
label string none Stop all currently playing, or all currently playing wads with a given label.

new Wad.Poly(args)

Property Type Default Description
args object none One big object with all the arguments for creating this polywad.
args.volume number 1 The default volume for this polywad.
args.panning number or array 0 The default panning for this polywad. See above.
args.filter object none Filter(s) applied to this polywad. See above.
args.delay object none Delay applied to this polywad. See above.
args.reverb object none Reverb applied to this polywad. See above.
args.tuna object none Tuna effects applied to this polywad. See above, and/or read the Tuna docs.
args.audioMeter object none Add a volume meter to this polywad that tells you if it's clipping.
args.audioMeter.clipLevel number 0.98 the level (0 to 1) that you would consider "clipping".
args.audioMeter.averaging number 0.95 how "smoothed" you would like the meter to be over time. Should be between 0 and less than 1.
args.audioMeter.clipLag number 750 how long you would like the "clipping" indicator to show after clipping has occured, in milliseconds.
args.compressor object none Add a compressor to this polywad.
args.compressor.attack number .003 The amount of time, in seconds, to reduce the gain by 10dB. This parameter ranges from 0 to 1.
args.compressor.knee number 30 A decibel value representing the range above the threshold where the curve smoothly transitions to the "ratio" portion. This parameter ranges from 0 to 40.
args.compressor.ratio number 12 The amount of dB change in input for a 1 dB change in output. This parameter ranges from 1 to 20.
args.compressor.release number 0.25 The amount of time (in seconds) to increase the gain by 10dB. This parameter ranges from 0 to 1.
args.compressor.threshold number -24 The decibel value above which the compression will start taking effect. This parameter ranges from -100 to 0.
args.recorder.options object ... The options passed to the MediaRecorder constructor.
args.recorder.onstop function ... The callback used to handle the onstop event from the MediaRecorder.

Wad.Poly.prototype.add(wad)

Property Type Default Description
wad object (wad or polywad) none The wad you want to add to this polywad.

Wad.Poly.prototype.remove(wad)

Property Type Default Description
wad object (wad or polywad) none The wad you want to remove from this polywad.

Wad.Poly.prototype.play(args)

This method calls play() on all the wads inside this polywad. It accepts the same arguments as Wad.prototype.play().

Wad.Poly.prototype.stop(label)

This method calls stop() on all the wads inside this polywad. It accepts the same arguments as Wad.prototype.stop().

Wad.Poly.prototype.setVolume(volume)

Change the volume for this polywad (separate from the volume from of the individual wads it contains).

Property Type Default Description
volume number none The new volume setting for this polywad.

Wad.Poly.prototype.setPitch(pitch)

This method sets the default pitch for each wad inside this polywad.

Property Type Default Description
volume number none The new volume setting for this polywad.

Wad.Poly.prototype.setPanning(panning, timeConstant)

Property Type Default Description
panning number or array none (required) New panning setting.
timeConstant string none Time in seconds for 63% of the transition to complete.

Change the panning of this polywad at any time, even during playback.

Wad.Poly.prototype.updatePitch()

This method is used for pitch detection. After calling it, the polywad will calculate the frequency of its output, and write that information to this.pitch and this.noteName.

Wad.Poly.prototype.stopUpdatingPitch()

This method stops the polywad from continuing to detect the pitch in real time.

Wad.assignMidiMap(midiMap, deviceIndex, success, failure)

This method is used to set up a MIDI event handler.

Property Type Default Description
midiMap function none (required) An event handler that describes what happens when your browser receives MIDI data.
deviceIndex number 0 If you have more than one connected MIDI device, this argument lets you specify which one you want to handle events for.
success function none A callback function that runs after successfully setting up the MIDI map.
failure function none A callback function that runs after failing to set up the MIDI map.

Showcase

Here are some examples of music, games, and other projects that people have built with WadJS. If you'd like your work to be featured here, feel free to send me a link, or just create a pull request.

Music by @Linsheng - https://lenshang.github.io/trigon.js/index.htm

Trombone.js by @bignimbus - https://github.com/bignimbus/trombone.js

wad's People

Contributors

ahultgren avatar aiyionprime avatar allannaranjo avatar amitmtrn avatar bignimbus avatar billshannon avatar coleww avatar dirkk0 avatar frastlin avatar jgladch avatar loganknecht avatar mattbierner avatar mwcz avatar ocwalk avatar rserota avatar sahalsadique avatar torch2424 avatar waynerad avatar zevanrosser avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wad's Issues

Can't set destination

I'm trying to set destination when initializing my Wad object, but I'm getting an error: SyntaxError: An invalid or illegal string was specified. A quick google search tells me this happens if you try to link nodes from different audio contexts together.

The problem is, since I can't access Wad's own context (I can see where it's defined in wad.js, but I can't access it from a different js file for some reason), I can't create my node in from the same context.

If there was a way to access wad's context from other JS files, or to tell Wad to use my own context, then I could do what I want to do.

wad for algorithmic composition

Hello everyone.
I'd like to use wad for algorithmic composition of music, which should work at runtime or be recorded.
So, my questions are:

  1. Can I change whatever parameter's value during playback? And
  2. Can I record a wave file with a javascript function?

Thanks in advance for either.

Cheers.

Wad features

Hello everyone.
My name is Ivano Arrighetta and I'm Italian.
I wonder if Wad supports these features:
filters:
lowpass
highpass
bandpass
notch

note playing:
chords
arpeggio

other:
mixer (assigning any audio output to a "virtual group")
loop points

Thanks in advance for any help.

Bye, Ivano.

FX order and FX loop

Since we did the thing where a user can pass multiple filters and specify the order, I think i can figure out how to do the same for everything else. Probably maintaining an array of the order things are passed to the constructor, and then using that during setuponplay time.

I'm also interested in making a sort of FX loop so that people could incorporate other libraries, and I think this would have to be a function that is passed the audiocontext and that/this and is overidden by the user. For things like audio visualizers and effect libraries.

Alllow changing volume during playback

The readme states you can change properties of a wad during playback by using it's setter functions, however, setVolume did not do this for me.

Currently, in another application that implements the use of wad (see here: https://github.com/julianpoy/Flyxer), I was able to set the volume of a wad doing the following:

    //Volume
    $scope.masterVolume = 100;
    $scope.setVolume = function() {

        for(var i=0;i<$scope.tracks.length;i++){
          if($scope.tracks[i].playing) {

              //Making variables in relation to the master volume

              $scope.tracks[i].player.nodes[4].output.gain.value = parseInt($scope.tracks[i].playbackVolume) / 100 * $scope.tracks[i].initVolumeMul * parseInt($scope.masterVolume) / 100;


              console.log(parseInt($scope.tracks[i].playbackVolume));
              console.log(parseInt($scope.masterVolume));
              console.log($scope.tracks[i].player.nodes[4].output.gain.value);
          }
        }
    }

Where the parseInt($scope.tracks[i].playbackVolume) / 100 * $scope.tracks[i].initVolumeMul * parseInt($scope.masterVolume) / 100; represents a slider bounded by angularJS' ngModel.

However, my problem is that I am accessing the node at index 4, where I would not like to assume at the volume node is at index 4. Is there a way that I can access the volume node without it's index? Thank You! I can fix this issue after this is figured out :)

External effects on mic input?

Hey sorry, so many issues! You've been so helpful in working them out so far though, really appreciate it. So I'm trying to add an external effect to the mic through Tuna. I followed the instructions for how to make it happen in the readme with the constructExternalFx and setUpExternalFxOnPlay methods, and noticed nothing was happening when I passed the arguments for it through to the play function.

Browsing quickly though the code, I saw that while constructExternalFx is being called, setUpExternalFxOnPlay is not anywhere and never goes off. I tried adding this to the same section of code above, and the function does run in that case, but the external effects are not actually applied.

Here's some sample code to work with:

var Wad = require('wad');
var Tuna = require('tuna');

Wad.prototype.constructExternalFx = function(arg, ctx) {
  console.log('constructExternalFx called');
  this.tuna = new Tuna(ctx);
  this.chorus = arg.chorus;
}

Wad.prototype.setUpExternalFxOnPlay = function(arg, context) {
  console.log('setUpExternalFxOnPlay called');
  if (arg.chorus) {
    var chorus = new this.tuna.Chorus({
      rate: arg.chorus.rate || this.chorus.rate,
      feedback: arg.chorus.feedback || this.chorus.feedback,
      delay: arg.chorus.delay || this.chorus.delay,
      bypass: arg.chorus.bypass || this.chorus.bypass
    });

    chorus.input.connect = chorus.connect.bind(chorus);
    this.nodes.push(chorus.input);
  }
}

var voice = new Wad({ source: 'mic' });

voice.play({
  chorus: {
      rate: 1.5,
      feedback: 0.2,
      delay: 0.0045,
      bypass: 0
    }
});

Edit: Also just tried adding these params to the Wad constructor -- no error but still no effects.

iOS sometimes distorted

Hi,

I've been working with wad on iOS 8 (phonegap/safari) loading small .m4a sounds, it's all good and wad is working well. Occasionally when I trigger many sounds it can start distorting. Do you have any tips for reducing memory? best file type, sample rate, poly volume, envelope usage?

I know this isn't stackoverflow, but wondered if you'd come across any tips that might be worth trying.

Thanks for the great work.
n

setVolume does not effect

Hello @rserota! Thanks for the great work, I really like the script!

I do have one problem. I try to get setVolume working at later times after loading, but it seems not to have effect. I am using latest Chrome. Here is a demo, bell.setVolume(0.5) works, but the one inside of the setTimeout does not. Also it does not work from any other function. Or am I missing anything here?

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="wad/build/wad.js"></script>
</head>
<body>
  <script>

var bell = new Wad({source : 'test.wav', volume : 1})
bell.play()
bell.setVolume(0.5);
setTimeout('bell.setVolume(0.1);console.log("voldown")',1000);

</script>
</body>
</html>

Calling stop on a nonplaying sound gives an error

Hello,
I am trying to stop all sounds at once. I don't know exactly what sounds are playing at any one moment in time, but I have a list of all sounds. I did the following code to stop all sounds:

sound_list.map(sound=>sound.stop())

I get the following error:

TypeError: this.gain[0] is undefined
["./node_modules/web-audio-daw/build/wad.js"]/</<["./src/wad.js"]/</Wad</Wad.prototype.stop
C:/path_to_project/node_modules/web-audio-daw/build/wad.js:3272
  3269 |     }
  3270 | }
  3271 | if ( !label ) {
> 3272 |     this.gain[0].gain.cancelScheduledValues(context.currentTime);
  3273 |     this.gain[0].gain.setValueAtTime(this.gain[0].gain.value, context.currentTime);
  3274 |     this.gain[0].gain.linearRampToValueAtTime(.0001, context.currentTime + this.env.release);
  3275 | }

Can we manage playing sequence of short duration MP3 files ?

I have a app developed using MIDI.js where I can create sequence of notes (for song) & play with useful parameters. Mainly I can manage duration of each note.

Can we achieve same using this library? I have set of all MP3 files for notes, is it possible to play them in sequence while controlling duration for each note ?
Please guide.

Changing the Rate of a Sound

Is there any way of changing the speed and or pitch of a recorded sound? Something along the lines of:
sound.rate(1.5)
or
sound.speed(1.5)
or
sound.pitch(1.5)

I know you can change the speed and pitch of oscillators, but I would like to change the pitch of a recorded sound. Howler does this with sound.rate(1.5).

Move Documentation/Usage into the wiki

Hello,

I was reading through the readme, and I was wondering if you would consider moving the usage into the wiki. It is a bit difficult to find what you are looking for with the single page design of the documentation. And the readme could be used a simple desciption of wad, and contain a link to the wiki for documentation

I would be more than happy to help with this in the next couple of weeks if you think it is a good idea.

Thanks!

Support npm/browserify

Just check if module.exports is available and set it to Wad. I can provide a pull request after this hackday is done :)

TypeError (iOS)

Great script! I'm really enjoying using it. Thanks for the great work.

I've come across an error on iOS

465: TypeError: undefined is not a function (evaluating 'b.createStereoPanner()')

But it works fine if I use the wad.js version from the demo...
http://www.codecur.io/javascripts/wad.js

Thanks
Nic

Plays an audio source file for a few seconds then cuts off

Weird issue, just curious if you quickly know a fix for this. When I load in an audio file as the source, it does play it for a few seconds, but then it stops. I would expect it to play the whole thing through, of course.

Here's a very simple example to demonstrate this issue. I have tested it with different audio sources, and with wav files as well but each time I get the same behavior, it stops abruptly after a few seconds ๐Ÿ˜•

http://wad-test.netlify.com

Is there a way to know when sound has been loaded?

I'd like to know if there is a way to be notified when a sound has loaded properly, through an "onLoad" mechanism, or maybe another way? (like you would have when using tag for example)

I didn't see anything into the documentation.

Apply effects on play, rather than on initialize?

Just a quick question -- it doesn't appear as if there is a way to, but can you apply effects for mic recording when play is called, rather than when the mic is initialized? The use case for this is if you want to allow the user to choose a vocal effect without having to re-initialize/accept the mic usage thing each time.

If there isn't, could you potentially push me in the right direction for implementation? I'd be happy to pull request it in, but don't have a vast amount of experience with the web audio API.

What's the best way to play the same sound multiple times

I'm working on a game engine and the same sound may be played simultaneously multiple times: should I create new Wad objects for each time it is played, or will calling play() several times on the created instance play the sound several times?

Btw, if I only have to create an instance: will doing myWad.setVolume() impact current playing sounds, or only future calls to myWad.play() ?

Demo page?

Looks interesting, but is it possible you could set up some kind of demo page to show the results of what this can do?

Any way to detect pitch from microphone input without calling play() ?

Trying to implement a simple tuner, but can't seem to figure out how to simultaneously listen to the user mic for frequencies and disallow the audio from playing back via speakers (e.g. to prevent feedback when users are not using headphones). Is there are way to do this? I see the feedback issue is mentioned in the docs, but no solution. Thoughts?

Update:

setting the tuner.output.gain.value = 0; seems to have solved the feedback issue by muting the gain node, but still allows the audio to be analyzed. might be worth mentioning in the docs (or some better solution) for others looking to use WAD for audio analysis purposes.

Audio stopping itself

I have just installed Wad on my website, and made a simple code for playing an audio file:
var music = new Wad({source : 'app/media/audio/ForgottenPlanet.mp3'});
music.play();

The audio file begins playing, but after some seconds it stops (tested on Firefox and Chrome).

Dramatically improving audio on iOS

Hi Raphael,

Following on from my discussion on #39 I've made a discovery. I noticed the audio on iOS using headphones is muffled compared to the same code on Macbook using headphone. I discovered if you add...

that.panning.node.panningModel = 'equalpower';

to the setUpPanningOnPlay function, it becomes crystal clear again and prevents distorting on the iPhone speaker. Whoopee!

See more here https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/panningModel

Hope this helps,
Nic

Cross browser issues?

"Cross-Browser Compatibility
I tried to future-proof Wad.js by using standards-compliant methods, but the cross-browser compatibility is still not great. It works best in Chrome, decently in Safari for iOS, and it works very poorly in Firefox. I have not tested it in any other browsers. I would greatly appreciate contributions to help Wad.js run optimally in any browser that supports Web Audio, especially mobile browsers."

What sorts of issues exists for cross-browser and mobile stuff? I'm interested in working on this.

Pitch detection : no nodes in .play()

Hi,
I'm testing the Pitch detection example with this script:

var voice = new Wad({source : 'mic' });
var tuner = new Wad.Poly({
    recConfig : { // The Recorder configuration object. The only required property is 'workerPath'.
        workerPath : 'bower_components/wad/src/Recorderjs/recorderWorker.js' // The path to the Recorder.js web worker script.
    }
   });
tuner.add(voice);
voice.play();

tuner.updatePitch() // The tuner is now calculating the pitch and note name of its input 60 times per second. These values are stored in tuner.pitch and tuner.noteName.

var logPitch = function(){
    console.log(tuner.pitch, tuner.noteName)
    requestAnimationFrame(logPitch)
};
logPitch();
// If you sing into your microphone, your pitch will be logged to the console in real time.

tuner.stopUpdatingPitch(); // Stop calculating the pitch if you don't need to know it anymore.

I have this console error when running the script:

 Uncaught TypeError: Cannot read property 'length' of undefined (wad:304)

After puting breakpoints, the error comes when the line 304 is called from the line 534 (else if ( this.source === 'mic' ) { plugEmIn(this, arg); } ). The first parameter of plugEmIn (this) does not contains the nodes property. So, when line 304 tries to loop in that.nodes, the var is undefined and the 'length' property is undefined.

But line 304 is called successfully a first time with this in that.node:
0: AnalyserNode
1: PannerNode
2: GainNode
length: 3
proto: Array[0]

I don't know if i did something wrong (I'm not familiar with this library), but the example does not seems to work.

And I'm on Chrome 40 for Mac OS X.

Thanks for your feedback ! The library seems really useful, and I can't wait to make it work ! ๐Ÿ˜ƒ

Multiple Sources?

In the spirit of allowing multiple filters, I'd like to add a feature that allows the user to specify more than one source wave. This opens up the possibility of more closely approximating real instrument sounds, if one were so inclined.

I don't see any reason why this couldn't be done in a very similar fashion to the way multiple filters are handled. Before I get started, does anyone have any thoughts?

Support for multiple filters

It would be great if you could pass arrays to the constructor and create combined filters:

filters : [
  {
    type : 'lowpass', 
    frequency : 600,
    q : 1,
    env : { 
      frequency : 800, 
      attack : 0.5 
    }
  },
  {
  // another filter
  }
]

including a compiled ES5 Version in the build folder?

Hello,
I am trying to build my app with Uglify.js in create-react-app, but I get the following error:

Failed to minify the code from this file:

        ./node_modules/web-audio-daw/build/wad.js:3093

Read more here: http://bit.ly/2tRViJ9

the create-react-app documentation says:

Some third-party packages don't compile their code to ES5 before publishing to npm. This often causes problems in the ecosystem because neither browsers (except for most modern versions) nor some tools currently support all ES6 features. We recommend to publish code on npm as ES5 at least for a few more years.

To resolve this:

  1. Open an issue on the dependency's issue tracker and ask that the package be published pre-compiled.
    โ€ข Note: Create React App can consume both CommonJS and ES modules. For Node.js compatibility, it is recommended that the main entry point is CommonJS. However, they can optionally provide an ES module entry point with the module field in package.json. Note that even if a library provides an ES Modules version, it should still precompile other ES6 features to ES5 if it intends to support older browsers.

Fork the package and publish a corrected version yourself.
3.
If the dependency is small enough, copy it to your src/ folder and treat it as application code.
In the future, we might start automatically compiling incompatible third-party modules, but it is not currently supported. This approach would also slow down the production builds.

It would be nice if WAD had ES5 compiled in the distro.

Tuna supprt broken when using UMD

When using Common.js to load WAD, Tuna is included in the build, but also recognizes the presence of module.exports and is not exposed to the window object. While this behaviour is correct, WAD hardcodedly tries to access Tuna via window object:

if ( window.Tuna != undefined ) {
        Wad.tuna = new Tuna(Wad.audioContext)
}

As a workaround I am using this:

var Tuna = require('tunajs');

window.Tuna = Tuna;
var Wad = require('./../vendors/wad/wad.min');

I suggest refactoring to a Common.js build which uses tunjas as dependency from NPM, so the min build will include it automatically and Common.js environments will treat Tuna as normal dependency. If you want, I can help you in this matter.

Sound only Plays 3 seconds

Hello!

I've been experimenting with Wad and no matter what set-up I've given it, the sound (.mp4 file) only plays for 3 or so seconds. The sound is part of a song I edited down to 17 seconds for this trial. I have put it on different web locations, browsers (Chrome 50.x ~ Safari 7.x), tried different songs, etc. - and it plays just a short bit (click the Button, that's all there is to the page):
http://wddtrialdemos.businesscatalyst.com/wadTrial.html

Mac 10.9.5
Any clues or directions to point me?
Thank You,
Jim

Allow setting filters properties before and during playback

Currently, in another application that implements the use of wad (see here: https://github.com/julianpoy/Flyxer), I was able to set the filter of a wad doing the following:

//Lowpass filter
    $scope.masterLowPass = 4000;
    $scope.setLowPass = function() {

      for(var i=0;i<$scope.tracks.length;i++){
        if($scope.tracks[i].playing){
          //Set the value
          $scope.tracks[i].player.filter[0].frequency = $scope.masterLowPass;

          //Set the node's value
          $scope.tracks[i].player.filter[0].node.frequency.value = $scope.masterLowPass;
        }
      }
    }

Where masterLowpass is bound to a slider using angularJS' ngModel.

Currently, I am only accessing the first filter in the array, implying there are multiple filters.

I am setting the wad as follows:

$scope.tracks[index].player = new Wad({
                source : 'file://' + $scope.tracks[index].uri,
                volume: 1.0,
                wait    : 0,
                loop: true,
                env : { hold : 100000000 },
                delay   : {
                      delayTime : 0.5,  // Time in seconds between each delayed playback.
                      wet : 0, // Relative volume change between the original sound and the first delayed playback.
                      feedback : 0, // Relative volume change between each delayed playback and the next.
                },
                reverb  : {
                    wet : 0,  // Volume of the reverberations.
                    impulse : 'sounds/impulse.wav' // A URL for an impulse response file, if you do not want to use the default impulse response.
                },
                filter  : {
                      type : 'lowpass', // What type of filter is applied.
                      frequency : 4000,       // The frequency, in hertz, to which the filter is applied.
                      q : 1,         // Q-factor.  No one knows what this does. The default value is 1. Sensible values are from 0 to 10.
                },
                tuna   : {
                    Bitcrusher : {
                        bits: 16,          //1 to 16
                        normfreq: 1,    //0 to 1
                        bufferSize: 4096  //256 to 16384
                    }
                }
            });

I was thinking I could simply allow developers to pass the index of the filter they would like to change. However, I dont see how they can set multiple filters. So I was hoping for a bit of help to solve this issue. Thank You!

Operators for PolyWad

Hello there again.
I wonder if PolyWad also supports substract and multiply methods, other than add.

Thanks in advance.

GUI reference error in soundStop()

Hi,

firstly: This is a great project!

Playing around with your GUI I encountered a little issue when pressing the stop button. A variable scope error is thrown and the sound doesn't stop.

//FireBug:
ReferenceError: coolSound is not defined play.js (line 59, col 4);

Cheers
jb

detune

Hello,

I've just started playing around with wad but really like what I'm seeing so far!

I'm having some trouble getting the detune functions to work properly.

for example, the following code does not play the sound clip detuned:

test = new Wad({source : '/sounds/guitar_E4.mp3', detune: -500});
test.play()

However, I can change while it's playing:

test = new Wad({source : '/sounds/guitar_E4.mp3'})
test.play()
test.setDetune(-500)

Playing it while simultaneously changing detune also works:

test = new Wad({source : '/sounds/guitar_E4.mp3'})
test.play().soundSource.detune.value = -500;

Any thoughts?

Thanks,
Nick

Making play a Promise

Hello,
Would it be possible to make play a Promise? I have some situations where I need to play sounds one after another and at the moment, I can only do this by setTimeout(callback, sound.decodedBuffer.duration)
Being able to use await would save a lot of extra coding on my part and would make the play function very useful for split scenes, footsteps, or any sequential sounds.

Creating Audio Sprites

Hello,
I would like support for audio sprites. Basically loading one long file that contains many sound effects that I can label and set the start and end values of.
This can be defined during the constructor as follows:
sprite: {
'labelName': [0, 500]
}
where the first number represents the offset and the second number represents the end value.
This is good for loading large amounts of sound effects for games, hacking soundfonts, making lists of sound effects, loading speech clips, and doing anything where there will be a lot of repetitive playing of many sound effects.
howlerJS has an implantation of this for reference.
Thanks,

Safari throwing an error on wad play due to missing detune property in soundSource

Hey there, am having an issue with safari and safari on iOS. When the code runs, it throws an error:

TypeError: undefined is not an object (evaluating 'this.soundSource.detune.value = arg.detune || this.detune')

on line 692 of wad.js. After a quick check of logging 'this' just before the error line I discovered that in chrome, soundSource contains a detune parameter, but in safari soundSource doesn't contain it.

Any thoughts of a workaround for this issue?

Can't switch panning type (3d/stereo) on play

Hi @rserota, great work on this script! It works like a charm, just one thing is not clear to me.

With code just like

var saw = new Wad({source: 'sine'});

stereo panning seems to be used by default. So following line:

saw.play({panning: [10, 0, 10]});

throws an exception Uncaught TypeError: Failed to set the 'value' property on 'AudioParam': The provided float value is non-finite. at line 473 in wad.js.
Setting up 3d panning manually:

var saw = new Wad({source: 'sine', panning: [0, 0, 0]}); // or 'panning: []'

fixes the thing.
And as I just figured out, this code:

var saw = new Wad({source: 'sine', panning: [0, 0, 0]});
saw.play({panning: 0.5});

gives again an error: Uncaught TypeError: Failed to execute 'setPosition' on 'PannerNode': The provided float value is non-finite. (line 468).

So, the question is if it's possible to change panning type after Wad is created? And can it be made automatically?

P.S. Should be in setUpPanningOnPlay not current Wad's but arg's panning type checked? Like

var setUpPanningOnPlay = function(that, arg) {
    var panning = arg && arg.panning; // can be zero provided as argument
    if (typeof(panning) === 'undefined') panning = that.panning.location;

    if (typeof(panning) === 'number') {
        that.panning.node = context.createStereoPanner();
        that.panning.node.pan.value = panning;
    }
    else {
        that.panning.node = context.createPanner();
        that.panning.node.setPosition(panning[0], panning[1], panning[2]);
    }

    that.nodes.push(that.panning.node);
};

or similar, I guess?

wad does not work in ios 9

The following code does not work in ios 9. touchend, mousedown, etc also fail.

document.getElementById('loop1').addEventListener("click", playSample);

function playSample(){
    var bell = new Wad({source : '/webaudio/audio/hot_pants.wav'});
bell.play();

   setTimeout(function(){
     bell.stop();
    },2000);
}

3D panning to surround speakers?

Hey!
Do you think it would be possible to use surround sound support for the 3D panning?
So you could play some sound effects from the back speakers of 5.1 surround system?

I know the HTML5 plays it well if it's in the source file. Does wad have any support for surround?

Thanks!

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.