mirror of https://github.com/nealey/vail.git
Noise generator, for #54
This commit is contained in:
parent
72f2df5d6c
commit
1c8ab50f0a
|
@ -268,6 +268,29 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="field is-horizontal">
|
||||||
|
<div class="field-label">
|
||||||
|
<label class="label">
|
||||||
|
<span data-i18n="label.gain">noise</span>:
|
||||||
|
<output for="noiseGain"></output>%
|
||||||
|
<i class="mdi mdi-volume-off muted"></i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="field-body">
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<input
|
||||||
|
id="noiseGain"
|
||||||
|
type="range"
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
value="0"
|
||||||
|
step="1">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="field is-horizontal">
|
<div class="field is-horizontal">
|
||||||
<div class="field-label">
|
<div class="field-label">
|
||||||
|
|
|
@ -1,35 +1,123 @@
|
||||||
|
import {AudioSource, AudioContextTime} from "./audio.mjs"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a noise generator with a low pass filter
|
* Create a white noise generator with a biquad filter
|
||||||
*
|
*
|
||||||
* @param {AudioContext} context Audio context
|
* @param {AudioContext} context Audio context
|
||||||
* @param {Number} lowpassFreq Low-pass filter frequency (Hz)
|
* @returns {BiquadFilterNode} Noise filter
|
||||||
* @returns {GainNode} Gain object for noise
|
|
||||||
*/
|
*/
|
||||||
function Noise(context, lowpassFreq = 100) {
|
function WhiteNoise(context) {
|
||||||
let bufferSize = 17 * context.sampleRate
|
let bufferSize = 17 * context.sampleRate
|
||||||
let noiseBuffer = context.createBuffer(1, bufferSize, context.sampleRate)
|
let noiseBuffer = new AudioBuffer({
|
||||||
|
sampleRate: context.sampleRate,
|
||||||
|
length: bufferSize,
|
||||||
|
})
|
||||||
let output = noiseBuffer.getChannelData(0)
|
let output = noiseBuffer.getChannelData(0)
|
||||||
for (let i = 0; i < bufferSize; i++) {
|
for (let i = 0; i < bufferSize; i++) {
|
||||||
output[i] = Math.random() * 2 - 1;
|
output[i] = Math.random() * 2 - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
let whiteNoise = context.createBufferSource();
|
let whiteNoise = context.createBufferSource()
|
||||||
whiteNoise.buffer = noiseBuffer;
|
whiteNoise.buffer = noiseBuffer
|
||||||
whiteNoise.loop = true;
|
whiteNoise.loop = true
|
||||||
whiteNoise.start(0);
|
whiteNoise.start(0)
|
||||||
|
|
||||||
let filter = context.createBiquadFilter()
|
let noiseFilter = new BiquadFilterNode(context, {type: "bandpass"})
|
||||||
filter.type = "lowpass"
|
whiteNoise.connect(noiseFilter)
|
||||||
filter.frequency.value = lowpassFreq
|
|
||||||
|
return noiseFilter
|
||||||
let gain = context.createGain()
|
|
||||||
gain.gain.value = 0.1
|
|
||||||
|
|
||||||
whiteNoise.connect(filter)
|
|
||||||
filter.connect(gain)
|
|
||||||
|
|
||||||
return gain
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Noise extends AudioSource {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {AudioContext} context
|
||||||
|
*/
|
||||||
|
constructor(context, noises=2) {
|
||||||
|
super(context)
|
||||||
|
|
||||||
|
this.whiteNoise = []
|
||||||
|
|
||||||
|
for (let i = 0; i < noises; i++) {
|
||||||
|
let wn = {
|
||||||
|
modulator: new OscillatorNode(context),
|
||||||
|
modulatorGain: new GainNode(context),
|
||||||
|
filter: WhiteNoise(context),
|
||||||
|
filterGain: new GainNode(context),
|
||||||
|
}
|
||||||
|
|
||||||
|
wn.modulator.frequency.value = 0
|
||||||
|
wn.modulatorGain.gain.value = 0
|
||||||
|
wn.filter.frequency.value = 800
|
||||||
|
wn.filterGain.gain.value = 0.8 / noises
|
||||||
|
|
||||||
|
wn.modulator.connect(wn.modulatorGain)
|
||||||
|
wn.modulatorGain.connect(wn.filter.frequency)
|
||||||
|
wn.filter.connect(wn.filterGain)
|
||||||
|
wn.filterGain.connect(this.masterGain)
|
||||||
|
|
||||||
|
wn.modulator.start()
|
||||||
|
this.whiteNoise.push(wn)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.SetNoiseParams(0, 0.07, 70, 400, 0.4)
|
||||||
|
this.SetNoiseParams(1, 0.03, 200, 1600, 0.4)
|
||||||
|
this.masterGain.gain.value = 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set modulator frequency
|
||||||
|
*
|
||||||
|
* You probably want this to be under 1Hz, for a subtle sweeping effect
|
||||||
|
*
|
||||||
|
* @param {Number} n Which noise generator
|
||||||
|
* @param {Number} frequency Frequency (Hz)
|
||||||
|
*/
|
||||||
|
SetNoiseModulator(n, frequency) {
|
||||||
|
this.whiteNoise[n].modulator.frequency.value = frequency
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set modulator depth
|
||||||
|
*
|
||||||
|
* The output of the modulator [-1,1] is multiplied this and added to the
|
||||||
|
* base frequency of the filter.
|
||||||
|
*
|
||||||
|
* @param {Number} n Which noise generator
|
||||||
|
* @param {Number} depth Depth of modulation
|
||||||
|
*/
|
||||||
|
SetNoiseDepth(n, depth) {
|
||||||
|
this.whiteNoise[n].modulatorGain.gain.value = depth
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set noise filter base frequency
|
||||||
|
*
|
||||||
|
* @param {Number} n Which noise generator
|
||||||
|
* @param {Number} frequency Frequency (Hz)
|
||||||
|
*/
|
||||||
|
SetNoiseFrequency(n, frequency) {
|
||||||
|
this.whiteNoise[n].filter.frequency.value = frequency
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set gain of a noise generator
|
||||||
|
*
|
||||||
|
* @param {Number} n Which noise generator
|
||||||
|
* @param {Number} gain Gain level (typically [0-1])
|
||||||
|
*/
|
||||||
|
SetNoiseGain(n, gain) {
|
||||||
|
this.whiteNoise[n].filterGain.gain.value = gain
|
||||||
|
}
|
||||||
|
|
||||||
|
SetNoiseParams(n, modulatorFrequency, depth, baseFrequency, gain) {
|
||||||
|
this.SetNoiseModulator(n, modulatorFrequency)
|
||||||
|
this.SetNoiseDepth(n, depth)
|
||||||
|
this.SetNoiseFrequency(n, baseFrequency)
|
||||||
|
this.SetNoiseGain(n, gain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Noise,
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import * as I18n from "./i18n.mjs"
|
||||||
import * as time from "./time.mjs"
|
import * as time from "./time.mjs"
|
||||||
import * as Music from "./music.mjs"
|
import * as Music from "./music.mjs"
|
||||||
import * as Icon from "./icon.mjs"
|
import * as Icon from "./icon.mjs"
|
||||||
|
import * as Noise from "./noise.mjs"
|
||||||
|
|
||||||
const DefaultRepeater = "General"
|
const DefaultRepeater = "General"
|
||||||
|
|
||||||
|
@ -46,6 +47,12 @@ class VailClient {
|
||||||
// Outputs
|
// Outputs
|
||||||
this.outputs = new Outputs.Collection(globalAudioContext)
|
this.outputs = new Outputs.Collection(globalAudioContext)
|
||||||
this.outputs.connect(globalAudioContext.destination)
|
this.outputs.connect(globalAudioContext.destination)
|
||||||
|
|
||||||
|
// Noise
|
||||||
|
this.noise = new Noise.Noise(globalAudioContext)
|
||||||
|
this.noise.connect(globalAudioContext.destination)
|
||||||
|
|
||||||
|
// App icon
|
||||||
this.icon = new Icon.Icon()
|
this.icon = new Icon.Icon()
|
||||||
|
|
||||||
// Keyers
|
// Keyers
|
||||||
|
@ -90,6 +97,9 @@ class VailClient {
|
||||||
this.inputInit("#masterGain", e => {
|
this.inputInit("#masterGain", e => {
|
||||||
this.outputs.SetGain(e.target.value / 100)
|
this.outputs.SetGain(e.target.value / 100)
|
||||||
})
|
})
|
||||||
|
this.inputInit("#noiseGain", e => {
|
||||||
|
this.noise.SetGain(e.target.value / 100)
|
||||||
|
})
|
||||||
let toneTransform = {
|
let toneTransform = {
|
||||||
note: Music.MIDINoteName,
|
note: Music.MIDINoteName,
|
||||||
freq: Music.MIDINoteFrequency,
|
freq: Music.MIDINoteFrequency,
|
||||||
|
|
Loading…
Reference in New Issue