2015-06-03 69 views
11

我通过这真棒文章的工作:https://jackschaedler.github.io/circles-sines-signals/dft_introduction.html自定义波形

我想利用网络音频API的PeriodicWave对象来实现这个演示:enter image description here

然而,当我设置周期波与这些设置:

var real = new Float32Array([0,0,1,0,1]); 
var imag = new Float32Array(real.length); 
var customWave = context.createPeriodicWave(real,imag); 
osc.setPeriodicWave(customWave); 

我输出波看起来像这样:

enter image description here 这里是完整的代码:http://jsbin.com/zaqojavixo/4/edit 要查看波形,请按数次播放声音。

我相信这些应该投其所好,所以这里是我的问题:

  1. 我失去了一些关于这里的理论基础还是我只是实现它是否有误? PeriodicWave对象应该如文章所述做同样的事情吗?
  2. 如果我采取了错误的做法,我将如何在Web Audio API中实现此图表?通过将不同频率的两个不同正弦波连接到相同的增益节点,我能够进行匹配 - 这与使用PeriodicWave对象有什么不同?
  3. 我是DSP和Web Audio API的新手 - 任何建议阅读将不胜感激!其次,在我的例子中,在将正确的数据绘制到画布之前,我必须推动'播放声音'按钮几次 - 分析器似乎在振荡器后面,即使analyser.getFloatTimeDomainData()在我启动振荡器后,在这里发生了什么?

编辑:正如在评论中指出,我的图是倒挂(画布0,0是左上角)。

回答

9

注意,第一阵列限定的余弦项,第二正弦项:

real参数表示一组余弦项(传统上 的A条款)。在音频术语中,第一个元素(索引0)是周期性波形的直流偏移量 。第二个元素(索引1) 代表基频。第三个元素表示 第一个泛音,依此类推。第一个元素被忽略,实现必须在内部将其设置为零。

imag参数表示的正弦项(传统 的乙术语)的阵列。第一个元素(索引0)应该设置为零(并且 将被忽略),因为该项不存在于傅立叶级数中。 第二个元素(索引1)表示基频。 第三个元素表示第一个泛音,依此类推。

Source

你会看到你会得到预期的波形,但“逆转”(画倒挂感谢@Julian指出这一点在他的答案 - 下面固定):

snap

(我在这里用代码替换了阵列:)
已更新原始代码中的固定绘图问题

//setup audio context 
 
window.AudioContext = window.AudioContext || window.webkitAudioContext; 
 
var context = new window.AudioContext(); 
 

 
//create nodes 
 
var osc; //create in event listener so we can press the button more than once 
 
var masterGain = context.createGain(); 
 
var analyser = context.createAnalyser(); 
 

 
//routing 
 
masterGain.connect(analyser); 
 
analyser.connect(context.destination); 
 

 
var isPlaying = false; 
 

 
//draw function for canvas 
 
function drawWave(analyser, ctx) { 
 
    
 
    var buffer = new Float32Array(1024), 
 
     w = ctx.canvas.width; 
 
    
 
    ctx.strokeStyle = "#777"; 
 
    ctx.setTransform(1,0,0,-1,0,100.5); // flip y-axis and translate to center 
 
    ctx.lineWidth = 2; 
 
    
 
    (function loop() { 
 
    analyser.getFloatTimeDomainData(buffer); 
 
    
 
    ctx.clearRect(0, -100, w, ctx.canvas.height); 
 

 
    ctx.beginPath(); 
 
    ctx.moveTo(0, buffer[0] * 90); 
 
    for (var x = 2; x < w; x += 2) ctx.lineTo(x, buffer[x] * 90); 
 
    ctx.stroke(); 
 
    
 
    if (isPlaying) requestAnimationFrame(loop) 
 
    })(); 
 
} 
 

 
//button trigger 
 
$(function() { 
 
    var c = document.getElementById('scope'), 
 
     ctx = c.getContext("2d"); 
 
    
 
    c.height = 200; 
 
    c.width = 600; 
 
    
 
    // make 0-line permanent as background 
 
    ctx.moveTo(0, 100.5); 
 
    ctx.lineTo(c.width, 100.5); 
 
    ctx.stroke(); 
 
    c.style.backgroundImage = "url(" + c.toDataURL() + ")"; 
 
    
 
    $('button').on('mousedown', function() { 
 
    osc = context.createOscillator(); 
 
    //osc settings 
 
    osc.frequency.value = 220; 
 
    var imag= new Float32Array([0,0,1,0,1]); // sine 
 
    var real = new Float32Array(imag.length); // cos 
 
    var customWave = context.createPeriodicWave(real, imag); // cos,sine 
 
    osc.setPeriodicWave(customWave); 
 

 
    osc.connect(masterGain); 
 
    osc.start(); 
 
    isPlaying = true; 
 
    
 
    drawWave(analyser, ctx); 
 
    }); 
 

 
    $('button').on('mouseup', function() { 
 
    isPlaying = false; 
 
    osc.stop(); 
 
    }); 
 
});
button {position:fixed;left:10px;top:10px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<button>Play the sound</button> 
 
<canvas id='scope'></canvas>

2

演示和输出之间的唯一区别是两个音调之间的相位关系。演示是y=sin(x) + sin(2x),你的是y=sin(x) + sin(2x + pi/2)。我并不清楚这个阶段是从哪里来的,但我不认为这是你所做的任何事情。

下面是从钨阿尔法一些图:

y=sin(x) + sin(2x)

y=sin(x) + sin(2x + pi/2)

1

createPeriodicWavereal阵列是余弦部分(或一个术语),而imag阵列(该b术语)是正弦部分。

参见:http://en.wikipedia.org/wiki/Fourier_series

我觉得你刚刚倒二。在它的文章中写道:

其中Ai是第i个正弦的振幅,fi是第i个正弦的频率。

所以它是你的imag数组(正弦部分)应该是[0,0,1,0,1],你的真实数组应该是[0,0,0,0,0]。

像这样:

var imag = new Float32Array([0,0,1,0,1]); 
var real = new Float32Array(real.length); 

尝试在你的jsbin你将它的作品,唯一的事情,它会被反转,因为你是在否定绘画(意为0坐标的顶部,而不是底部)。要获得文章中的内容,请反向绘制或使用您的imag数组:[0,0,-1,0,-1]。

如果你要玩一点不同imagreal配置并查看结果,你可以在这里看到:http://themusictoolbox.net/waves/