d3 - возникают проблемы при построении кругов для представления частоты аудиоклипа в зависимости от времени - PullRequest
1 голос
/ 14 марта 2019

Я довольно новичок в d3, и я работаю над проектом, который включает в себя получение аудиоклипа и построение графика зависимости частоты / высоты звука от времени на графике. Я бы хотел представить точки данных кружками.

Ось X будет временем, а ось Y будет шагом в данное время х. Радиус каждого круга будет связан с объемом клипа в данный момент времени x.

Мой первый вопрос - как я могу вытащить эти данные высоты тона? И как мне найти среднюю / репрезентативную «подачу» для сюжета? Из того, что я понимаю, частота BinCount дает вам полный диапазон частот и дает значение от 0 до 255 для каждой частоты. Но мне просто нужна "репрезентативная" частота.

Мой второй вопрос: если бы я хотел отображать каждую точку последовательно во время воспроизведения клипа, как бы я это сделал? Как мне пройти через каждый раз? Ниже приведен мой код - я знаю, что, возможно, есть серьезные проблемы, но я только начинаю с d3. Базовый код был изменен с этого источника .

псевдокод:

1.Импортный аудиоанализатор

  1. Начало аудио

  2. Цикл для каждой секунды: -Получить высоту и громкость текущего звука, который воспроизводится в данный момент времени (current_time).
    -Кружка на высоте = высота тона, x_position = current_time

  3. Когда аудио закончится, остановите рисование

<script>

  var audioElement = document.getElementById('audioElement');
  var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
  var audioSrc = audioCtx.createMediaElementSource(audioElement);
  var analyser = audioCtx.createAnalyser();
  audioSrc.connect(analyser);
  audioSrc.connect(audioCtx.destination);

  var bufferSize = analyser.frequencyBinCount
  var frequencyData = new Uint8Array(bufferSize);
  analyser.getByteFrequencyData(frequencyData);

  var timeDomainData = new Uint8Array(bufferSize);
  analyser.getByteTimeDomainData(timeDomainData);

  // return average frequency
  var total = 0;
  for(var i = 0; i < frequencyData.length; i++) {
    total += frequencyData[i];
  }
  var avgfreq = total / frequencyData.length;



  // return average amplitude
  var total = 0;
  for(var i = 0; i < timeDomainData.length; i++) {
    total += Math.abs(timeDomainData[i] % 128);
  }
  var avgtd = total / timeDomainData.length;


  var svgHeight = window.innerHeight - 100;
  var svgWidth = window.innerWidth-10;


  // var colorScale = d3.scaleLinear()
  //   .domain([0, 150])
  //   .range(["#2c7bb6","#d7191c"]);

  
  var svg = d3.select('body').append('svg')
    .attr('width', svgWidth)
    .attr('height', svgHeight);

  //how do I loop this while audio is playing so that it sequentially plots points?
  var circle = svg.append('circle')
    .attr('r', function() { return avgtd+2; })
    .attr('cx', function() { return svgWidth/2; })
    .attr('cy', function() { return svgHeight - avgfreq; })
    .attr('fill', function() { return 'blue'; });


</script>
...