3 bài trước tạo và xử lý âm thanh; bài này quan sát nó. AnalyserNode
không tạo ra hay biến đổi âm thanh — nó là 1 "điểm dò" (tap) đọc dữ liệu tín hiệu đang chạy qua, cho
phép vẽ waveform và spectrum tần số thời gian thực — nền tảng của mọi visualizer nhạc.
1. Biến Đổi Fourier (FFT): Trực Giác Cơ Bản
Mọi tín hiệu âm thanh phức tạp — dù là hợp âm, giọng nói, hay tiếng trống — về mặt toán học đều có thể phân tích thành tổng của nhiều sóng sine đơn giản ở các tần số, biên độ, và pha khác nhau. Biến đổi Fourier Nhanh (FFT — Fast Fourier Transform) là thuật toán tách 1 đoạn tín hiệu theo thời gian thành đúng những thành phần tần số đó — biến 1 dạng sóng rối rắm thành 1 biểu đồ rõ ràng: "tần số này có bao nhiêu năng lượng".
2. Thiết Lập AnalyserNode: fftSize Và Độ Phân Giải
audioContext.createAnalyser() tạo 1 node đặc biệt — kết nối vào giữa đồ thị (như 1 điểm
rẽ nhánh) để đọc dữ liệu mà không ảnh hưởng âm thanh thật sự phát ra.
analyser.fftSize (phải là luỹ thừa của 2, từ 32 tới 32768) quyết định độ phân giải: FFT
càng lớn, càng nhiều tần số phân biệt được, nhưng cũng chậm cập nhật hơn theo thời gian.
frequencyBinCount chỉ bằng đúng 1 nửa fftSize?
analyser.frequencyBinCount = fftSize / 2 giá trị thực sự hữu ích.
analyser tiếp tới destination
AnalyserNode chỉ là 1 điểm dò dữ liệu — nó KHÔNG tự động phát tiếp âm thanh ra loa. Nếu
chỉ source.connect(analyser) mà quên analyser.connect(destination),
visualizer vẫn vẽ được (vì đọc dữ liệu không cần phát ra loa) nhưng người dùng sẽ không nghe thấy gì
cả — 1 lỗi rất dễ bỏ sót vì visualizer trông vẫn "chạy đúng".
3. getByteFrequencyData() Và getByteTimeDomainData()
| Phương thức | Trả về gì | Dùng để vẽ |
|---|---|---|
getByteFrequencyData(array) |
Năng lượng (0–255) tại mỗi dải tần số (frequency bin) | Spectrum analyzer (thanh cột theo tần số) |
getByteTimeDomainData(array) |
Biên độ mẫu thô (0–255, tâm ở 128) theo thời gian | Waveform / oscilloscope (dạng sóng thô) |
Cả 2 đều cần gọi lại mỗi frame trong vòng lặp requestAnimationFrame — dữ
liệu chỉ phản ánh đúng khoảnh khắc hiện tại, không tự động cập nhật nếu không đọc lại.
smoothingTimeConstant làm mượt dữ liệu giữa các frame
analyser.smoothingTimeConstant (0–1, mặc định 0.8) trộn kết quả FFT khung hình hiện tại
với khung hình ngay trước đó theo tỉ lệ đó — giá trị càng cao, thanh spectrum càng
mượt mà/ít giật, nhưng phản ứng càng chậm hơn với thay đổi thực tế của âm thanh. Giá trị 0 cho dữ
liệu thô, giật nhưng phản ứng tức thời.
requestAnimationFrame, không phải setInterval
requestAnimationFrame tự động đồng bộ với tần số refresh màn hình và
tự tạm dừng khi tab ẩn (tab không hiển thị) — tiết kiệm CPU/pin đáng kể so với
setInterval chạy đều đặn dù người dùng không nhìn thấy gì.
Sân chơi tương tác: Spectrum Analyzer + Waveform
Bấm "Phát" và kéo tần số/dạng sóng — quan sát waveform (nửa trên) phản ánh đúng hình dạng sóng bạn chọn, và spectrum (nửa dưới) hiện rõ tần số cơ bản cùng các họa âm bậc cao đã học ở Bài 2.
Nhật ký
Trắc nghiệm ôn tập
Câu 1: Vì sao analyser.frequencyBinCount chỉ bằng đúng 1 nửa fftSize?
Trắc nghiệm ôn tập
Câu 2: smoothingTimeConstant càng cao thì điều gì xảy ra?
Trắc nghiệm ôn tập
Câu 3: Nếu chỉ source.connect(analyser) mà quên
analyser.connect(destination), điều gì xảy ra?