2014-10-31 76 views
2

我想从头编程一个音乐程序。大目标:是的。我没有明确的意图完成任何事情。这主要是一个个人学习项目。 :P音频合成最佳实践

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

想象一下,我有一首跟乐器X演奏不同音符的曲目。我想最好是“预先渲染”这些音符。所以我会支付预付费用来运行我的波函数来生成一个代表波的数字数组。假设我想以44.1KHz的采样率来做到这一点,这是否意味着每个乐器每秒钟会有44.1k项目的声音?

我认为这个问题本身是语言不可知的。但我打算使用JavaScript,因为我会在浏览器中运行它。

回答

1

音频只是一条曲线 - 所以要建立你的振荡器,你会出现这个算法来输出一条曲线。数字不是模拟的软件要求将曲线定义为一系列时间点(样本),其值是音频曲线的瞬时高度。通常这些样本每秒发生44100次,即。赫兹。

结帐Web音频API - 其惊人的强大和非常支持。只是为了得到它的灵活性结帐这个演示由谷歌职员内幕

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); 

产生这应该让你渡过了难关

+0

感谢您连接到操场。虽然这篇文章的其余部分基本上是我的问题的重演。也许我不清楚?我正在寻找关于实际实施方法的提示! :) – simme 2014-10-31 19:40:06

+0

感谢您的代码!但你在哪里找到这个?在https://github.com/cwilso/WebAudio/?我是否因为找不到而失明? :P – simme 2014-10-31 20:18:47

+0

上面的代码是从我的第一个JavaScript项目https://github.com/scottstensland/webgl-3d-animation/blob/master/src/webaudio_tooling.js – 2014-11-01 14:10:13

1

说我想以44.1KHz的采样率来做到这一点,这是否意味着我将有每个乐器每秒44.1k项目的声音数组?

就是这样,你将有44.1k样本,以浮点数或字节的形式(取决于你使用的是什么语言)。

下面是在44.1kH产生与基于浮动的样品1秒的正弦波一些伪代码:

RATE = 44100 
frequency = 440 
for(i = 0; i < RATE; i++){ 
    array[i] = sin(i*2*PI*frequency/RATE); 
} 
0
#include <stdio.h> 
#include <math.h> 
#include <stdlib.h> 

#define PI 3.141592 

int main(void){ 

double RATE = 44100; 
double frequency = 440; 
double Amp=16384;//amplitude of signal 
FILE *file; 
double data; 
    file=fopen("dummyf.pcm", "w"); 

for(double i = 0; i < RATE; i++){ 
    data = Amp*sin(i*2*PI*frequency/RATE); 
    fputc(data, file); 
} 

fclose(file); 

return 0; 
} 

我想尝试不同的解决方案使用的文件写下来的数据。它的优点是你不需要在内存中创建一个大数组。使用函数构建自己的数据并将其存储在pcm文件中比存储在内存中更容易,不是吗? LE:您应该使用directx DirectMusic,因为它使用f.m.合成许多仪器。

LE2:我的程序现在预期

+0

真的很奇怪的代码,这个。应该是'int main',你完全不使用'array [0]',当数组不存在时,你将'array [2]'写入磁盘,由'malloc'分配,你不检查文件是否可以打开,你正在比较'int i'和'RATE'是'double'... – MSalters 2015-01-09 13:07:43

1

正如前面的应答者都指出它不工作,你可以用C编写一个简单的程序(或与此有关的任何语言)输出一系列值代表声音样本或声波中的点。如果您将这些值写入文本文件,则可以使用soxhttp://sox.sourceforge.net/)等程序将该文件转换为.wav文件。然后,您可以在电脑上播放wav文件,并通过扬声器收听声音。