2014-10-31 34 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文件,並通過揚聲器收聽聲音。