typescript를 사용하여 오디오 시각화 도구를 만듭니다
우리는 결국 무엇을 건설할 것인가
Click here to see what the end result looks like
The entire source code can be found at https://github.com/BharatKalluri/bharatkalluri.com/blob/main/components/AudioVisualizer.tsx
네트워크 오디오 API
우리가 구축하고 있는 주파수 그래프라고 불린다.
시각화 중인 모든 프레임을 그릴 때, 우리는 당시 오디오의 주파수를 정수로 얻을 수 있다.우리는 이 정수를 사용하여 그림에 줄무늬를 그렸다.노래 신호에 대한 빠른 부립엽 변환 (FFT) 을 통해 주파수를 검색합니다.
이것이 바로 문제가 복잡해진 부분이다.푸리엽 변환은 가장 아름다운 수학 방정식 중의 하나다.하지만 나는 아직 충분한 직감으로 설명할 수 없다.아마도 어느 날, 그것을 눌렀을 때, 나는 명확한 문자를 가지고 있을 것이다.이제 그 요점은 복잡한 신호를 받아들여 더 간단한 신호로 분해하는 것이다.우리는 그 중에서 주파수를 추출할 수 있다.(이것이 바로 나의 이해이다. 나는 여기서 100% 정확하지 않을 수도 있다.
우리는 어떻게 이런 주파수를 얻습니까?웹 오디오 API에는 analyzer라는 유틸리티가 있습니다.분석기에서 우리는 주파수 데이터를 얻을 수 있다.FFT (빠른 부립엽 변환) 의 크기를 설정한 다음 주파수를 되돌려야 합니다.따라서 FFT 크기가 1024로 설정되면 주파수를 나타내는 1024개의 숫자 그룹을 얻을 수 있습니다.이곳의 조건 중 하나는 그것이 반드시 32에서 32768 사이의 2의 멱이어야 한다는 것이다.
이해해야 할 또 다른 개념은 웹오디오가 노드 방면에서 작용한다는 것이다.이 단독 노드들은 하나의 그림을 형성하고 이 그림을 집행한다.예를 들어, 웹 audio API에는 이득 노드라는 노드가 있습니다.만약 우리가 이득치를 1로 설정한다면, 이것은 그것의 소리가 가장 크다는 것을 의미한다.0은 침묵을 의미한다.미디어 요소를 만들고 버프 노드를 이 요소에 연결할 수 있습니다.그리고 버프 노드가 목적지(즉 스피커)에 연결됩니다.따라서 프로그램이 실행될 때, 오디오는 목적지에 도착하기 전에 모든 노드를 통과한다.
분석기도 하나의 노드다.이런 방법의 장점 중 하나는 한 노드에 여러 개의 하위 노드가 있을 수 있다는 것이다.하나의 미디어 요소는 목적지와 분석기를 동시에 연결할 수 있다.이것은 소화해야 할 중요한 사상이다.
실제 가시화는 결코 어렵지 않다.모든 값이 캔버스에 사각형으로 그려지고 색상이 표시됩니다.이렇게여기서 주의해야 할 기능 중 하나는
requestAnimationFrame
입니다.이 방법은 브라우저에 애니메이션을 실행하고 싶은 것을 알려주고 지정한 함수를 호출해 달라고 요청합니다.일반적으로 이것은 모니터의 주사율과 일치한다.인코딩해 봅시다!
현재 이 이론은 이미 시대에 뒤떨어졌다.먼저 HTML로 원하는 내용을 설명하는 템플릿을 만듭니다.
<input
type="file"
id="audioPicker"
accept="audio/*"
/>
<audio>No support for audio</audio>
<canvas
id="canvas"
></canvas>
오디오 파일을 선택할 수 있는 간단한 입력오디오 라벨은 실제 오디오를 재생하는 데 사용되고, 주파수 그래프를 그리는 데 사용됩니다.이제 타자 원고 부분으로 넘어갑시다.const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const audioElement = document.getElementById("audio");
const audioPickerElement = document.getElementById("audioPicker");
const canvasElement = document.getElementById(
"canvas"
) as HTMLCanvasElement;
canvasElement.width = window.innerWidth;
canvasElement.height = window.innerHeight;
const canvasCtx = canvasElement.getContext("2d");
몇몇 기본적인 성명은 우리가 먼저 얻었다AudioContext
.이 인터페이스는 서로 다른 노드에서 구축된 오디오 프로세서를 표시합니다.그리고 우리는 getElementById
audioElement, audioPickerElement과 canvasElement을 가져옵니다.우리는 곧 그것들을 변이시킬 것이다.그리고 우리는 화포의 높이와 너비를 설정한다.마지막으로 화포의 상하문을 얻으면 우리는 그것으로 화포에 그림을 그릴 수 있다.audioPickerElement.onchange = function () {
// @ts-ignore
const files = this.files;
audioElement.src = URL.createObjectURL(files[0]);
audioElement.load();
audioElement.play();
}
간단하게 파일 변경을 시작합니다.첫 번째 파일을 검색하고 오디오 요소의 원본으로 설정합니다.그런 다음 audioElement을 로드하고 재생합니다.이 점에서, 너는 노래 한 곡을 선택하고, 여기에서 오디오를 재생할 수 있어야 한다.이제 웹오디오를 봅시다.// ...from now the code you see here is a part of the onchange function of audiopicker in the above example
const track = audioContext.createMediaElementSource(
audioElement
);
track.connect(audioContext.destination);
// Analyzer node
const analyser = audioContext.createAnalyser();
analyser.fftSize = 128;
track.connect(analyser);
이것은 도형 구조다.도표의 기본 요소는 createMediaElementSource
인데 이것은 실제 오디오 원본이다.한쪽 목적지(오디오 출력/스피커)와 분석기를 연결합니다.이것은 앞의 삽화와 같다.간단하게 보기 위해서 우리는 이득 노드를 뛰어넘었다.analyzer 노드는 실시간 주파수와 시간 분석을 제공할 수 있습니다.잠시 후 주파수 데이터를 가져와야 합니다.FFT 크기가 128로 설정되어 있기 때문에 128개의 값만 얻을 수 있습니다. 우리는 이 값을 그릴 수 있습니다.너무 많은 값은 철근이 얇아진다는 것을 의미한다.// Creating the array to store the frequency data
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
여기서부터 모든 주파수 데이터를 저장하기 위해 Uint8Array
중의 fftSize
를 만들어야 한다. 이 데이터는 계속 흐를 것이다.// Some useful constants
const WIDTH = canvasElement.width;
const HEIGHT = canvasElement.height;
const barWidth = (WIDTH / bufferLength) * 2.5;
let barHeight;
let x = 0;
// Colors used for plotting
const MATTE_BLACK = "#1A202C";
const WHITE = "#FFFFFF";
// The function which will get called on each repaint
function draw() {
requestAnimationFrame(draw);
if (canvasCtx !== null) {
x = 0;
analyser.getByteFrequencyData(dataArray);
canvasCtx.fillStyle = WHITE;
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
for (let i = 0; i < bufferLength; i++) {
barHeight = dataArray[i];
canvasCtx.fillStyle = MATTE_BLACK;
canvasCtx.fillRect(x, 0, barWidth, barHeight);
x += barWidth + 3;
}
}
}
draw();
너비, 높이, 스트라이프 너비 (너비 곱하기 2.5는 스트라이프를 더 커 보이게 하기 위해서일 뿐, 사용하지 않으려면 2.5도 우리가 왜 이러는지 보자) 와 일부 색깔은 편의를 위해 정의된 것이다.이제 중요한 부분을 살펴보자.draw 함수는 실제 화포를 그리는 함수입니다.매번 호출할 때마다, 우리는 초당draw 함수를 약 60회 (60헤르츠 디스플레이가 있다면), 입력과 같은 함수 호출 requestAnimationFrame
을 사용합니다.기억해라, 이 모든 것은 비동기적으로 발생한 것이다.함수 내부에서 우리는
x=0
부터 시작하여 화포에서 (0,0)이다.그리고 우리는 분석기의 getByteFrequencyData
함수를 사용하여 주파수 데이터를 앞에서 설명한 dataArray
에 채웁니다.실제 채워진 내용을 알아보기 위해 데이터 그룹을 살펴보는 것을 권장합니다. (주의: 이 동작을 실행할 때 노래 한 곡을 불러오고, draw 함수에 컨트롤러 로그가 있으면, 128 크기의 거대한 그룹은 초당 30회 이상 컨트롤러에 기록되며, 브라우저가 붕괴되거나 속도가 느려집니다.)현재 데이터가 그룹에 있습니다. 캔버스 배경을 흰색으로 설정하십시오.배열의 각 요소에 사각형을 그립니다.좌표는 (x, y, width, height) => (0, 0,barWidth,barHeight)에서 시작합니다.
MATTE_BLACK
로 이 직사각형을 채우고 x를 증가barWidth + 3
합니다.가령 스트라이프의 폭이 50px라고 가정하면 두 번째 사각형은 다음과 같은 좌표(53, 0, 스트라이프의 폭, 스트라이프의 높이)를 가지게 된다.수조의 모든 원소는 이렇다.이것이 바로 프레임을 그리는 방식이다.이것은 1초에 >30번(모니터 주사율 기준)을 반복하여 부드럽고 연속적인 이동 그래픽임을 느끼게 합니다.🤯
The entire source code can be found at https://github.com/BharatKalluri/bharatkalluri.com/blob/main/components/AudioVisualizer.tsx
우리는 단지 표면에 닿았을 뿐, 매우 좋은 시각 효과가 많다.This is one of my favorites .
본 논문의 영감은 MDN의 visualizations with the Web Audio API에 관한 문장에서 나왔다.
Reference
이 문제에 관하여(typescript를 사용하여 오디오 시각화 도구를 만듭니다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/bharatkalluri/let-us-make-an-audio-visualizer-using-typescript-2b8p텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)