Почему высота звука не смещается в этом JavaScript звуковом переключателе высоты звука, который использует FFT и iFFT для смещения высоты звука? - PullRequest
0 голосов
/ 11 февраля 2020

Я выполнил следующие шаги:

  1. Я использовал функцию transform из библиотеки nayuki fft для преобразования аудиосэмплов в серию комплексных чисел, представляющих частотную область,
  2. I затем unshifted индексы всех значений выросли на 40000
  3. После этого я использовал inverseTranform из той же библиотеки для преобразования данных в частотной области обратно в волну.
  4. Я сыграл ее с Web Audio API и сравнил.

Я обнаружил, что смещение всех индексов на 40000 практически не влияет на окончательный звук. Учитывая, что я заменил нижние 40 000 индексов, а общий массив длиной 96 000 элементов, данные в массиве после выполнения unshift существенно отличались от того, что было до unshift. Я подумал, что это будет означать, что после того, как я построю новую звуковую волну из сильно измененных частотных данных, у меня получится нечто существенно отличающееся (надеюсь, версия оригинала со смещением высоты тона).

Вот jsFiddle: https://jsfiddle.net/vj4dr7wc/1/.

Вот важный раздел скрипта:

//** Do processing **//
    console.log(">>>>>Buffer>>>>>");
    //console.log(Array.isArray(nowBuffering));
    console.log(buffer[0],buffer[1]);

    // Calculate fft of buffer
    console.log("=====FrequencyInfo====");
    var freqInfo = [buffer[0].slice(),buffer[1].slice()];
    transform(freqInfo[0],freqInfo[1])
    console.log(freqInfo[0],freqInfo[1]);

    // Do effects
    console.log("^^^^^^Pitch Effects^^^^^^^");
    var beforeEffect = freqInfo[0].slice();
    pitchEffects(channel,freqInfo);
    console.log(beforeEffect);
    console.log("!=");
    console.log(freqInfo[0]);
    console.log(freqInfo[0]==beforeEffect);

    // Reconstruct waveform
    console.log("~~~~~~Reconstructed~~~~~~~");
    var reconstred = [freqInfo[0].slice(),freqInfo[1].slice()];
    inverseTransform(reconstred[0],reconstred[1]);

    // Normalize it
    var max = Math.max(...reconstred[0]);
    var maxOrig = Math.max(...buffer[0]);
    console.log("max: "+max);
    reconstred[0] = reconstred[0].map(function(value){
      return (maxOrig/max)*value;
    });

    // Save it
    var reconBuffer = audioBuffer1.getChannelData(channel);
    for (var i = 0; i < frameCount; i++) {
      reconBuffer[i] = reconstred[0][i];
    }
    console.log(reconstred[0],reconstred[1]);

    // Check results
    console.log("*******Results********");
    console.log(reconstred[0]==buffer[0]);
    console.log(reconstred[0]);
    console.log("==");
    console.log(buffer[0]);

    //** End Processing **//

Вот полный рабочий пример (требуется fft.js):

<code><!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width">
  <script src="fft.js"></script>

  <title>Audio Test</title>
  <link rel="stylesheet" href="">
  <!--[if lt IE 9]>
      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
</head>

<body>
  <h1>Audio Test</h1>
  <button id='0'>Play original sound</button>
  <button id='1'>Play reconstructed sound</button>
  <pre>
подключения (audioCtx.destination); song.start (); song.onended = () => {console.log («Восстановленный звук закончен»); }} buttonOriginal.onclick = function () {var song = audioCtx.createBufferSource (); song.buffer = audioBuffer0; song.connect (audioCtx.destination); song.start (); song.onended = () => {console.log ('Оригинальный звук закончен'); }} function freqSin (freq, time) {return Math.sin (freq * (2 * pi) * time); } var currentPitchShift = 0; function pitchEffects (channel, freqInfo) {pitchShiftUp (freqInfo, 40000); } function pitchShiftUp (freqInfo, num) {var arrLen = freqInfo [0] .length; console.log ("arrLen:" + arrLen); // построить массив из 0 переменных var zeros = []; для (var i = 0; i
...