ino
ino

Reputation: 273

How do I make an OscillatorNode oscilate between 0 and 1 in Web Audio?

To my understanding, all waves from the oscillator oscillate from -1 to 1.

I want to make them oscillate from 0 to 1, still using sine and square waves.

Why? for example a vibrato that only pitches up (pitch never goes below the main note, like a guitar vibrato).

In the vibrato case. the closest thing I got to was to play the note in the middle of the two notes and oscillate from there, but the tones aren't exactly right:

window.AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContext();

// notes are semitones from soundFreq
var soundFreq = 440; // a4
var mainNote = 0.0;  // a4
var bendNote = 4.0;  // c#4 (major third interval)

// nSoundSource is the sound we're playing, on the a4
var nSoundSource = audioContext.createOscillator();
nSoundSource.type = 'triangle';
nSoundSource.frequency.value = soundFreq; // a4

// at 1 second sound plays the note between a4 and c#4: b4
nSoundSource.frequency.setValueAtTime(
  intervalToFrequency((mainNote + bendNote) / 2) * soundFreq,
  audioContext.currentTime + 1.0
);

// at 3 seconds, sound returns to a4
nSoundSource.frequency.setValueAtTime(
  soundFreq,
  audioContext.currentTime + 3.0
);


// gain to change the detune of the played sound
var nGainSoundFreq = audioContext.createGain();

// if amplitude is the whole interval (400 cents), the value should be half of that, so in this case 200 cents
nGainSoundFreq.gain.value = ((mainNote + bendNote) / 2) * 100; // 200 cents up and down

// oscillator to make the vibrato on the gain
var nGainSoundFreqOsc = audioContext.createOscillator();
nGainSoundFreqOsc.type = 'square'; // try with sine too
nGainSoundFreqOsc.frequency.value = 3;
nGainSoundFreqOsc.start(audioContext.currentTime + 1.0);
nGainSoundFreqOsc.stop(audioContext.currentTime + 3.0);

// enable vibrato
nGainSoundFreqOsc.connect(nGainSoundFreq);
nGainSoundFreq.connect(nSoundSource.detune);

// play the sound
nSoundSource.connect(audioContext.destination);
nSoundSource.start(audioContext.currentTime);
nSoundSource.stop(audioContext.currentTime + 4.0);


// helper to convert semitones to frequency
function intervalToFrequency(interval) {
    return Math.pow(2, interval / 12);
}

I know I can achieve the vibrato using other techniques, that's not the point. I want to know if it is possible to make a NodeOscillator oscilate between 0 and 1.

Upvotes: 0

Views: 653

Answers (1)

Raymond Toy
Raymond Toy

Reputation: 6048

The square wave oscillator does go from -1 to 1, but not quite the way you expect because it is normalized. Due to bandlimiting, there is some ringing which at the discontinuities, so the actual "square" top of the wave is slightly below 1.

You could add a gain to the output to scale it up a little. The best solution is to use PeriodicWave to create your own square wave but turn off this normalization. Then the square top will have amplitude 1, but some parts of the wave will exceed 1.

Upvotes: 1

Related Questions