Mở đầu: bánh xe xe ngựa quay ngược trong phim cao bồi

Xem một cảnh phim xe ngựa phóng nhanh, bánh xe đôi khi trông như đang quay CHẬM LẠI rồi quay ngược — dù con ngựa vẫn đang lao về phía trước. Đây không phải lỗi kỹ xảo: máy quay chỉ chụp khoảng 24 khung hình mỗi giây, và nếu bánh xe quay đủ nhanh, mỗi khung hình chỉ bắt được một vị trí "gần đúng" của nan hoa — não bạn ghép các vị trí đó lại thành một chuyển động hoàn toàn khác với thực tế. Hiện tượng này có tên: aliasing (gập phổ, hay "giả trang tần số"), và nó không chỉ xảy ra với hình ảnh — nó là kẻ thù số một của mọi hệ thống lấy mẫu, kể cả ADC đang đọc giọng nói của bạn hàng vạn lần mỗi giây.

Bài này trả lời câu hỏi trung tâm mà Bài 1 để lại: lấy mẫu thưa đến đâu thì bắt đầu MẤT thông tin so với tín hiệu gốc? Câu trả lời — định lý Nyquist–Shannon — không chỉ là một công thức để nhớ, mà là một ranh giới cứng mà một khi đã vượt qua, KHÔNG phần mềm nào trên đời cứu lại được dữ liệu đã mất.


📚 Điều kiện tiên quyết
Bắt buộc: Bài 1 (x(t) vs x[n], chu kỳ rời rạc — chính verify "1000Hz và 3000Hz @ 8000Hz cho cùng chu kỳ 8 mẫu" ở cuối Bài 1 đã hé lộ toàn bộ nội dung bài này).

1. Lấy mẫu: chụp ảnh liên tiếp

Nhớ lại Bài 1: $x[n] = x(nT)$ — lấy mẫu là chụp lại giá trị của $x(t)$ tại các thời điểm cách đều $T = 1/f_s$ giây. Trực giác dễ hình dung nhất: giống một máy ảnh chụp liên tiếp cảnh một vật đang chuyển động — nếu chụp đủ nhanh so với tốc độ vật di chuyển, ghép các ảnh lại cho chuyển động mượt mà đúng thực tế; nếu chụp quá thưa, vật có thể "nhảy cóc" qua những vị trí không ai chụp được, và bộ não (hay thuật toán) khi ghép lại sẽ suy luận ra một chuyển động HOÀN TOÀN KHÁC — chậm hơn, hoặc thậm chí đảo ngược chiều.

Câu hỏi trung tâm của cả bài: chụp thưa đến đâu thì bắt đầu mất thông tin? Câu trả lời hoá ra có một ranh giới CHÍNH XÁC, không mơ hồ chút nào.

2. Định lý Nyquist–Shannon

Định lý lấy mẫu Nyquist–Shannon phát biểu: để khôi phục lại HOÀN TOÀN một tín hiệu từ các mẫu của nó, tần số lấy mẫu phải LỚN HƠN gấp đôi tần số cao nhất có mặt trong tín hiệu:

$$f_s > 2 f_{max}$$

Xây trực giác bằng chính ví dụ bánh xe: hãy tưởng tượng một cái strobe (đèn nháy) chớp đúng 2 lần mỗi vòng quay của bánh xe — bạn sẽ luôn thấy được vị trí gần đối xứng của nan hoa, đủ để nhận ra hướng quay thật. Chớp ít hơn 2 lần mỗi vòng — thông tin về hướng quay bắt đầu mơ hồ, có thể suy luận sai. Tần số đặc biệt $f_s/2$ — nửa tần số lấy mẫu — được gọi là tần số Nyquist: đây là "bức tường" cao nhất của thế giới số, tần số cao nhất một hệ lấy mẫu ở $f_s$ có thể biểu diễn đúng.

3. Aliasing — kẻ mạo danh

Khi một tín hiệu có tần số VƯỢT tường Nyquist, nó không biến mất — nó "gập" (fold) xuống thành một tần số THẤP HƠN, giả mạo một tín hiệu hoàn toàn khác mà bộ lấy mẫu KHÔNG THỂ phân biệt được với tín hiệu giả đó. Công thức tần số gập (tự viết, verify bằng số thật):

⚠️ Verify: gập phổ có thể ĐẢO PHA, không chỉ đổi tần số
Lấy mẫu sine 6000Hz ở tốc độ 8000Hz (Nyquist = 4000Hz — tần số này VƯỢT tường): verify từng mẫu — kết quả trùng CHÍNH XÁC với ÂM của sine 2000Hz (đảo dấu hoàn toàn, không chỉ đổi tần số). Đây chính là gốc rễ toán học của hiệu ứng "bánh xe quay ngược": khi tần số thật nằm giữa Nyquist và $f_s$, tín hiệu gập xuống KÈM đảo pha — quay lùi thay vì quay tiến.

Ngược lại, lấy mẫu sine 9000Hz ở CÙNG tốc độ 8000Hz: verify — kết quả khớp tuyệt đối, KHÔNG đảo pha với sine 1000Hz (chỉ đơn giản "cuộn vòng" qua $f_s$ một lần, không đi qua vùng phản xạ Nyquist). Cùng là aliasing, nhưng hai cơ chế khác nhau tuỳ vị trí tần số gốc so với $f_s$ và $f_s/2$.

Trong đời thực, aliasing xuất hiện khắp nơi: cánh quạt máy bay quay "ngược" trong phim (giống bánh xe ngựa), vân moiré kỳ lạ khi chụp ảnh một màn hình hoặc hoạ tiết sọc mịn (tần số không gian của hoạ tiết vượt "Nyquist không gian" của cảm biến máy ảnh), và tiếng rít lạ tai khi resample âm thanh ẩu (Bài 12 sẽ mổ xẻ kỹ).

⚠️ Pitfall: "đúng bằng 2× là đủ" — hiểu nhầm phổ biến
Định lý viết $f_s > 2f_{max}$ — dấu LỚN HƠN NGHIÊM NGẶT, không phải $\geq$. Tại đúng biên $f_s = 2f_{max}$, biên độ và pha của tín hiệu tại chính tần số đó có thể bị mất hoàn toàn (một trường hợp suy biến toán học). Thực tế luôn cần một khoảng đệm an toàn ("guard band") lớn hơn hẳn lý thuyết tối thiểu. Ví dụ kinh điển: tai người nghe tối đa khoảng 20kHz, nhưng chuẩn CD/audio chọn tần số lấy mẫu 44,1kHz chứ không phải đúng 40kHz — Nyquist của 44,1kHz là 22.050Hz, chừa ra đúng 2.050Hz đệm an toàn phía trên ngưỡng nghe của tai người, không phải một con số tuỳ tiện.

4. Anti-aliasing: phải lọc analog TRƯỚC khi lấy mẫu

Hệ quả quan trọng nhất của toàn bộ bài: một khi tín hiệu đã bị alias (lấy mẫu xong rồi mới phát hiện tần số vượt Nyquist), KHÔNG có thuật toán phần mềm nào phân biệt được đâu là tín hiệu thật, đâu là tần số giả — vì cả hai đã trở thành CÙNG MỘT dãy số $x[n]$. Việc "trộn" (alias) là vĩnh viễn ngay tại thời điểm lấy mẫu.

Giải pháp duy nhất: một mạch lọc analog (bộ lọc thông thấp RC hoặc phức tạp hơn — xem lại Series Điện Tử) đặt NGAY TRƯỚC ADC, cắt bỏ mọi tần số vượt Nyquist TRƯỚC khi tín hiệu kịp bị lấy mẫu. Đây chính là lý do mọi thiết bị thu âm nghiêm túc đều có một tầng lọc analog vật lý trước chip ADC (Series Nhúng Bài 10) — không phải trang trí, mà là điều kiện BẮT BUỘC để định lý Nyquist có ý nghĩa trong thực tế. Oversampling (lấy mẫu nhanh hơn cần thiết rồi lọc số sau) là một kỹ thuật giúp nới lỏng yêu cầu độ dốc của bộ lọc analog này — sẽ nhắc lại khi bàn về ADC thực tế.

5. Thực hành: Aliasing Stroboscope

Demo dưới đây chạy đúng công thức tần số gập vừa học: một chấm quay THẤY được đảo chiều thật, và một chirp quét qua Nyquist NGHE được alias gập xuống — cả hai đều tính bằng chính các hàm trong dsp-core.js:

🌀 Aliasing Stroboscope — DSPJS thật

1. Chấm quay stroboscope (strobe 5Hz — Nyquist 2,5Hz)

Đang tải…

2. Chirp quét qua Nyquist (fs=8000Hz giả lập, Nyquist=4000Hz)

Đường xanh dương là tần số THẬT (tăng đều 100→7500Hz); đường cam là tần số NGHE ĐƯỢC sau alias (tính bằng aliasFrequency()) — chú ý nó tăng đều rồi ĐẢO CHIỀU đi xuống ngay khi vượt Nyquist 4000Hz, khớp đúng verify Mục 3.

aliasing_demo.js (đúng logic đang chạy ở tab Xem trước)
import { aliasFrequency, aliasFrequencySigned, generateSignal } from './dsp-core.js';

// Chiec dom "banh xe" - khong can tinh toan gi dac biet: chi ve goc
// 2*pi*f*n/fs tai moi buoc strobe n - viec gap/dao chieu tu dong xay ra
// dung nhu ban chat toan hoc cua sine (Bai 1).
const STROBE_HZ = 5;
function wheelAngle(n, trueFreqHz) {
  return (2 * Math.PI * trueFreqHz * n) / STROBE_HZ;
}
console.log(aliasFrequencySigned(4, 5)); // -1 (quay NGUOC, vi 4Hz > Nyquist 2.5Hz)

// Chirp quet qua Nyquist - alias tu dong "nuong" san trong tung mau
const SIM_FS = 8000;
const chirpSamples = generateSignal('chirp', SIM_FS * 3, { f0Hz: 100, f1Hz: 7500, sampleRateHz: SIM_FS });
const ctx = new AudioContext();
const buffer = ctx.createBuffer(1, chirpSamples.length, SIM_FS); // sampleRate=8000 - trinh duyet tu resample luc phat
buffer.copyToChannel(new Float32Array(chirpSamples), 0);
const src = ctx.createBufferSource();
src.buffer = buffer;
src.connect(ctx.destination);
src.start();

// Tan so "nghe duoc" tai thoi diem t giay cua chirp:
function apparentFreqAtTime(tSec, f0=100, f1=7500, durationSec=3, fs=8000) {
  const trueFreq = f0 + ((f1 - f0) * tSec) / durationSec;
  return aliasFrequency(trueFreq, fs);
}
console.log(apparentFreqAtTime(2.5)); // tan so that ~6350Hz -> da gap xuong duoi Nyquist

Tóm lược

  • ✅ Định lý Nyquist–Shannon: $f_s > 2f_{max}$ để khôi phục trọn vẹn tín hiệu — tần số Nyquist $f_s/2$ là "bức tường" cao nhất của thế giới số.
  • ✅ Aliasing verified: sine 6000Hz @ 8000Hz gập thành ÂM của sine 2000Hz (đảo pha, cơ chế phản xạ qua Nyquist — gốc "bánh xe quay ngược"); sine 9000Hz @ 8000Hz khớp tuyệt đối sine 1000Hz (không đảo pha, chỉ cuộn vòng).
  • ✅ Pitfall: dấu $>$ nghiêm ngặt, không phải $\geq$ — thực tế cần guard band (44,1kHz cho tai 20kHz chừa đúng 2.050Hz đệm an toàn, không tuỳ tiện).
  • ✅ Anti-aliasing PHẢI là một mạch lọc analog TRƯỚC ADC — một khi đã alias là trộn vĩnh viễn, không phần mềm nào gỡ lại được.

Trắc nghiệm ôn tập

Câu 1

Định lý Nyquist–Shannon phát biểu điều gì?

Câu 2

Verified: sine 6000Hz lấy mẫu ở 8000Hz cho ra mẫu Y HỆT ÂM của sine 2000Hz (đảo pha), trong khi sine 9000Hz lấy mẫu ở CÙNG 8000Hz lại khớp tuyệt đối (không đảo pha) với sine 1000Hz. Vì sao hai trường hợp aliasing này khác nhau?

Câu 3

Vì sao chuẩn CD/audio chọn tần số lấy mẫu 44,1kHz thay vì đúng 40kHz (bằng đúng 2 lần ngưỡng nghe 20kHz của tai người)?

Câu 4

Vì sao bộ lọc chống alias (anti-aliasing filter) BẮT BUỘC phải là một mạch analog đặt TRƯỚC ADC, không thể là một thuật toán phần mềm chạy SAU khi đã lấy mẫu?

Tải file code thực hành minh họa bài học

File JavaScript DSPJS — thư viện DSP mini dùng xuyên suốt cả 15 bài, Bài 2 vừa thêm sampleContinuous, aliasFrequency, và aliasFrequencySigned, kèm self-test đối chiếu đúng mọi hành vi trong bài (chạy node dsp-core.js, không cần cài thêm gì):

Tải về dsp-core.js

📖 Tài liệu tham khảo

Bài viết liên quan trong series

Bài 1: Tín hiệu là gì: từ liên tục đến số Bài 3: Lượng tử hoá & dải động Quay lại Lộ trình Series Xử Lý Tín Hiệu Số

Bình luận