2013-09-08 6 views
1

자바 스크립트에서 사인 스윕을 생성하려고했지만 몇 가지 문제가 있습니다. 결과 오디오 웨이브가 잘못 들립니다 (분리, 클릭 등).자바 스크립트에서 주파수 사인 스윕 생성

디버깅을 위해 데이터를 플롯하고 비정상적인 방식으로 데이터가 변경되는 곳을 찾았습니다.

저는 오디오 프로그래밍에 대한 경험이 거의 없으므로 디버깅 및 문제 발견에 어려움이 있습니다.

저는 주파수가 100Hz에서 200Hz로 돌아가고 100Hz로 되돌아 가고 분당 55 사이클로 사인을 만들어 봅니다. 지역 주변 일부 값 산출 여기 http://www.shareimage.ro/images/pxf8xb8r18je56drwmy6.png

된다 : 은 합니다 (알주세요 여기

function SweepFreq(cyclesPerMinuteElement, lowFreqElement, highFreqElement) { this.cyclesPerMinute = 55; this.cycle_length = 60.0/this.cyclesPerMinute; this.lowFreq = 100; this.highFreq = 200; this.time = 0.0; this.buffer = null; this.initSweep = function (element) { var sampleRate = 44100.0 var seconds = 12; var length = sampleRate*seconds; this.buffer = new Float32Array(length); this.generateSineWave(this.buffer, sampleRate, seconds) } this.generateSineWave = function(buffer, sampleRate, seconds) { var deltaTime = 1.0/(sampleRate); var old_v = 0; var old_frequency = 0; var old_waveLength = 0; var old_timePos = 0; var old_pos = 0; var old_val = 0; for (var i = 0; i < sampleRate*seconds; i++) { var v = this.getProgress(deltaTime); var frequency = ((this.highFreq-this.lowFreq)*v)+this.lowFreq; var waveLength = 1.0/frequency; var timePos = i/sampleRate; var pos = timePos/waveLength; var val = Math.sin(pos * 2.0 * Math.PI); this.buffer[i] = val; // debug stuff var diff_v = old_v-v; var diff_frequency = old_frequency-frequency; var diff_waveLength = old_waveLength - waveLength; var diff_timePos = old_timePos - timePos; var diff_pos = old_pos - pos; var diff_val = old_val - val; old_v = v; old_frequency = frequency; old_waveLength = waveLength; old_timePos = timePos; old_pos = pos; old_val = val; if (i > (5*4096+3570) && i < (5*4096+3590)) { // console.log(v, frequency, waveLength*100000000.0, diff_v, diff_frequency, diff_waveLength*100000000.0); console.log(timePos, pos, val, diff_timePos, diff_pos, diff_val); } // end of debug stuff } } this.getProgress = function(deltaTime) { this.time += deltaTime; if (this.time > this.cycle_length) this.time -= this.cycle_length; var progress = this.time/this.cycle_length; if (progress < 0.5) { return progress*2.0; } else { return 1.0-((progress-0.5)*2.0) } } } 

플롯의 관련 영역의 화상이다

는 코드 timePos 델타의 차이)

v, frequency, waveLength*100000000.0, diff_v, diff_frequency, diff_waveLength*100000000.0 
0.9998941798945973 199.98941798945972 500026.4564261616 -0.0000415721844293504 -0.004157218442941257 10.394362057533634 
0.9999357520790266 199.99357520790267 500016.0624962343 -0.0000415721844293504 -0.004157218442941257 10.39392992724722 
0.999977324263456 199.99773242634558 500005.6689984104 -0.0000415721844293504 -0.004157218442912836 10.393497823935755 
0.9999811035521147 199.99811035521145 500004.7241566063 -0.0000037792886586895946 -0.00037792886587340035 0.9448418041013706 
0.9999395313676853 199.99395313676854 500015.1176151494 0.0000415721844293504 0.004157218442912836 -10.393458543117573 
0.999897959183256 199.9897959183256 500025.5115057935 0.0000415721844293504 0.004157218442941257 -10.393890644087161 
0.9998563869988266 199.98563869988266 500035.90582856524 0.0000415721844293504 0.004157218442941257 -10.394322771771492 
0.9998148148143973 199.98148148143974 500046.3005834917 0.0000415721844293504 0.004157218442912836 -10.394754926430771 
0.9997732426299679 199.97732426299677 500056.6957706 0.0000415721844293504 0.004157218442969679 -10.39518710832521 
0.9997316704455386 199.97316704455386 500067.09138991666 0.0000415721844293504 0.004157218442912836 -10.395619316674182 
0.9996900982611092 199.96900982611092 500077.4874414691 0.0000415721844293504 0.004157218442941257 -10.396051552431784 
0.9996485260766799 199.96485260766798 500087.883925284 0.0000415721844293504 0.004157218442941257 -10.396483814904128 
0.9996069538922505 199.96069538922507 500098.28084138845 0.0000415721844293504 0.004157218442912836 -10.396916104438159 
0.9995653817078212 199.9565381707821 500108.67818980943 0.0000415721844293504 0.004157218442969679 -10.39734842094714 
0.9995238095233918 199.95238095233918 500119.07597057364 0.0000415721844293504 0.004157218442912836 -10.397780764257597 
0.9994822373389625 199.94822373389624 500129.4741837084 0.0000415721844293504 0.004157218442941257 -10.398213134716478 
0.9994406651545331 199.9440665154533 500139.87282924046 0.0000415721844293504 0.004157218442941257 -10.398645532063572 
0.9993990929701038 199.9399092970104 500150.27190719673 0.0000415721844293504 0.004157218442912836 -10.39907795629888 
0.9993575207856744 199.93575207856745 500160.67141760443 0.0000415721844293504 0.004157218442941257 -10.39951040768261 

timePos, pos, val, diff_timePos, diff_pos, diff_val 
0.545374149659864 109.06905877697271 0.4204208397546066 -0.000022675736961463855 -0.006802052642697731 -0.03915004637084152 
0.5453968253968254 109.07586101815137 0.4588041214830869 -0.000022675736961463855 -0.006802241178661461 -0.03838328172848032 
0.5454195011337869 109.08266344786601 0.49635046831417823 -0.000022675736961463855 -0.006802429714639402 -0.037546346831091315 
0.5454421768707483 109.08740468218267 0.5219878252653231 -0.000022675736961352833 -0.004741234316654186 -0.02563735695114483 
0.5454648526077097 109.08967217018066 0.5340864997440766 -0.000022675736961463855 -0.002267487997997364 -0.012098674478753568 
0.5454875283446712 109.09193946964263 0.5460757756696786 -0.000022675736961463855 -0.0022672994619625797 -0.01198927592560195 
0.5455102040816326 109.09420658056864 0.5579532472663103 -0.000022675736961463855 -0.0022671109260130606 -0.011877471596631772 
0.5455328798185941 109.09647350295867 0.5697165324497411 -0.000022675736961463855 -0.00226692239003512 -0.011763285183430727 
0.5455555555555556 109.09874023681267 0.5813632732981516 -0.000022675736961463855 -0.0022667338540003357 -0.011646740848410553 
0.545578231292517 109.10100678213077 0.5928911365171865 -0.000022675736961463855 -0.002266545318093449 -0.011527863219034873 
0.5456009070294785 109.10327313891281 0.6042978138973617 -0.000022675736961463855 -0.002266356782044454 -0.0114066773801752 
0.54562358276644 109.1055393071589 0.615581022770094 -0.000022675736961463855 -0.002266168246094935 -0.011283208872732264 
0.5456462585034013 109.10780528686898 0.6267385064542539 -0.000022675736961352833 -0.0022659797100743617 -0.011157483684159919 
0.5456689342403628 109.11007107804308 0.637768034700286 -0.000022675736961463855 -0.002265791174096421 -0.011029528246032094 
0.5456916099773242 109.11233668068122 0.6486674041261999 -0.000022675736961463855 -0.002265602638146902 -0.010899369425913963 
0.5457142857142857 109.11460209478336 0.659434438648618 -0.000022675736961463855 -0.0022654141021405394 -0.010767034522418006 
0.5457369614512472 109.11686732034953 0.670066989909156 -0.000022675736961463855 -0.0022652255661625986 -0.010632551260538081 
0.5457596371882086 109.11913235737973 0.6805629376928694 -0.000022675736961463855 -0.0022650370301988687 -0.010495947783713322 
0.5457823129251701 109.12139720587393 0.6909201903420606 -0.000022675736961463855 -0.002264848494206717 -0.010357252649191295 

까지입니다 내가 할 수있는 것처럼 문제는 그입니다 delta on timePos가 갑자기 ~0.006802052642697731에서 스테핑에서 ~ 0.0022671109260130606으로 바뀝니다.

진행률이 0.5 (주파수가 200Hz에 도달)에 도달하고 주파수가 다시 100Hz로 이동하기 시작할 때 발생합니다.

나는이 코드를 몇 시간 동안보고 있었기 때문에 문제를 볼 수 없었습니다.

내가 일정한 주파수 파형을 생성하는 데 사용하는 코드입니다 :

for (var i=0; i<sampleRate*seconds; i++) { 
    var p = (i/sampleRate); 
    var v = Math.sin((2*Math.PI) * p * frequency); 
    buffer[i] = v; 
} 
+0

이미지를 다른 사이트 (예 : 포토 버킷)에 넣고 링크를 게시 할 수 있습니다. –

+0

코드를 빨리 읽는 것이 어렵습니다. 'v'와 'val'은 무엇입니까? '진보'란 무엇입니까? 두 개의 주기적 파형 (가청 파 및 변조기)이 있더라도 왜 주파수와 파장에 대해 하나의 변수 만 있습니까? 아마도 변조되지 않은 사인파에 해당하는 코드를 게시 할 수 있습니까? (아마도 당신은 그 코드를 가지고 있을까요?) –

+0

다음은 이미지 링크입니다 : http://www.shareimage.ro/images/pxf8xb8r18je56drwmy6.png 죄송합니다. 코드를 읽기가 약간 어렵습니다. v : 현재주기의 "진행률"을 나타내는 0.0-1.0의 값입니다. (이 예에서 분당 55 사이클, 각 사이클은 1.09 초). val은 오디오 버퍼 (PCM)로 들어가는 계산 된 사인 값입니다. – Morgan

답변

1

나는 문제는 당신이 주파수를 청소하고 있지만, 당신의 위치에 누적 을 추가하지 않는 것으로 생각합니다 ' 오실레이터 '는 그 주파수를 기반으로합니다 - 대신 오실레이터 의 위치가 일 때 그 순간에 계산 된 주파수가 이고 주파수가 인 것처럼 보입니다.

나는이 알고리즘을 시도

는 (I Excel에서 보는 것이 더 편안 출력을 만들기 위해 약간의 값을 변경했습니다!)

function SweepFreq(cyc, lo, hi) { 
this.cyclesPerMinute = cyc; 
this.cycle_length = 60.0/this.cyclesPerMinute; 
this.lowFreq = lo; 
this.highFreq = hi; 
this.time = 0.0; 
this.buffer = null; 

window.initSweep = function (element) { 
    var sampleRate = 10000.0 
    var seconds = 1; 
    var length = sampleRate*seconds; 
    this.buffer = new Float32Array(length); 
    this.generateSineWave(this.buffer, sampleRate, seconds) 
} 

this.generateSineWave = function(buffer, sampleRate, seconds) { 
    var deltaTime = 1.0/(sampleRate); 

    var oldCyclePosition=0; 

    for (var i = 0; i < sampleRate*seconds; i++) { 
     var frequencyFactor = this.getFrequencyFactor(deltaTime); 
     var frequency = ((this.highFreq-this.lowFreq)*frequencyFactor)+this.lowFreq; 

     var distanceMovedInThisSample = frequency/sampleRate; 
     var currentCyclePosition = distanceMovedInThisSample + oldCyclePosition; 

     var val = Math.sin(currentCyclePosition * 2.0 * Math.PI); 
     this.buffer[i] = val; 
     oldCyclePosition = currentCyclePosition; 
     console.log(val); 
    } 
} 

this.getFrequencyFactor = function(deltaTime) { 
    this.time += deltaTime; 
    if (this.time > this.cycle_length) 
     this.time -= this.cycle_length; 
    var progress = this.time/this.cycle_length; 
    if (progress < 0.5) { 
     return progress*2.0; 
    } 
    else { 
     return 1.0-((progress-0.5)*2.0) 
    } 
}} 

줄 듯 부드러운 - 어쨌든, 스윕을 찾고!

또 하나의 사실은 100 % 진폭으로가는 파형이 특정 드라이버와 하드웨어를 통해 클릭과 팝을 일으키기 때문에 웨이브를 50 %로 정규화 해보십시오.

+0

테스트를 위해 'SweepFreq (100, 100, 500);'와 함께 이것을 호출했습니다. –

+1

네 말이 맞아. 내가 잘못 생각한거야. 코드가 완벽하게 작동하고 소리가납니다. 감사. – Morgan

+0

알려 주셔서 감사합니다. (내가 듣기에는 .wav로 렌더링하기에는 너무 게으르다!) –