【问题标题】:How do I generate this tick sound in JavaScript?如何在 JavaScript 中生成这种滴答声?
【发布时间】:2019-11-04 13:00:39
【问题描述】:

在 a.bestmetronome.com 上,他们有一个节拍器,可以根据噪音产生滴答声。

但是,我无法弄清楚“刻度”是如何生成的。虽然我能够从 Audacity 中找出“滴答”生成器:

;; Metronome tick by Steve Daulton.
(defun metronome-tick (hz peak)
    (let* ((ln 300)
        (sig-array (make-array ln))
        (x 1))
    ;; generate some 'predictable' white noise
    (dotimes (i ln)
        (setf x (rem (* 479 x) 997))
        (setf (aref sig-array i) (- (/ x 500.0) 1)))
        (setf sig (sim (s-rest-abs 0.2)
            (snd-from-array 0 44100 sig-array)))
    (setf sig
        (mult (abs-env (pwev 10 (/ ln 44100.0) 2 1 0))
            (highpass8  (lowpass2 sig (* 2 hz) 6)
                        hz)))
    (let ((gain (/ (peak sig 300))))
    ; The '1.11' factor makes up for gain reduction in 'resample'
    (mult (abs-env (pwlv 1.11 0.02 1.11 0.05 0 ))
        (jcrev (mult peak gain sig) 0.01 0.1)))))

;; Single tick generator:
(defun get-metronome-tick (hz gain)
    (resample
        (sound-srate-abs 44100 (metronome-tick hz gain))
        *sound-srate*))

这是我目前在生成它的函数中拥有的刻度:

function scheduleNote(beatNumber, time)
{
    // push the note on the queue, even if we're not playing.
    notesInQueue.push({
        note: beatNumber, 
        time: time
    });

    if (beatNumber % 4 === 0)          // beat 0 == high pitche
    {
        var fader = actx.createGain();
        fader.gain.value = 2;
        fader.connect(distor);

        var oscil0 = actx.createOscillator();
        oscil0.frequency.value = noteFreq[0];
        oscil0.connect(fader);

        var oscil1 = actx.createOscillator();
        oscil1.frequency.value = noteFreq[0] * 2;
        oscil1.connect(fader);

        oscil0.start(time);
        oscil1.start(time);
        oscil0.frequency.exponentialRampToValueAtTime(noteFreq[1], time + noteLength);
        oscil1.frequency.exponentialRampToValueAtTime(noteFreq[1] * 2, time + noteLength);
        fader.gain.linearRampToValueAtTime(0, time + noteLength);
        oscil0.stop(time + noteLength);
        oscil1.stop(time + noteLength);
    }
}

但是,生成刻度本身的脚本是基于 Lisp 的奈奎斯特语言。我怎样才能在 JavaScript 中编写一些东西来实现 Lisp/Nyquist 生成器的功能,但使用 AudioContext 和 Web Audio 函数?

我在网上尝试了许多翻译工具,但似乎没有一个能到达我需要的地方。另外,如何确保我开始的空缓冲区(填充了上面代码生成的噪声样本)完全根据 JS 中的time 变量开始?

“highpass8”可以使用createBiquadFilter() 完成,并且可以从随机数开始创建噪声。我之前使用过 Web Audio API,并用它制作了噪音和音调发生器。但是,在这个任务上我卡住了。


另外,我尝试查看 a.bestmetronome.com 的源代码,但显然他们使用 Flash 生成声音,但我找不到实际生成滴答声的 ActiveX 对象。我怎样才能复制他们生成刻度的方式? (也使用 Web Audio API)

【问题讨论】:

标签: javascript html5-audio audiocontext nyquist


【解决方案1】:

问题中编写的奈奎斯特代码将无法运行,因为尚未定义 s-rest-abs 函数。这个版本可以在 Audacity 的“Nyquist Prompt”效果下运行(参见:https://manual.audacityteam.org/man/nyquist_prompt.html

;version 4
;type generate

;; Metronome tick by Steve Daulton.
(defun metronome-tick (hz peak)
    (let* ((ln 300)
        (sig-array (make-array ln))
        (x 1))
    ;; generate some 'predictable' white noise
(dotimes (i ln)
    (setf x (rem (* 479 x) 997))
    (setf (aref sig-array i) (- (/ x 500.0) 1)))
        (setf sig (sim (abs-env (s-rest 0.2))
            (snd-from-array 0 44100 sig-array)))
    (setf sig
        (mult (abs-env (pwev 10 (/ ln 44100.0) 2 1 0))
            (highpass8  (lowpass2 sig (* 2 hz) 6)
                        hz)))
    (let ((gain (/ (peak sig 300))))
    ; The '1.11' factor makes up for gain reduction in 'resample'
    (mult (abs-env (pwlv 1.11 0.02 1.11 0.05 0 ))
        (jcrev (mult peak gain sig) 0.01 0.1)))))

;; Single tick generator:
(defun get-metronome-tick (hz gain)
    (resample
        (sound-srate-abs 44100 (metronome-tick hz gain))
        *sound-srate*))

(get-metronome-tick 440 0.8)

最后一行调用函数“get-metronome-tick”。

(作为 Audacity Rhythm Track 生成器的作者,我很乐意提供有关此代码到底在做什么的更多详细信息,尽管我认为在问题的上下文中没有必要这样做。)

正如您在 Audacity 的 Nyquist Prompt 中运行此代码所见,它会生成 2200 个样本值的序列(在 44100 Hz 采样率下为 50 毫秒)。它是这样编写的,以便整个插件可以分布在一个小文本文件中。

我不是 JS 专家,但我希望在 JS/HTML5 中简单地为示例数据创建一个小音频文件会更容易。由于不需要非常高的频率,这可能是一个非常小的低采样率文件(例如 550 个采样率,采样率为 11025 Hz)或压缩格式,如 OGG 或 MP3。该文件可以在 Audacity 中通过使用上述代码生成刻度然后导出来创建。

然后可以加载声音,例如:

<audio src="tickSound.ogg" type="audio/ogg"></audio>

另见:https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Using_Web_Audio_API

https://www.w3.org/TR/webaudio/

【讨论】:

  • 谢谢!我注意到我能够使用带通过滤的白噪声和重度削波获得明显的滴答声。
猜你喜欢
  • 2018-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-25
  • 1970-01-01
  • 2011-03-05
相关资源
最近更新 更多