웹 오디 오 API 기반 오디 오 시각 화 효과 구현

웹 페이지 오디 오 인터페이스 의 가장 재 미 있 는 특성 중 하 나 는 주파수,파형 과 다른 사 운 드 소스 에서 온 데 이 터 를 얻 을 수 있다 는 것 이다.이 데 이 터 는 오디 오 시각 화 에 사용 할 수 있다.이 글 은 시각 화 를 어떻게 하 는 지 설명 하고 기본 적 인 사용 사례 를 제공 할 것 이다.
기본 개념 절
오디 오 소스 에서 데 이 터 를 얻 으 려 면AnalyserNode노드 가 필요 합 니 다.AudioContext.createAnalyser()방법 으로 만 들 수 있 습 니 다.예 를 들 어:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var analyser = audioCtx.createAnalyser();
그리고 이 노드(node)를 당신 의 음 원 에 연결 합 니 다.

source = audioCtx.createMediaStreamSource(stream);
source.connect(analyser);
analyser.connect(distortion);
// etc.
메모:분석 기 노드(Analyser Node)가 반드시 다른 노드 로 출력 되 는 것 이 아니 라 출력 하지 않 을 때 도 정상적으로 사용 할 수 있 습 니 다.그러나 전 제 는 하나의 음 원 과 연결 되 어야 한 다 는 것 이다.
분석 기 노드(Analyser Node)는 특정한 주파수 영역 에서 빠 른 푸 립 엽 변환(Fast Fourier Transform (FFT) )을 사용 하여 오디 오 데 이 터 를 캡 처 할 것 입 니 다.이것 은 당신 이AnalyserNode.fftSize속성 에 부여 한 값(할당 이 없 으 면 기본 값 은 2048)에 달 려 있 습 니 다.
메모:FFT 데이터 크기 조정 범 위 를 최소 값 과 최대 값 으로 지정 할 수 있 습 니 다.AnalyserNode.minDecibels AnalyserNode.maxDecibels을 사용 하여 설정 할 수 있 습 니 다.데이터 의 평균 상수 에 따라 AnalyserNode.smoothingTimeConstant를 사용 하 십시오.이 페이지 들 을 읽 어서 정 보 를 어떻게 사용 하 는 지 더 알 아 보 세 요.
데 이 터 를 캡 처 하려 면AnalyserNode.getFloatFrequencyData()또는AnalyserNode.getByteFrequencyData()방법 으로 주파수 데 이 터 를 얻 고AnalyserNode.getByteTimeDomainData() AnalyserNode.getFloatTimeDomainData()으로 파형 데 이 터 를 가 져 와 야 합 니 다.
이 방법 들 은 데 이 터 를 특정한 배열 에 복사 하기 때문에 호출 하기 전에 새 배열 을 만들어 야 합 니 다.첫 번 째 방법 은 32 비트 부동 소수점 배열 을 만 들 고,두 번 째 방법 과 세 번 째 방법 은 8 비트 기호 없 는 정형 배열 을 만 들 수 있 기 때문에 하나의 표준 자 바스 크 립 트 배열 은 사용 할 수 없습니다.-Float 32Array 나 Uint 8 Array 배열 을 사용 해 야 합 니 다.구체 적 으로 어떤 상황 에 따라 정 해 야 합 니까?
예 를 들 어 2048 사이즈 의 FFT 를 처리 하고 있 습 니 다.우 리 는AnalyserNode.frequencyBinCount 을 되 돌려 주 었 다.그것 은 FFT 의 절반 이 고Uint8Array()를 호출 하여frequencyBinCount를 길이 의 매개 변수 로 삼 았 다.이것 은 우리 가 이 사이즈 의 FFT 에 대해 얼마나 많은 데 이 터 를 수집 할 것 인 지 를 나타 낸다.

analyser.fftSize = 2048;
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
데 이 터 를 정확하게 검색 하고 우리 의 배열 에 복사 하려 면 우리 가 원 하 는 데이터 수집 방법 을 호출 하여 배열 을 매개 변수 로 전달 해 야 한다.예 를 들 어:

analyser.getByteTimeDomainData(dataArray);
지금 우 리 는 그때 의 오디 오 데 이 터 를 얻 었 고 우리 의 배열 에 병존 되 었 으 며 그것 을 우리 가 좋아 하 는 시각 화 효과 로 만 들 수 있다.예 를 들 어 그것 을HTML5 <canvas>캔버스 에 그 릴 수 있다.
주파수 막대 그래프 를 만 듭 니 다.
또 다른 작은 시각 화 방법 은 주파수 막대 그래프 를 만 드 는 것 이다.
이제 그것 이 어떻게 실현 되 었 는 지 봅 시다.
우선,우 리 는 해상도 와 빈 배열 을 설정 한 후에clearRect()로 캔버스 를 비 웁 니 다.이전 과 의 유일한 차이 점 은 우리 가 이번에FFT의 크기 를 크게 줄 였 다 는 것 이다.이렇게 하 는 이 유 는 모든 주파수 가'가 는 막대'가 아니 라'막대'처럼 보이 기 때문이다.

 analyser.fftSize = 256;
 var bufferLength = analyser.frequencyBinCount;
 console.log(bufferLength);
 var dataArray = new Uint8Array(bufferLength);
 canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
그 다음 에 우 리 는 draw()함 수 를 쓰 고 다시requestAnimationFrame()로 순환 을 설정 하면 표 시 된 데 이 터 를 갱신 할 수 있 고 프레임 마다 캔버스 를 비 울 수 있 습 니 다.

function draw() {
  drawVisual = requestAnimationFrame(draw);
  analyser.getByteFrequencyData(dataArray);
  canvasCtx.fillStyle = 'rgb(0, 0, 0)';
  canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
  }
이제 모든 막대 너비 와 같은 barWidth 변 수 를 설정 합 니 다.이론 적 으로 꽃무늬 천 너비 로 줄 의 개 수 를 나 누 면 그것 을 얻 을 수 있 지만 여기 서 우 리 는 2.5 를 곱 해 야 한다.이것 은 되 돌아 오 는 주파수 구역 에서 소리 가 없 기 때문에 우리 가 매일 듣 는 대부분의 소리 도 아주 작은 주파수 구역 에 있 을 뿐이다.막대 그래프 에서 우 리 는 큰 공백 을 보고 싶 지 않 을 것 이다.그래서 우 리 는 정상적으로 표시 할 수 있 는 막대 기 를 넓 혀 서 이 공백 구역 을 채 울 것 이다.
우 리 는 또 하나의 고도 변수barHeight를 설정 하고,또 하나의 x 변 수 를 설정 하여 현재 줄무늬 의 위 치 를 기록 해 야 한다.

var barWidth = (WIDTH / bufferLength) * 2.5;
var barHeight;
var x = 0;
이전 처럼 dataArray 배열 의 데 이 터 를 반복 적 으로 옮 겨 다 닙 니 다.매번 순환 과정 에서 우 리 는 스 트 라 이 프 의 높이barHeight를 배열 의 수치 와 같 게 한 다음 에 높이 에 따라 스 트 라 이 프 의 충전 색(스 트 라 이 프 가 높 을 수록 충전 색 이 밝 아 짐)을 설정 한 다음 에 가로 좌표 x 에서 설 치 된 너비 와 높이 의 절반 에 따라 스 트 라 이 프 를 그리 기로 결정 했다.
더 설명해 야 할 것 은 각 선형 수직 방향의 위치 입 니 다.우 리 는HEIGHT-barHeight/2의 위치 에 각각 하 나 를 그 렸 습 니 다.이것 은 모든 선형 을 아래쪽 에서 위로 뻗 게 하고 싶 기 때 문 입 니 다.위 에서 아래로(우리 가 수직 위 치 를 0 으로 설정 하면 이렇게 그 릴 것 입 니 다)그래서 우 리 는 수직 위 치 를 캔버스 높이 에서 선형 높이 의 절반 을 줄 이 는 것 으로 설정 하면 모든 선형 은 중간 에서 아래로 그 려 캔버스 의 맨 밑 까지 그 릴 것 이다.

for(var i = 0; i < bufferLength; i++) {
  barHeight = dataArray[i]/2;
  canvasCtx.fillStyle = 'rgb(' + (barHeight+100) + ',50,50)';
  canvasCtx.fillRect(x,HEIGHT-barHeight/2,barWidth,barHeight);
  x += barWidth + 1;
  }
 };
아까 와 마찬가지 로 우 리 는 마지막 에draw()함 수 를 호출 하여 전체 시각 화 과정 을 엽 니 다.
draw();
이 코드 들 은 다음 과 같은 효 과 를 가 져 올 것 입 니 다.
在这里插入图片描述
원본 코드:

<!doctype html>
<html lang="en">
<head>
 <meta charset="UTF-8"/>
 <title>        </title>
</head>
<body>
<input type="file" name="" value="" id="musicFile">
<p id="tip"></p>
<canvas id="casvased" width="500" height="500"></canvas>
</body>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
//     
function randomRgbColor() { //    RGB  
 var r = Math.floor(Math.random() * 256); //    256  r 
 var g = Math.floor(Math.random() * 256); //    256  g 
 var b = Math.floor(Math.random() * 256); //    256  b 
 return `rgb(${r},${g},${b})`; //  rgb(r,g,b)    
}
//    0-255
function sum (m,n){
  var num = Math.floor(Math.random()*(m - n) + n);
 
}
console.log(sum(0,100));
console.log(sum(100,255));
//       
var canvas = document.getElementById("casvased");
var canvasCtx = canvas.getContext("2d");
//     AudioContext            ,        ;audioContext         ,        AudioContext         (AudioNode)    ,                 。
//       AudioContext      ,   new Date()         
var AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
if (!AudioContext) {
 alert("        audio API,      (chrome、firefox)   ,               !")
}
var audioContext = new AudioContext();//   
//           
// 1        (         )
// 2       ,   ,            
// 3               
$('#musicFile').change(function(){
 if (this.files.length == 0) return;
 var file = $('#musicFile')[0].files[0];//  input       
 var fileReader = new FileReader();//  FileReader      
 fileReader.readAsArrayBuffer(file);//        
 fileReader.onload = function(e) {//         
 //e.target.result          (         )
 //                 ,            
 var count = 0;
 $('#tip').text('    ')
 var timer = setInterval(function(){
  count++;
  $('#tip').text('   ,   '+count+' ')
 },1000)
 //    ,           
 audioContext.decodeAudioData(e.target.result, function(buffer) {
  clearInterval(timer)
  $('#tip').text('    ,    :'+count+' ')
  //   AudioBufferSourceNode          buffer   
  var audioBufferSourceNode = audioContext.createBufferSource();
  //   AnalyserNode            
  var analyser = audioContext.createAnalyser();
  //fftSize (Fast Fourier Transform)         ,         2048。             ,      ,                。   ,     ,     。
  analyser.fftSize = 256;
  //     ,audioContext.destination           ,
  //            。                 
  //    audioContext.destination      。
  audioBufferSourceNode.connect(analyser);
  analyser.connect(audioContext.destination);
  console.log(audioContext.destination)
  //     
  audioBufferSourceNode.buffer = buffer; //         
  audioBufferSourceNode.start(); //      noteOn()  ,    
  //        
  // var dataArray = new Uint8Array(analyser.fftSize);
  // analyser.getByteFrequencyData(dataArray)//       ,            
  // console.log(analyser.getByteFrequencyData)
  var bufferLength = analyser.frequencyBinCount;
  console.log(bufferLength);
  var dataArray = new Uint8Array(bufferLength);
  console.log(dataArray)
  canvasCtx.clearRect(0, 0, 500, 500);
  function draw() {
  drawVisual = requestAnimationFrame(draw);
  analyser.getByteFrequencyData(dataArray);
  canvasCtx.fillStyle = 'rgb(0, 0, 0)';
		//canvasCtx.fillStyle = ;
  canvasCtx.fillRect(0, 0, 500, 500);
  var barWidth = (500 / bufferLength) * 2.5;
  var barHeight;
  var x = 0;
  for(var i = 0; i < bufferLength; i++) {
   barHeight = dataArray[i];
		 //   0-255 Math.floor(Math.random()*255) 
		 //     10*Math.random()
   canvasCtx.fillStyle = 'rgb(' + (barHeight+100) + ','+Math.floor(Math.random()*(20- 120) + 120)+','+Math.floor(Math.random()*(10 - 50) + 50)+')';
   canvasCtx.fillRect(x,500-barHeight/2,barWidth,barHeight/2);
   x += barWidth + 1;
  }
  };
  draw();
 });
 }
})
</script>
</html>
 주의:
본 논문 의 사례 는 AnalyserNode.getByte Frequency Data()와 AnalyserNode.getByte Time DomainData()의 용법 을 보 여 주 었 다.AnalyserNode.getFloat Frequency Data()와 AnalyserNode.getFloat Time DomainData()의 용법 을 보 려 면 저희 의 Voice-change-O-matic-float-data 프레젠테이션(소스 코드 도 볼 수 있 음)을 참고 하 십시오.본 논문 에 나타 난 Voice-change-O-matic 기능 과 똑 같 습 니 다.유일한 차이 점 은 부동 소수점 을 데이터 로 사용 하 는 것 입 니 다.본문의 부호 없 는 정형 수가 아니다.
https://github.com/mdn/voice-change-o-matic 》
사례 1:https://mdn.github.io/voice-change-o-matic/ 》
사례 2:http://margox.github.io/vudio.js/ 》
총결산
웹 오디 오 API 를 기반 으로 오디 오 시각 화 효 과 를 실현 하 는 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 웹 오디 오 API 가 오디 오 시각 화 를 실현 하 는 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 지원 바 랍 니 다!

좋은 웹페이지 즐겨찾기