音频合成最佳实践

标签 audio waveform synthesis

我想从头开始编写一个音乐程序。大目标:是的。我没有明确的意图去完成任何事情。这主要是个人学习项目。 :P

第一步是构建振荡器和仪器。乐器可能是振荡器和滤波器(以及包络+效果)的组合。现在,我的第一个问题是:我应该如何构建波浪发生器?

假设我有一首轨道用 X 乐器演奏不同的音符。我想最好“预渲染”这些音符。因此,我需要支付预付费用来运行我的波函数来生成代表波的数字数组。假设我想以 44.1KHz 的采样率执行此操作,这是否意味着每个乐器每秒会有 44.1k 个声音项目的数组?

我认为这个问题本身与语言无关。但我计划使用 JavaScript,因为我将在浏览器中运行它。

最佳答案

音频只是一条曲线 - 因此为了构建振荡器,您需要使用这个算法来输出曲线。软件是数字而非模拟的,要求将曲线定义为一系列时间点(样本),其中其值是音频曲线的瞬时高度。通常这些样本每秒发生 44100 次,即赫兹。

查看 Web Audio API - 其功能非常强大并且非常受支持。只是为了了解其灵活性,请查看由 Google 内部员工编写的演示

Web Audio Playground
http://webaudioplayground.appspot.com/

在其他音频小部件中,它提供黑盒振荡器,但允许您滚动自己的振荡器并实时渲染合成或基于文件的音频数据。它是模块化的,因此每个组件都称为一个节点 - 您可以通过链接这些节点来构建

这里是用于合成音频(振荡器)的回调的定义

function setup_onaudioprocess_callback(given_node) {

    given_node.onaudioprocess = (function() {

        return function(event) {

            if (allow_synth) {

                // console.log('inside main_glob callback   onaudioprocess   BUFF_SIZE ', BUFF_SIZE);

                var synthesized_output_buffer;

                // stens TODO - how to pass in own buffer instead of being given object: out so I can do a circular ring of such buffers

                synthesized_output_buffer = event.outputBuffer.getChannelData(0); // stens TODO - do both channels not just left

                var phi = 0,
                    dphi = 2.0 * Math.PI * given_node.sample_freq /
                    given_node.sample_rate;

                for (var curr_sample = 0; curr_sample < given_node.BUFF_SIZE; curr_sample++, phi += dphi) {

                    synthesized_output_buffer[curr_sample] = Math.sin(phi);
                }

                given_node.sample_freq *= given_node.freq_factor;

                if (given_node.sample_freq <
                    given_node.MIN_FREQ) {

                    given_node.freq_factor = given_node.increasing_freq_factor;

                } else if (given_node.sample_freq > given_node.MAX_FREQ) {

                    given_node.freq_factor = given_node.decreasing_freq_factor;
                }

                // ---

                audio_display_obj.pipeline_buffer_for_time_domain_cylinder(synthesized_output_buffer,
                    BUFF_SIZE, "providence_2");
            }
        };

    }());
}

它将与使用 createScriptProcessor 生成的节点相关使用

function init_synth_settings(given_node, g_MIN_FREQ, g_MAX_FREQ, g_BUFF_SIZE, g_decreasing_freq_factor, g_increasing_freq_factor) {

    given_node.MIN_FREQ = g_MIN_FREQ;
    given_node.MAX_FREQ = g_MAX_FREQ;

    given_node.sample_freq = given_node.MIN_FREQ; // Hertz
    given_node.BUFF_SIZE = g_BUFF_SIZE;

    given_node.decreasing_freq_factor = g_decreasing_freq_factor;
    given_node.increasing_freq_factor = g_increasing_freq_factor;
    given_node.freq_factor = g_increasing_freq_factor;
}

var this_glob_01 = audio_context.createScriptProcessor(BUFF_SIZE, 1, 1);

init_synth_settings(this_glob_01, 20, 300, BUFF_SIZE, 0.98, 1.01);

setup_onaudioprocess_callback(this_glob_01);

这应该可以帮助你渡过难关

关于音频合成最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26678093/

相关文章:

jquery - 输入网址后的音频长度

ios - AVPlayer 从 iOS 7 后台通知播放音频

javascript - 我想使用条形图在javascript中可视化声音

python - 在 Python 中生成音频波形图

php - 音频波形许可被拒绝bbcrd

javascript - Web Audio API - 可以解调 Osc 的特定 LR channel 吗?

javascript - 在触摸屏上添加声音

wpf - WPF 中的 Windows 窗体绘制等效事件

verilog - 为什么我们在 Verilog/Systemverilog 中使用 Always Block 设计的组合电路中使用 Blocking 语句?为什么不是非阻塞?

system-verilog - 在可综合的 SystemVerilog 中的枚举 typedef 中使用 don't-care