Xây dựng chương trình xử lý âm thanh số

Mục lục phần I: giới thiệu chung 1. Giới thiệu chung . 1 2. Đặt vấn đề . 1 3. Chủ đề của luận án 2 phần ii: cơ sở lý thuyết Chương 1: lý thuyết xử lý tín hiệu số 3 1. Tín hiệu số . 3 2. Xử lý tín hiệu số (DSP - Digital Signal Processing) . 3 2.1. Phép biến đổi Z . 4 2.2. Biến đổi Fourier rời rạc (DFT - Discrete Fourier Transform) 6 2.3. Lọc tín hiệu . 6 2.4. Hàm cửa sổ 7 2.5. Phép biến đổi nhanh Fourier (FFT - Fast Fourier Transform) . 8 2.6. Cepstrum . 9 Chương 2: giới thiệu chung về âm thanh số 10 1. Âm thanh và đặc tính của âm thanh 10 1.1. Sóng âm và cảm giác âm . 10 1.2. Độ cao của âm . 10 1.3. Âm lượng của âm (độ to của âm) 10 1.4. Âm sắc của âm 11 2. Âm thanh số 11 2.1. Nguyên lý 11 2.2. Tần số và cường độ . 12 3. Định dạng dữ liệu . 13 4. Khuôn dạng lưu trữ 15 phần III: giải pháp xử lý Chương 3: khuôn dạng tệp âm thanh 17 1. Khuôn dạng lưu trữ 17 1.1. Au/ Snd . 17 1.2. Voc 19 1.3. Wave/ Riff . 23 1.4. Aiff/ Aiff-C/ Aif/ Snd . 27 1.5. IFF/8 SVX 30 1.6. MIDI . 33 1.7. Mod/ Sam 36 1.8. MPEG . 39 1.9. VBA , VBase ADPCM (.VBA) . 42 1.10. VCE, NMS VCE (.VCE) 42 1.11. TXT . 42 1.12. SMP, SampleVision (.Smp) . 43 1.13. VOX 43 1.14. PCM, PCM Raw Data (.PCM) . 44 1.15. DWD , DiamondWare Digitized (.DWD) 44 1.16. RA, RealAudio 3.0 (.RA) . 44 2. Thao tác với tệp âm thanh . 44 2.1. Thu thanh tạo tệp âm thanh . 44 2.2. Soạn thảo . 45 2.3. Phát âm 45 Chương 4: Hàm cửa sổ và lọc tín hiệu 46 1. Hàm cửa sổ . 46 1.1. Rectangular . 46 1.2. Hamming . 47 1.3. Hanning . 47 1.4. Triangle (Bartlett) 47 1.5. Black man 48 1.6. Flat top 48 1.7. Exponent down . 48 2. Lọc tín hiệu . 49 Chương 5: FFt và cepstrum 50 1. FFT (Fast Fourier Transform) . 50 1.1. Nguyên lý 50 1.2. FFT trong âm thanh số 50 2. Cepstrum . 51 phần iV: thiết kế và cài đặt Chương 6: Phương pháp thiết kế . 53 1. Khái quát chức năng . 53 2. Cơ chế thực hiện . 54 Chương 7: Thao tác với tệp âm thanh . 55 1. Truy nhập tệp Wave 55 2. Truy nhập tệp Voc 56 3. Cấu hình dữ liệu 57 4. Soạn thảo 58 4.1. Nguyên lý 58 4.2. Thao tác dưới dạng trực quan . 59 4.3. Cơ chế thực hiện . 61 5. Phát thanh . 64 5.1. Thu thanh 64 5.2. Phát thanh . 64 Chương 8: Phân tích tín hiệu 66 1. Phổ biên độ . 66 Hàm cửa sổ (Windows) 69 2. Cepstrum . 74 3. Một vài trợ giúp khác 79 3.1. Xác định tần số trội (tần số trung bình vùng biên độ đỉnh) . 79 3.2. Tính phổ của mẫu cho trước 80 Chương 9: Hướng dẫn sử dụng 81 1. Giao diện chương trình . 81 2. Tuỳ chọn chức năng 82 phần v: Đánh giá chương trình 1. Đánh giá chương trình 83 2. Hướng phát triển . 83 3. Kết luận . 84 Phụ lục A: Giải thích thuật ngữ 85 Phụ lục B: Tài liệu tham khảo 86 Giới thiệu chung 1. Giới thiệu chung Cùng với sự phát triển của cuộc cách mạng khoa học và công nghệ đang diễn ra một cách sôi động, chúng ta đang tiến dần tới thế giới của sự số hoá. Với các ưu điểm của xử lý số, nhanh gọn, chính xác với chất lượng cao, mọi lĩnh vực hoạt động của xã hội loài người, nhất là các ngành trong các lĩnh vực thông tin liên lạc, phát thanh truyền hình . đều tiến tới việc áp dụng một cách đồng bộ và có hiệu quả các công cụ cũng như các phép xử lý số. Trong đó, âm thanh là một lĩnh vực đặc biệt quan trọng, đây là một phương thức dùng để trao đổi cũng như cảm nhận tin, không chỉ là tiếng nói, bản nhạc mà đó là tất cả các âm mà ta cảm nhận được trong cuộc sống hàng ngày, do đó, lĩnh vực về âm thanh không thể nằm ngoài xu hướng phát triển chung mà còn cần sự nghiên cứu sâu hơn nữa. 2. Đặt vấn đề Với âm thanh số, bằng việc lưu trữ âm thanh dưới dạng các dãy số, chúng ta đạt được yêu cầu về tốc độ truyền cũng như về khối lượng lưu trữ và độ trung thực trong các phép xử lý như khử nhiễu, soạn thảo hay các hiệu quả tạo độ vang, trễ . Do vậy, ngoài các phương tiện sử dụng kỹ thuật số, như camera số, thiết bị ghi số, điện thoại số . với chất lượng cao, thì những âm thanh tương tự được ghi từ micro với các nhạc cụ truyền thống đều được chuyển đổi sang dạng số hoá. Hơn nữa, với âm thanh, chúng ta không chỉ quan tâm tới khả năng cảm nhận một cách trung thực nhất âm thanh tự nhiên, mà ta còn hướng tới việc tạo ra (hay tổng hợp) được những âm thanh mà ta mong muốn. Do đó, khi nói đến âm thanh số thì cần thiết phải xét tới 3 khía cạnh: · Các khuôn dạng lưu trữ âm thanh với các đặc tính riêng biệt. Đây là yêu cầu trước tiên của bất kỳ quá trình thu thanh hay khi cần đọc dữ liệu để phân tích. Cần phải hiểu rõ các đặc tính cả từng khuôn dạng thì mới có thể lưu trữ một cách hiệu quả nhất. · Thao tác với các tệp âm thanh qua một trình soạn thảo âm thanh với các phép sao chép, cắt, dán, lọc, trộn âm hay chuyển đổi khuôn dạng tệp lưu trữ cũng như phương thức lưu trữ dữ liệu. Đây là cách để chúng ta có thể cảm nhận được âm thanh một cách rõ nét. · Phân tích tín hiệu của âm thanh bằng cách biểu diễn dữ liệu âm thanh dưới dạng tín hiệu tuỳ theo mục đích phân tích. Dữ liệu đọc từ tệp, sau đó qua các phép xử lý tín hiệu số như lọc, hàm cửa sổ, biến đổi FFT, Cepstrum . để có thể rút ra các tham số đặc trưng, các thông tin cần thiết cho các quá trình nhận dạng hay tổng hợp âm sau đó. 3. Chủ đề của luận án Chính vì vậy, với đề tài “Xây dựng chương trình xử lý âm thanh số” thì nhiệm vụ trước tiên sẽ phải nghiên cứu, tìm hiểu các khuôn dạng lưu trữ dữ liệu, sau đó xây dựng một chương trình (xử dụng ngôn ngữ lập trình Delphi) để thao tác với các tệp âm thanh và phân tích tín hiệu của các âm thanh đó.

doc87 trang | Chia sẻ: lvcdongnoi | Lượt xem: 6004 | Lượt tải: 1download
Bạn đang xem trước 20 trang tài liệu Xây dựng chương trình xử lý âm thanh số, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
ong trường hợp này, cần phải chuyển sang dạng âm nổi trước quá trình ghi. 2. Thao tác với tệp âm thanh Từ các khuôn dạng tệp âm thanh đã có sẵn hay được tạo ra, ta tiến hành các chức năng soạn thảo, chuyển đổi một cách trực quan trên phần sóng âm tương ứng được hiển thị. 2.1. Thu thanh tạo tệp âm thanh Có hai dạng xử lý âm thanh số hoá trên Windows: Dạng thứ nhất được Microsoft gọi là "Wave Form Audio", dựa trên nguyên tắc số hoá sóng âm. MPC lưu chúng trên bộ nhớ hay trong tệp *.Wav trên đĩa từ. Các dữ liệu số này thông qua phần cứng có thể biến đổi lại thành âm thanh. Dạng thứ hai là âm thanh được lưu trữ dưới dạng MIDI. Dạng tệp này chỉ lưu trữ các thông tin điều khiển bộ tổng hợp phát ra âm thanh (lưu trữ các nốt nhạc thay cho việc lưu trữ toàn bộ quá trình thu thanh). Chính vì vậy, kích thước tệp *.Mid nhỏ hơn nhiều so với các tệp *.Wav. 2.2. Soạn thảo Tất cả các bộ soạn thảo dạng sóng thực hiện các chức năng Cut, Copy, và Paste giống như xử lý word. Khi xét một bộ soạn thảo, đầu tiên phải mở một tệp âm thanh xác định phương pháp yêu cầu cho phần được ghi. Nhiều chương trình chấp nhận kỹ thuật nhấn và kéo chuột để chiếu sáng phần sóng âm thanh được hiển thị. Như chương trình soạn thảo GoldWave dùng nhấn chuột trái để chọn điểm bắt đầu, nhấn chuột phải để chọn điểm cuối. Khi chơi lại phần âm thanh được chọn luôn đảm bảo các điểm bắt đầu và kết thúc mà không bị cắt chậm hoặc nhanh. Các phần âm thanh được copy có thể được lưu trữ dưới khuôn dạng tệp duy nhất, trộn chính xác với một sóng âm khác đã có, hoặc chèn vào trong một dạng sóng gốc tại một điểm đã chọn. 2.3. Phát âm Khi phát âm thanh ra loa, ta có thể khuếch đại mức âm lượng theo mong muốn. Quá trình khuếch đại âm lượng này được thực hiện trên dữ liệu tệp Wave (với các dạng tệp khác ta có thể chuyển đổi sang dạng tệp Wave trước khi phát). Sau đó, có thể thực hiện phát âm thanh theo ba chế độ: Phát toàn bộ tệp Wave theo đường dẫn lựa chọn. Chỉ phát phần sóng âm được lựa chọn. Phát phần sóng âm được tạo ra trong màn hình soạn thảo. Để xác định chế độ phát âm, ta tạo một biến kiểm tra xem có phần lựa chọn hay không: nếu biến có giá trị "false" (tức là không có phần sóng âm nào được lựa chọn thì sẽ phát toàn bộ tệp Wave; nếu bằng "true" thì sẽ phát phần sóng âm được lựa chọn hiện thời. Với phần sóng âm trong màn hình soạn thảo thì có thể có một tuỳ chọn riêng: ta có thể ghi phần sóng âm này dưới dạng một tệp Wave hoàn chỉnh, và sau đó phát toàn bộ tệp; hoặc phát trực tiếp các đoạn sóng âm theo trình tự được ghép trên màn hình soạn thảo. Chương 4 Hàm cửa sổ và lọc tín hiệu 1. Hàm cửa sổ Phương pháp cửa sổ là một trong 3 phương pháp chính để tổng hợp bộ lọc số (phương pháp cửa sổ, lấy mẫu tần số, và phương pháp lặp). Hơn nữa, một tín hiệu có độ dài hữu hạn N có thể được biểu diễn hoàn toàn qua phép biến đổi Fourier rời rạc DFT. Tuy nhiên không thể tính DFT cho một tín hiệu có độ dài vô hạn hoặc quá lớn. Cho nên, để nghiên cứu phổ của những tín hiệu như vậy, ta có thể tính xấp xỉ bằng cách chặt lấy một đoạn thích hợp để xử lý. Và việc quan sát tín hiệu x(n) bằng một đoạn xN(n) trong khoảng từ n0 tới n0 + N-1 tương đương với việc nhân x(n) với một hàm cửa sổ w(n- n0): xN(n) = x(n). w(n- n0) = (2.1) Việc nhân tín hiệu với hàm cửa sổ theo thời gian tương đương với việc nhân chập phổ của tín hiệu x(n) với phổ của cửa sổ: XN(f) = X(g)W(f-g)dg = X(f)*W(f) (2.2) Trong đó XN(f), X(f), và W(f) là biến đổi Fourier tương ứng của xN(n), x(n), và w(n). 1.1. Rectangular Đây là dạng cửa sổ đơn giản nhất. Ta chỉ việc nhân tín hiệu với tín hiệu chữ nhật để có được một khúc tín hiệu của x(n). xN(n) = x(n).RectN(n-n0) = x(n).wR(n-n0) (2.3) Trong đó: wR(n-n0) = RectN(n-n0) = (2.4) là hàm cửa sổ chữ nhật. 1.2. Hamming Hamming là dạng cửa sổ được phát triển từ dạng Hanning. Những sự thay đổi là rất nhỏ, nhưng các kết quả đạt được lại rất khác nhau. Lý do cho những sự thay đổi là chỉ các điểm tại phần bắt đầu và phần cuối của tín hiệu. Sau khi cửa sổ Hanning đã được áp dụng cho tín hiệu thì những điểm này phần lớn đều là 0. Điều đó có nghĩa là chúng ta mất đi các tần số mà chúng có trong các vùng đó của tín hiêụ. Mặt khác, độ phân giải tốt hơn nhiều cho vấn đề đó lại bị xếp chồng nhau. Trong quá trình tính toán phổ, tín hiệu thời gian thường cũng chứa cả phần nửa dữ liệu thứ hai được chứa trong phần tín hiệu thời gian liền trước đó. Hệ số xếp chồng có thể thay đổi và thường trong khoảng 50 tới 90%. Dạng tổng quát của cửa sổ Hamming: w(n) = (2.5) 1.3. Hanning Dạng tổng quát của cửa sổ Hanning: w(n) = (2.6) 1.4. Triangle (Bartlett) Với mục đích làm giảm các búp sóng phụ của cửa sổ chữ nhật WR(f), ta chọn một dạng cửa sổ khác dạng tam giác cân gọi là cửa sổ tam giác (Triangle hay Bartlett). wT(n) = (2.7) Lý do chọn hàm naỳ là có thể biểu diễn wT(n) như là tích chập của cửa sổ chữ nhật có độ rộng N/2 với chính nó: wT(n) = . RectN/2(n+N/4) * RectN/2(n+N/4) (2.8) Một hạn chế của cửa sổ tam giác là N phải là số chẵn để đảm bảo độ rộng của cửa sổ chữ nhật là N/2. Và với cửa sổ này ta đạt được các búp phụ giảm nhưng bề rộng búp chính (4/N) lại lớn hơn so với cửa sổ chữ nhật (2/N).\ 1.5. Black man Công thức tổng quát của cửa sổ Black man như sau: wB(n)N = (2.9) Trong các quá trình phân tích tần số, các nhà nghiên cứu đã cố gắng tìm ra một loại cửa sổ có sự rò rỉ nhỏ nhất. Cửa sổ Black man là một trong những dạng đầu tiên đạt tới yêu cầu đó. Dạng cửa sổ Black man đã được phát triển theo hướng nghiên cứu muốn tìm ra một dạng cửa sổ lý tưởng. Ngày nay, dạng cửa sổ lý tưởng đó được biết tới như cửa sổ Kaiser. Cửa sổ Black man trở nên rất gần với cửa sổ Kaiser. Tuy nhiên, cửa sổ Kaiser rất hiếm khi được sử dụng do nó yêu cầu sự tính toán của hàm Bessel của dạng đầu tiên. Hàm này không được biết rộng rãi như các hàm được yêu cầu trong sự tính toán của các cửa sổ Hanning, Hamming, hay Black man. Dù rằng thực tế, Kaiser đã được xuất bản vào năm 1974 dựa theo mã Fortran để tính toán hàm Bessels. Ngày nay, cửa sổ Kaiser không được sử dụng trong việc phân tích tần số. Real Function I0(X) DS=1.0 D=0.0 S=1.0 1 D=D+2.0 DS=DS*X*X/(D*D) S=S+DS IF(DS-.2E-8*S) 2, 1, 1 2 I0 = S Return End 1.6. Flat top Dạng cửa sổ này đã được thiết kế một cách riêng biệt cho việc xác định biên độ trong phổ. Chúng ta cũng thấy rằng dạng cửa sổ này có sự rò rỉ ít hơn so với cửa sổ chữ nhật và nhiều hơn so với cửa sổ Hanning. Nhưng đây không phải là mục đích của dạng cửa sổ này. Trong trường hợp xấu nhất, sai số về biên độ là 0.2%. 1.7. Exponent down Khi trong quá trình thực hiện sự phân tích động hệ thống, hàm chuyền đạt hệ thống (system transfer function) được gọi phải được truy nhập. Cho mục đích đó, các giá trị của tín hiệu thời gian về phía cuối của nó phải được tiến gần tới 0 hay bằng 0. Hiệu ứng mà thủ tục đó tạo ra trên phổ tần số có thể được quan sát bằng cách sử dụng cửa sổ này. 2. Lọc tín hiệu Trước khi tính FFT để có thể phân tích tín hiệu qua phổ tương ứng của nó, ta có thể sử dụng một bộ lọc không truy hồi, hay còn gọi là bộ lọc gây méo trước để làm rõ phổ của tín hiệu. Bộ lọc này có đáp ứng xung luôn hữu hạn. Hàm của bộ lọc như sau: H(z) = 1- a*z-1 , với a < 1. (2.10) Đây là bộ lọc thông cao (High pass filter). Bộ lọc có tác dụng nhấn mạnh thành phần bậc cao, loại bỏ các thành phần thông thấp, đặc biệt là các phần tử một chiều. Với bộ lọc này, tín hiệu ra chỉ phụ thuộc tín hiệu vào. Ngoài ra, do nhiễu là các thành phần tần số cao nên cũng cần thiết sử dụng một bộ lọc thông thấp nhằm loại bỏ nhiễu. Chương 5 FFt và cepstrum 1. FFT (Fast Fourier Transform) 1.1. Nguyên lý Biến đổi Fourier được thực hiện dựa trên nguyên lý rằng ta có thể dùng bất cứ hàm tuần hoàn theo thời gian x(t) nào và chuyển nó sang dạng một phép tổng xác định của các sóng hình sin hay hình cosin tương ứng với các tần số bắt đầu tại 0 và tăng dần theo cấp số nhân một số nguyên lần của tần số cơ bản f0=1/T, với T là chu kỳ của x(t). Dĩ nhiên, ta không thể thực hiện một tổng không xác định của bất cứ loại nào trong sự tính toán thực, nên chúng ta phải thiết lập một tập xác định các hình sin và cosin. Điều này tạo thuận lợi cho đầu vào được lấy mẫu một cách số hoá, khi chúng ta quy định rằng số các mẫu tần số ra và các mẫu thời gian vào là như nhau. Hơn nữa, thật may mắn khi mọi quá trình thu thanh âm số hoá đều có độ dài xác định. Chúng ta có thể giả thiết rằng, hàm x(t) là tuần hoàn, và chu kỳ có cùng độ dài như quá trình thu thanh. Mặt khác, hãy coi qúa trình thu thanh được lặp mãi mãi, và gọi hàm lặp x(t). Quãng của phân đoạn lặp xác định tần số cơ bản f0, mà f0=samplingRate/N, với N là số các mẫu trong quá trình thu thanh. Ví dụ như vậy, nếu ta đang sử dụng một tần số lấy mẫu 44100 mẫu /giây, và độ dài quá trình thu thanh là 1024 mẫu, thì tổng thời gian được thể hiện bởi quá trình thu thanh là 1024/44100=0.02322 giây, nên tần số cơ bản f0 sẽ là 1/0.02322=43.07 Hz. Nếu ta xử lý 1024 mẫu này với FFT, đầu ra sẽ là các hệ số sin và cosin (giả sử là ak và bk) và cho các tần số 43.07Hz, 2*43.07Hz, 3*43.07Hz, vv... Để kiểm tra lại rằng sự tính toán hoàn toàn chính xác, ta có thể phát sinh mọi sóng hình sin và cosin tại các tần số này, nhân chúng với các hệ số ak và bk tương ứng, cộng chúng lại với nhau, và ta sẽ nhận được lại quá trình thu thanh gốc. 1.2. FFT trong âm thanh số Đặt vấn đề Vấn đề chính cùng với FFT cho quá trình xử lý các âm thanh là các quá trình thu thanh số phải được làm vỡ thành các khúc (chunks) với độ dài mỗi khúc là n mẫu, trong đó n luôn phải là một số nguyên bội của 2. Đầu tiên, sẽ lấy FFT của một khối, xử lý mảng ra FFT (ví dụ như điền 0 vào mọi mẫu tần số bên ngoài một dẫy xác định các tần số), sau đó thực hiện biến đổi ngược FFT để nhận lại tín hiệu trong miền thời gian đã được lọc. Khi âm được làm vỡ thành từng khúc giống như vậy, và được sử lý với FFT, kết quả nhận được sau khi lọc sẽ có những sự gián đoạn mà chúng dẫn đến việc có tiếng lách cách trong âm nhận được tại mỗi đường bao của khúc. Ví dụ như, nếu quá trình thu thanh có tần số lấy mẫu là 44,100Hz, và các khối có kích thước là n=1024, thì sẽ có một tiếng lách cách có thể nhận rõ tại mỗi khoảng 1024/(44,100Hz)=0.0232 giây. Giải pháp Để giải quyết điều này, ta có thể xử lý theo cách sau: Giả sử rằng kích thước bộ nhớ đệm là n = 2N. Trong bước lặp đầu tiên, đọc n mẫu từ âm vào, thực hiện FFT, xử lý, và IFFT, sau giữ lại dữ liệu theo thời gian nhận được trong bộ nhớ đệm thứ 2. Sau đó dịch nửa thứ 2 của bộ nhớ đệm gốc sang nửa đầu (chú ý rằng n là luỹ thừa của 2 nên nó chia hết cho 2), và đọc n/2 mẫu vào nửa thứ 2 của bộ nhớ đệm. Sau đó thực hiện biến đổi FFT, xử lý, và IFFT. Bây giờ thực hiện một phép suy giảm tuyến tính trên nửa thứ 2 của bộ nhớ đệm cũ mà nó đã được ghi từ bộ ba (FFT, xử lý, và IFFT) đầu tiên bằng cách nhân mỗi mẫu với một giá trị thay đổi từ 1 (cho mẫu số n/2) tới 0 (cho mẫu số n-1). Thực hiện phép tăng tuyến tính trên nửa đầu của bộ nhớ đệm ra mới (đi một cách tuyến tính từ 0 tới 1), sau đó cộng 2 nửa lại với nhau để nhận được một đầu ra với sự chuyển tiếp mịn. Chú ý rằng, các vùng xung quanh mỗi điểm gián đoạn được xoá bỏ thực sự từ đầu ra, qua một mức âm lượng thích hợp được giữ nguyên. Kỹ thuật này làm việc rất tốt khi quá trình xử lý không làm nhiễu loạn thông tin về phase của phổ tần số. Ví dụ như, một bộ lọc thông dải (bandpass) sẽ hoạt động rất tốt, nhưng ta có thể bắt gặp sự méo âm với sự dịch chuyển về cường độ. 2. Cepstrum Đặc điểm của homomorphic là sự biến đổi đại số tuyến tính mà nhờ đó có thể tách hai tín hiệu không cộng nhờ thuật toán phi tuyến trên cơ sở lọc tuyến tính. Tuỳ theo kiểu tổ hợp, ta tách thành hai khái niệm: Homomorphic nhân: tách tích của hai dãy tín hiệu. Tách tích chập homomorphic: tách tích chập của hai tín hiệu. Tín hiệu vào x(n) là tích của hai dãy phức x1(n) và x2(n). Để có thể tách hai dãy tín hiệu này bằng toán tử tuyến tính, ta cần phải lấy log phức. Và: (2.11) sẽ cho hai thành phần thực và ảo: (2.12) (2.13) Nếu phổ của các dãy không trùm hoặc trùm ít thì ta có thể dùng bộ lọc tuyến tính để lọc một tín hiệu và chặn tín hiệu còn lại. Khi đó đầu ra của hệ thống tuyến tính là dãy phức chỉ chứa log phức của một tín hiệu. Như vậy, khi dùng toán tử ngược của log tự nhiên ta sẽ nhận được một thành phần tín hiệu. Do đó, ta có sơ đồ tính Cepstrum như sau: Hình 3.2: Sơ đồ tính Cepstrum trong âm thanh Chương 6 Phương pháp thiết kế 1. Khái quát chức năng Sau khi đã nghiên cứu, tìm hiểu về các khuôn dạng lưu trữ âm thanh cũng như các kỹ thuật xử lý tín hiệu số, ta tiến hành thiết kế và xây dựng chương trình. Và, với chủ đề "Xây dựng chương trình xử lý âm thanh số", ta có thể tách các chức năng của chương trình thành 2 phần khá riêng biệt: âm thanh và tín hiệu của âm thanh. Với âm thanh, ta xét tới các đặc trưng của các khuôn dạng lưu trữ dữ liệu, cách tạo một tệp âm thanh và một số thao tác chuyển đổi dưới dạng trực quan. Và để có thể phân tích, nhận dạng các âm thanh với các tham số đặc trưng như tần số, cường độ..., thì ta phải xét tới dạng của tín hiệu cũng như phổ tương ứng của dữ liệu âm thanh đó. Do đó, ta có mô phỏng các chức năng của chương trình như sau: Hình 4.1: Mô hình xử lý 2. Cơ chế thực hiện Do dữ liệu đầu vào của chương trình là các tệp âm thanh nên chức năng đầu tiên của chương trình là mở tệp và đọc dữ liệu. Tuy nhiên, do có rất nhiều khuôn dạng tệp lưu trữ âm thanh khác nhau nên khi mở một tệp âm thanh ta phải kiểm tra để xác định khuôn dạng của tệp để từ đó có phương thức đọc tệp tương ứng. Trong chương trình, ta xét tới 2 khuôn dạng: tệp *.Wav và tệp *.Voc. Nói chung, ta nên kiểm tra dạng tệp Voc trước bởi tệp Voc có 20 bits ký hiệu định vị ngay đầu tệp nên khả năng có sự giả mạo dạng tệp là rất thấp, do đó nhanh chóng xác định được lệnh rẽ nhánh tiếp theo. Sau khi xác định được dạng tệp, ta sẽ có phương thức đọc dữ liệu tương ứng. Sau các chức năng xử lý và biểu diễn kết quả, chương trình có thể kết thúc hay tiếp tục mở một tệp mới để phân tích. Hình 4.2: Cơ chế hoạt động của chương trình Chương 7 Thao tác với tệp âm thanh 1. Truy nhập tệp Wave Mô phỏng cấu trúc WaveHeader: WaveHeader=record case boolean of false:( rID:longint; { 'RIFF' } rLen:longint; { dLen+36 } wID:longint; { 'WAVE' } fID:longint; { 'fmt ' } fLen:longint; { 16 wFT:word; { FormatTag : 1:PCM } nC:word; { Chanel: 1-mono; 2-stereo } nSp:word; { NumSamplesPerSecond } nAB:word; { 0: AvegBytesPerSecond } nBA:word; { BlockAligne = nSp*un1 } Fs:word; { 0: FormatSpecific } un1:word; { BitsPerSample:1-PCM8bit;2-PCM16bit } un2:word; { cbSize: 8-PCM8bits; 16-PCM16bits } dID:longint; { 'data' } dLen:longint; {NumBytes of TotalSamples } ); true:(hb:array[0..43]of byte); end; Định dạng dữ liệu Sau khi đọc khúc header định dạng (khúc "fmt "), ta sẽ biết được dữ liệu âm thanh PCM biểu diễn dưới dạng nào (dữ liệu trong khúc "data"). Điều đầu tiên mà ta cần biết là kích thước của mỗi mẫu dữ liệu. Giá trị này được xác định qua tham số un2 (nBitsPerSample) từ header định dạng. Nếu un2 nhỏ hơn hay bằng 8 bits, thì mỗi mẫu PCM sẽ là một byte, và sẽ xắp xếp theo các giá trị từ 0 tới 255. Tuy nhiên, nếu un2 là giá trị trong khoảng từ 9 tới 16 thì mỗi mẫu PCM sẽ chiếm 2 bytes, và giá trị nằm trong khoảng -32768 tới +32767 (và đây thực sự là một mâu thuẫn khi ta sử dụng dữ liệu dạng biểu diễn "unsigned" trong một khuôn dạng, và trong khuôn dạng khác lại là "signed"). Số kênh truyền Sau đó, ta cần biết số kênh truyền (numChannels - nC). Nếu chỉ là một kênh, thì dữ liệu PCM sẽ được xắp xếp theo thứ tự thời gian: mẫu đầu tiên sẽ ở đầu tệp, và mẫu cuối cùng định vị ở cuối tệp. Nếu có nhiều hơn một kênh, thì mọi mẫu cho chỉ số đầu tiên được đưa trước, quá trình lặp lại qua các kênh. Sau đó đưa ra mẫu tiếp theo, và tiếp tục lặp lại qua các kênh. Một cách mô phỏng, với số kênh tuỳ ý: i:= 0; While i < numSamples do Begin For c:= 0 to numChannels - 1 do {...xử lý Sample[i+c]...}; i:= i + numChanels; End; Cần chú ý rằng, nếu có 2 kênh thì giá trị đầu tiên trong mỗi cặp là của kênh trái, và giá trị thứ hai là của kênh phải. Do đó, ta có thể coi kênh trái như Channel 0, và kênh phải như Channel 1. Tần số lấy mẫu Và một định lượng quan trọng khác là tần số lấy mẫu (số mẫu/giây hay Hz - nSp: NumSamplesPerSecond). Tham số này thực sự quan trọng khi ta cần xử lý âm dựa trên các giá trị thời gian thực biểu diễn theo giây, hay cần thể hiện thông tin về tần số theo Hz (như khi sử dụng FFT). Do đó, cần lưu giá trị tần số lấy mẫu này vào một biến (Fs) để có thể áp dụng cho quá trình phân tích tín hiệu sau đó. 2. Truy nhập tệp Voc Do đặc tính của tệp Voc là gồm các khối nên cần phải đọc lần lượt cho tới khi hết tệp hay gặp khối dữ liệu. Ngoại trừ khối dạng 0 chỉ chứa một byte đơn giá trị 0 đánh dấu cuối tệp, khuôn dạng các khối khác đều gồm một header kích thước 4 bytes và tiếp theo là dữ liệu. Do đó, ta có cấu trúc chung: Khuôn dạng khối VocBlockFormat = record header: VocBlockHeader; data: VocData; End; Trong đó, dạng VocBlockHeader là cấu trúc chung cho mọi khối. VocBlockHeader = record blockType:byte; {1 byte định danh dạng khối } dataLen: longint; {3 byte xác định độ dài dữ liệu } End; Riêng phần VocData là khác nhau. Tuy nhiên ta chỉ cần xét các khối dạng 1, dạng 8 và dạng 9. Bởi vì đây là các khối chứa thông tin về khuôn dạng lưu trữ dữ liệu. Khối dạng 1: VocData1 = record SamRateCode :byte; {1 byte mã tần số lấy mẫu} DataCompresCode :byte; {1 byte mã phương thức nén dữ liệu} End; Trong đó, tần số lấy mẫu được tính theo công thức: Fs = 1000000/(256 - SamRateCode); Và mã phương thức nén trong bảng thuộc phần khuôn dạng tệp Voc. Tuy nhiên, 2 dạng thường dùng là: 0 - PCM 8bits; 4 - PCM 16bits. Khối dạng 8: VocData8 = record SamRateCode :word; {2 byte mã tần số lấy mẫu} DataCompresCode :byte; {1 byte mã phương thức nén dữ liệu} Mode :byte; {0: mono; 1: stereo} End; Trong đó, tần số lấy mẫu được tính theo công thức: Fs = 256*1000000/(65536 - SamRateCode); Fs = Fs *2; Khối dạng 9: VocData9 = record SamRate :longint; {4 byte tần số lấy mẫu} NumBitsPerSam :byte; {Số bits cho mỗi mẫu} NumChannel :byte; {Số kênh truyền: 1-mono; 2-stereo} DataCompresCode :word; {2 byte mã phương thức nén dữ liệu} Exten :longint; {Phần mở rộng} End; 3. Cấu hình dữ liệu Do đôi khi không cần thiết phải đọc toàn bộ các mẫu dữ liệu trong tệp để phân tích (ví dụ như khi tín hiệu là tuần hoàn, trong mỗi chu kỳ tín hiệu là như nhau), hay do số mẫu quá lớn (làm chậm thời gian đọc và xử lý), nên ta chỉ cần đọc một số mẫu nhất định (NPTS mẫu). Tuy nhiên, để tạo sự bao quát toàn bộ tệp, ta có thể tuỳ chọn vị trí mẫu bắt đầu được đọc. Hình 4.3: Cấu hình dữ liệu Dữ liệu được đọc từ tệp và gán vào một mảng kiểu nguyên (integer) (do các tệp có lưu dữ liệu theo byte), và sau đó biểu diễn tín hiệu theo dạng thời gian. Hình 4.4: Biểu diễn dữ liệu gốc theo thời gian 4. Soạn thảo 4.1. Nguyên lý Trong phần này, ta thực hiện một số thao tác trực quan trên màn hình. Tức là thao tác qua sự hiển thị của dữ liệu gốc được biểu diễn theo thời gian. Ta chỉ áp dụng với dữ liệu gốc, tức là dữ liệu âm thanh chưa được xử lý (chưa qua các quá trình lọc hay được giới hạn qua hàm cưả sổ). Và các phép xử lý này chỉ tác động lên một tệp âm thanh trong mỗi phiên làm việc, có nghĩa là mọi thao tác xử lý trên phần sóng âm của một tệp được hiển thị trên màn hình, sau đó nếu muốn lưu các thay đổi thì các tệp âm mới sẽ có định dạng như tệp gốc. Chúng sẽ có cùng header với tần số lấy mẫu, số kênh truyền, ... chỉ khác các mẫu dữ liệu. Nên, nếu F là tham số tệp gốc, và Fsave là tham số của tệp âm mới được lưu sau một số thao tác soạn thảo, và header có dạng WaveHeaderFile (trong chương trình mới chỉ áp dụng soạn thảo trên tệp Wave, tuy nhiên muốn soạn thảo trên khuôn dạng khác ta có thể chuyển đổi khuôn dạng về dạng Wave, hay nói chung cơ sở của thuật toán trên các khuôn dạng khác cũng tương tự như vậy). Assigned(F, MainFilename); Assigned(Fsave, CurentFilename); Reset(F); Rewrite(Fsave); BlockRead(F, Header, 44); {... Thay đổi tham số về độ dài dữ liệu ...} BlockWrite(Fsave, Header); Close(F); Close(Fsave); 4.2. Thao tác dưới dạng trực quan Thực chất của các thao tác là tác động một cách trực quan lên hai màn hình: màn hình biểu diễn sóng âm gốc và màn hình soạn thảo. Nếu các thao tác chỉ đơn giản là cắt hay xoá bớt các mẫu của dữ liệu gốc thì chỉ cần một màn hình biểu diễn dữ liệu gốc là đủ. Bởi ta sẽ cắt, xoá ngay trên phần sóng âm gốc, và sau đó ghi phần sóng âm còn lại dưới dạng một tệp mới có cùng định dạng kiểu. Để có thể chọn phần dữ liệu tác động, ta sử dụng phương pháp nhấn và kéo chuột để khoanh vùng dữ liệu, hay chọn toàn bộ phần sóng âm hiển thị. Hình 4.5: Chọn một phần dữ liệu Theo cách nhìn trực quan cũng như xét theo khía cạnh về sự thay đổi của sóng âm gốc, thì thay đổi do các phép cắt, xoá tạo ra là như nhau: phần dữ liệu lựa chọn bị xoá mất, và khi lưu tạo tệp mới thì các mẫu dữ liệu phía sau sẽ dồn lên chiếm chỗ các mẫu dữ liệu đã mất. Hình 4.6: Xoá phần dữ liệu đã chọn Tuy nhiên, những thay đổi đó chỉ có thể làm thay đổi vị trí chứ không phải trình tự lưu trữ dữ liệu. Muốn có một trình tự mới, ta phải cắt, ghép các phần sóng âm tương ứng tuỳ theo mong muốn. Chính vì vậy, ta cần một màn hình thứ 2 (chính là màn hình soạn thảo) để có thể biểu diễn các phân đoạn sóng âm theo một trình tự nào đó. Hình 4.7: Màn hình soạn thảo Do đó, có sự khác nhau giữa lệnh cắt và xoá. Lệnh cắt khác ở chỗ xoá phần sóng trên màn hình nhưng lại lưu vào bộ nhớ đệm. Mặc dù ta có thể lưu ảnh của phần sóng âm, và như vậy khi lệnh dán được kích hoạt ta sẽ dán ra màn hình ảnh tương ứng, nhưng khi tạo một tệp dữ liệu ta phải xét tới các mẫu dữ liệu, do đó phải lưu thông tin về các mẫu đã tác động. 4.3. Cơ chế thực hiện Màn hình sóng âm gốc Khởi tạo một mảng kiểu “boolean” (DelCut: array ...) có kích thước bằng kích thước của mảng lưu trữ các mẫu dữ liệu. Mỗi khi mở một tệp mới, mọi thành phần trong mảng được khởi tạo giá trị “true”. Trên màn hình sóng âm gốc, khi có bất cứ thao tác cắt hay xoá nào xẩy ra (có nghĩa là một số mẫu dữ liệu đã bị mất), ta sẽ đánh dấu vị trí các mẫu tương ứng bằng cách gán giá trị “false”: Begin for i:=StartPoint to FinitPoint do DelCut[i]:=false; CutDel:=true; End; Trong đó, StartPoint và FinitPoint là vị trí mẫu bắt đầu và cuối cùng của phần bị xoá. Để có thể tính được vị trí các mẫu tương ứng này, ta phải xác định toạ độ (theo toạ độ màn hình) điểm bắt đầu và kết thúc khi nhấn và kéo chuột khi muốn chọn một phần sóng âm, sau đó quy ngược lại các mẫu tín hiệu có vị trí tương ứng. Ngoài ra, sử dụng thêm biến kiểm tra trạng thái CutDel: false - không có thay đổi nào với các mẫu; true - đã có thay đổi (một số mẫu đã bị xoá). Sau đó, khi muốn ghi tệp âm đó sang một tệp mới ta sẽ chép toàn bộ các mẫu trong tệp gốc sang tệp mới, tức là các mẫu trong khoảng từ mẫu thứ nhất, tới vị trí mẫu liền trước vị trí mẫu đầu tiên được đọc ra; và các mẫu từ vị trí liền sau mẫu cuối cùng được đọc ra tới cuối tệp. Seek(F,44); For i:=1 to DebutPoint-1 do {... sao chép các mẫu từ F sang Fsave ...}; và: seek(F, 44+ (DebutPoint + NumSamples)*numBytesPerSample); While not eof(F) do {... sao chép dữ liệu từ F sang Fsave ...}; Nhưng sẽ kiểm tra riêng các mẫu tín hiệu tương ứng với phần sóng âm trên màn hình qua biến DelCut[i]. Và phần sóng âm này gồm NumSamples mẫu tín hiệu liên tiếp bắt đầu từ mẫu thứ DebutPoint trong tệp dữ liệu. for i:= 1 to NumSamples do begin if DelCut[i] then begin seek(F,44+ (DebutPoint+i)*numBytesPerSample); {... read(F,temp);write(fSave,temp);...} end; end; Trong đó, numBytesPerSample là số byte mà mỗi mẫu dữ liệu cần lưu trữ: 1- dạng dữ liệu PCM 8bits; 2- dạng dữ liệu PCM 16bits. Ngoài ra, phần sao chép các mẫu giữa các tệp phải lưu ý tới số kênh truyền, 1: dạng mono và 2: dạng stereo, và dạng lưu trữ dữ liệu PCM, 8 hay 16 bits tức là số các byte dùng để lưu trữ mỗi mẫu. Hình 4.8: Sóng âm tệp gốc và của tệp sao chép với một số mẫu đầu bị xoá Ghi phần dữ liệu được lựa chọn Ta có thể chọn một phần dữ liệu trên phần sóng âm gốc để lưu dưới dạng một tệp riêng. seek(F,44 + (DebutPoint + StartPoint)* numBytesPerSample); for i:= 1 to (FinitPoint-StartPoint+1)*numBytesPerSample do begin read(F,temp); write(fSave,temp); end; Hình 4.9: Sóng âm phần lựa chọn Màn hình soạn thảo Đây là màn hình ta dùng để hiển thị các phân đoạn sóng âm được dán sau khi đã thực hiện lệnh sao chép hay cắt. Mỗi lần dán, các phân đoạn sẽ được xếp kế tiếp nhau. Cho nên, để đạt được theo một trình tự mong muốn, ta sẽ sao chép hay dán các phân đoạn mong muốn theo trình tự đó. Hơn nữa, các biến FinitPoint và StartPoint sẽ nhận giá trị tương ứng ngay sau các phép cắt hay sao chép xảy ra (như bộ nhớ đệm chỉ lưu duy nhất một giá trị). Nên khi dán, thao tác sẽ xử lý với dữ liệu của phần lựa chọn sau cùng. Và để lưu phần sóng âm trên màn hình soạn thảo, ta sử dụng mảng PointEdit có cùng kiểu với dữ liệu trong tệp âm (integer). Mỗi lần thực hiện thao tác dán, ta sẽ đọc các mẫu tín hiệu tương ứng từ tệp gốc và gán vào các giá trị PointEdit[i]. seek(F,44+ (StartPoint + DebutPoint)*numBytesPerSample); for i:= 1 to (FinitPoint-StartPoint+1)*numBytesPerSample do begin read(F,temp); PointEdit[i + NumEdit] :=temp; end; NumEdit:=NumEdit+(FinitPoint-StartPoint+ 1)*numBytesPerSample; Trong đó, NumEdit là một biến kiểu nguyên và nhận giá trị là số mẫu hiện thời có trong mảng PointEdit. Khi mở một tệp mới hay khi bắt đầu một phiên cắt ghép các phân đoạn sóng mới, biến NumEdit sẽ nhận giá trị khởi đầu là 0. Khi thao tác ghi phần soạn thảo được kích hoạt, sau phần header cùng định dạng ta sẽ gán toàn bộ các giá trị trong mảng PointEdit vào các bytes liên tiếp trong tệp mới với cùng trình tự. Hình 4.10: Sóng âm của tệp được cắt ghép từ một số phân đoạn 5. Phát thanh 5.1. Thu thanh Để có thể tạo được một tệp âm thanh, ta phải sử dụng một số thiết bị chuyên dụng như micro, soundblaster hay soundcard... Âm thanh qua micro được các trình điều khiển âm thanh chuyển thành dạng số và lưu trữ dưới dạng tệp Wave. Tuy nhiên, để đạt được điều đó, ta phải xác định một số tham số nhằm định dạng lưu trữ dữ liệu. Đó là các tham số như tần số lấy mẫu, dạng âm thanh mono hay stereo, số bits cho mỗi mẫu ... Trong chương trình ta ấn định luôn số kênh truyền là 1 (âm thanh dạng mono). 5.2. Phát thanh Trong chương trình, ta chỉ xét tới trường hợp phát toàn bộ một tệp âm thanh. Nếu muốn phát một đoạn nào đó trong tệp âm thanh tuỳ ý, ta sẽ sao chép riêng phần đó và lưu dưới dạng một tệp Wave mới (sử dụng chế độ soạn thảo âm như phần trên), sau đó sẽ phát tệp âm này. Để có thể phát âm thanh ra loa, thiết bị cần nhận tên tệp và một số tham số đặc trưng của âm thanh. Chương trình có thể ứng dụng cho cả dạng âm thanh (Wave file) và dạng hình ảnh video (Midi file). Delphi hỗ trợ rất nhiều trong việc tích hợp hoạt ảnh và âm thanh vào các ứng dụng. Thông thường có 2 cách: a) Sử dụng các chức năng riêng biệt trong Win32 API. Cách sử dụng này rất đơn giản. Ta chỉ cần sử dụng một hàm đã được hỗ trợ: PlaySound('Path', 0, SND_SYNC); Trong đó 'Path' có thể là đường dẫn tên tệp, địa chỉ bộ nhớ, hay sự kiện hệ thống. Ngoài ra, ta có thể phát âm thanh từ định vị bộ nhớ. Điều thuận lợi là người sử dụng không thể truy cập trực tiếp vào tệp âm thanh. Như vậy, ta cần tải âm thanh vào bộ nhớ, sau đó dùng một con trỏ để chỉ tới dữ liệu âm thanh, và dùng cờ SND_MEMOIRY để báo cho PlaySound API rằng ta đang sử dụng định vị bộ nhớ thay vì tên tệp. f:=CreateFile ('Path',GENERIC_READ,0,nil,OPEN_EXISTING,0,0); if not (f=INVALID_HANDLE_VALUE) then begin ReadFile(f,ArrSample, MaxSize,sizs,nil); CloseHandle; end; .... PointDat:=ArrSample; PlaySound(PointDat, 0, SND_ASYNC or SND_MEMORY); Trong đó, PointDat là con trỏ chỉ tới mảng dữ liệu âm thanh ArrSample có kích thước là MaxSize. b) Sử dụng các thành phần để thực hiện các chức năng về multimedia. Ta sử dụng hợp thành Media Player. Có thể sử dụng trực quan qua tập các nút chức năng như "Record", "Play", "Stop",... hay điều khiển qua mã lệnh chương trình. MediaPlayer.FileName:=OpenDialog.FileName; MediaPlayer.Open; Chương 8 Phân tích tín hiệu 1. Phổ biên độ Chính vì bất cứ âm thanh nào cũng có thể làm vỡ thành các sóng hình sin nên ta có thể miêu tả dạng phổ tần số của âm thanh. Phổ tần số của âm thanh là một đồ thị với hai trục biên độ và tần số. Từ đồ thị này, ta có thể xác định được các tần số của âm thanh. Thông thường, tần số cơ bản cũng là tần số mạnh nhất mà nó xuất hiện trong âm thanh. Từ tần số cơ bản, ta có thể cảm nhận được cường độ âm thanh tổng thể. Hơn nữa, tần số của một âm phức tạp chính là tần số của một sóng hình sin với cùng một cường độ cảm nhận được. Tần số cơ bản này cũng là tần số của sóng hình sin mạnh nhất trong âm thanh. Vì vậy, ta có thể dự đoán được cường độ của âm thanh bằng cách đo phổ tần số và nhặt ra thành phần lớn nhất. Tuy nhiên, trong một số trường hợp, tần số cơ bản là rất trầm hay thậm chí là hoàn toàn biến mất, và chúng ta vẫn nghe thấy cùng một cường độ. Hơn nữa, nếu âm thanh chứa nhiễu thì tuỳ mức độ, ta rất khó xác định được các tần số âm thanh. Trước hết, ta xét một tín hiệu được biểu diễn dưới dạng thời gian. Đây là tín hiệu gốc chưa được xử lý (lọc và giới hạn qua hàm cửa sổ): Hình 4.11: Tín hiệu trong miền thời gian Với một tín hiệu như vậy, không qua các phép tiền xử lý, ta quan sát phổ tương ứng: Hình 4.12: Phổ của tín hiệu gốc Toàn bộ phổ bị làm mờ đi do sự bao phủ của toàn bộ dải tần lớn của các tần số mà chúng không có trong tín hiệu gốc. Hiệu ứng này thường được gọi là hiện tượng rò rỉ (leakage). Đây luôn là một vấn đề khi ta xét tới các tần số, mà tại đó ta tính toán biên độ, lại không phù hợp với các tần số có trong tín hiệu gốc. Do đó, để làm rõ hơn, ta chọn số các chu kỳ của tần số trong tín hiệu gốc là một số không nguyên. Hình 4.13: Tín hiệu gốc với số chu kỳ không nguyên Và ảnh phổ tương ứng: Hình 14: Phổ tương ứng số chu kỳ không nguyên Ta thấy một phần chu kỳ cuối cùng của tín hiệu bị mất. Trong phổ tương ứng ta có thể thấy hiện tượng bị méo là rất rõ khi mà ta tính toán biên độ tại tần số của tín hiệu gốc nằm giữa hai đường. Vấn đề cơ bản của các quá trình phân tích tần số (hiện nay và trong tương lai) là hiện tượng bị méo bị tạo ra do các tần số có một số không nguyên các chu kỳ trong tín hiệu được phân tích. Nhưng ta cũng có thể xem xét nó theo một khía cạnh khác. Nếu hiện tượng méo đó sẽ không được hiển diện, thì sẽ cần thiết tính toán biên độ tại tần số đã biết (giá trị thực tế và giá trị trong phổ tương ứng là khác nhau). Nên hầu như là sẽ không thể nhận được một phổ hoàn chỉnh. Và thông thường, chúng ta quan tâm tới 2 khía cạnh: Biên độ chính xác tương ứng với tần số chỉ định. Tần số của đỉnh hiện thời hiển thị trong phổ. Cả hai vấn đề này đã được giải quyết. Tuy nhiên, nếu tần số của tín hiệu rơi vào giữa 2 dòng, thì hầu như ta không thể nói được tần số hay biên độ thực sự của tín hiệu đó. Và làm thế nào để có thể biết được đâu là các tần số thực sự mà chúng ta có thể quan sát. Để có thể quan sát được những thay đổi của biên độ tương ứng với tần số, ta sẽ đo trực tiếp trên phổ của nó. Và ta thấy biên độ trong phổ luôn thấp hơn so với thực tế khoảng 36%, và tần số luôn được quy trong theo dòng. Rất nhiều phương thức khác nhau đã được phát triển nhằm làm cho các quá trình phân tích tần số trở nên dễ dàng, chính xác và nhanh hơn. Một trong các phương pháp nổi tiếng là sử dụng hàm các cửa sổ. Hàm cửa sổ (Windows) Các hàm cửa sổ được sử dụng để thao tác với dữ liệu (tín hiệu gốc) theo cách mà thông tin mong muốn có thể được chiết xuất từ phổ. Điều đầu tiên mà ta cần phải biết về các hàm cửa sổ là hiệu ứng của một tần số tuần hoàn (period frequency) không nguyên, như một kết quả trực tiếp của hàm cửa sổ. Trong thực tế, tín hiệu cần phân tích được giới hạn về độ dài, hoạt động giống như một cửa sổ. Cửa sổ này thường được gọi là cửa sổ chữ nhật (Rectangular). Chúng ta đã có một hiệu ứng cửa sổ mà không phải áp dụng bất cứ sự chuyển đổi nào. Và với một hàm cửa sổ nói chung, chúng ta sẽ nhận được một cách chính xác nhất có thể các biên độ và tần số tín hiệu hiện thời. Và, tuỳ theo yêu cầu phân tích tín hiệu qua phổ của tín hiệu mà ta sử dụng dạng cửa sổ tương ứng. Sau đây là một số hàm cửa sổ thông dụng. Hanning Với tín hiệu được giới hạn qua cửa sổ Hanning: Hình 4.15: Hanning Và phổ tương ứng: Hình 4.16: Phổ biên độ với cửa sổ Hanning Hình 4.17: Phổ biên độ với cửa sổ chữ nhật Ta hãy quan sát hiệu ứng rò rỉ cũng như độ chính xác về biên độ trong phổ tương ứng. So với cửa sổ chữ nhật, ta thấy hiện tượng làm mờ phổ vẫn còn rõ thậm chí với ngay cả một số nguyên các chu kỳ, và hơn nữa đỉnh tương ứng cũng hẹp hơn. Tuy nhiên, độ chính xác về biên độ lại tốt hơn, sai số lớn nhất chỉ còn 15% thay vì 35% như đồi với cửa sổ chữ nhật. Một cách rõ ràng rằng hiệu ứng rò rỉ của cửa sổ Hanning nhỏ hơn rất nhiều so với cửa sổ chữ nhật. Bất lợi duy nhất của cửa sổ Hanning so với cửa sổ chữ nhật là đỉnh sẽ rộng hơn khi có một số nguyên các chu kỳ. Nhưng điều này cũng đủ để bù lại có độ chính xác về biên độ cao và hiện tượng rò rỉ thấp. Bởi vì, trên thực tế để có thể đạt được độ chính xác về biên độ cao hơn ta phải chấp nhận với một đỉnh rộng hơn. (Cửa sổ Flat top đã được phát triển riêng với mục đích đó). Trong thực tế, cửa sổ Hanning là dạng thông dụng nhất do có sự rò rỉ thấp. Điều này thể hiện ở chỗ, với cửa sổ chữ nhật thì tần số thứ hai hầu như không hiển thị. Nơi mà rất cần thiết để có thể quan sát các tần số với các biên độ nhỏ bên cạnh các biên độ lớn. Flat top Đây là dạng cửa sổ được thiết kế riêng cho các phép đo biên độ phổ. Hình 4.18: Phổ biên độ với cửa sổ Flat top Từ phổ tương ứng, ta có thể nhận thấy có ít sự rò rỉ hơn so với cửa sổ chữ nhật, nhưng lại nhiều hơn so với cửa sổ Hanning. Mặc dù vậy, đây không phải mục đích của dạng cửa sổ này. Trong trường hợp xấu nhất biên độ chỉ có sai số 0.2%. Black man Quan sát phổ tương ứng, ta thấy sự rò rỉ nhỏ hơn một chút so với cửa sổ Hanning nhưng với đỉnh rộng hơn, và độ chính xác tốt hơn một chút so với cửa sổ Hanning. Nói chung, đây là dạng cửa sổ tốt nhất cho phần lớn ứng dụng. Hình 4.19: Phổ biên độ với cửa sổ Black man Hamming Nhưng quan sát phổ tương ứng, ta thấy rằng sự rò rỉ là lớn (gần như đối với cửa sổ chữ nhật), và sự chính xác về biên độ với sai số cực đại là 18.1%. Và cửa sổ Hamming có búp phụ thứ nhất rất nhỏ so với cửa sổ Hanning. Cho nên cửa sổ Hamming kém hơn so với cửa sổ Hanning, nhưng lại tốt hơn so với cửa sổ chữ nhật. Hình 4.20: Phổ biên độ với cửa sổ Hamming Tóm lại, biểu diễn dạng phổ phản chiếu các thuộc tính thay đổi theo thời gian của sóng âm. Với Hamming, tính tuần hoàn của tín hiệu là rất rõ ràng, phổ tương ứng với tần số cơ bản và tính hài hoà hiện ra giống như các đỉnh hẹp tại các tần số được khoảng cách hoá một cách đều nhau trong biến đổi Fourier thời gian ngắn. So sánh giữa cửa sổ Hamming và cửa sổ chữ nhật: Phổ của Hamming mịn hơn so với phổ của cửa sổ chữ nhật. Cửa sổ chữ nhật do có sự sắc nhọn tăng của các hàm điều hoà cường độ, nên độ phân giải tần số lớn hơn so với cửa sổ Hamming có cùng độ dài. Hơn nữa, các "lobes" cạnh lớn có liên quan của cửa sổ chữ nhật tạo ra một sự không đồng đều hay phổ bị nhiễu. Hiệu ứng này xuất hiện là do "side lobes" dẫn tới việc các hàm điều hòa lân cận tương tác với nhau trong khoảng trống giữa các hàm điều hoà - đôi khi tăng cường, nhưng đôi khi huỷ bỏ - theo cách đó tạo ra sự thay đổi xuất hiện ngẫu nhiên giữa các hàm điều hoà (harmonics). Sự rò rỉ (leakage) không mong muốn giữa các hàm điều hoà lân cận hướng tới việc định vị các lợi điểm của "lobe" chính hẹp hơn của cửa sổ chữ nhật. Nên các cửa sổ như vậy rất hiếm khi được sử dụng trong việc phân tích phổ tiếng nói. Tóm lại, độ phân giải tần số thay đổi nghịch đảo với độ dài của cửa sổ. Hơn nữa, mục đích của hàm cửa sổ là để giới hạn quãng thời gian của tín hiệu phân tích để cho các thuộc tính của sóng âm không thay đổi một cách đáng kể, thì ta cần sự lựa chọn như vậy. Và tuỳ theo cửa sổ, với một quãng phân tích ngắn có thể làm sai lệch đi một cách rõ rệt các phép biến đổi Fourier thời gian ngắn khác nhau. Vì vậy, một độ phân giải theo thời gian tốt yêu cầu một cửa sổ ngắn, trong khi độ phân giải tần số tốt lại yêu cầu một cửa sổ dài. Ngoài ra, trong phép biến đổi Fourier, phương thức chèn thêm các giá trị 0 là rất quan trọng để có thể hiểu rõ hơn về cách thức FFT hoạt động. Ví dụ như, FFT yêu cầu số các mẫu nên là 8, 16, 32, 64... nhưng tín hiệu lại không phải luôn có độ dài mong muốn. Do đó, trong những trường hợp như vậy ta cho phép một phần của tín hiệu được thiết lập về 0. Ta có thể quan sát các hiệu ứng xảy ra trong phổ biên độ nhận được bằng cách thay đổi bộ đệm 0 về 0. 2. Cepstrum Trong ảnh phổ xuất hiện các họ hài với chu kỳ của nguồn xung làm cho việc quan sát trở nên khó khăn. Nếu cùng lúc có nhiều nguồn xung tuần hoàn với các tần số khác nhau, trong ảnh phổ sẽ xuất hiện các họ hài với các chu kỳ khác nhau của các nguồn, nên cần phải dùng đến Cepstrum. Trong Cepstrum ta có thể nhận ra các xung nhảy vọt đặc trưng cho các họ hài của phổ. Nếu ta chặn được các xung của Cepstrum này, tính được dãy tín hiệu theo thời gian sau khi đã dùng phép biến đổi ngược, thì lúc đó ta sẽ có dạng đáp ứng xung đặc trưng cho sự truyền đạt của hệ thống. Nếu dùng lọc tần số thấp để chặn tất cả các tín hiệu trừ xung của Cepstrum đặc trưng cho nguồn xung thì sau phép biến đổi ngược ta nhận lại được tín hiệu theo thời gian của đáp ứng nguồn xung. Hình 4.21: Tín hiệu tuần hoàn Hình 4.22: Cepstrum tương ứng với tín hiệu tuần hoàn Ta thấy Cepstrum biến đổi tương đối chậm đặc trưng cho hàm truyền đạt và Cepstrum nhảy vọt đại diện cho sự lặp lại tuần hoàn. Tiến hành lọc các thành phần biên độ thấp tại điểm t = 6,47ms: Hình 4.23: Ngưỡng lọc Tất cả các thành phần sau ngưỡng lọc sẽ có biên độ được suy giảm về 0. Ta có Cepstrum tương ứng như sau: Hình 4.24: Cepstrum sau khi lọc Một nét đặc trưng chung cho phần lớn các tín hiệu rung mang ý nghĩa liên quan tới cuộn trôi qua là tồn tại một vài loại của nhóm các hàm điều hoà mà chúng không đồng bộ một cách trực tiếp với tốc độ thay đổi của dạng phổ. Nhóm này có thể là trong phần cuối tần số thấp của phổ, hay phần cuối cao hay cả hai. Nó cũng có thể bao gồm rất nhiều các âm mang ý nghĩa cơ bản và /hoặc các "sidebands" tỷ lệ luân chuyển. Trong bất cứ trường hợp nào, đều tồn tại một khoảng cách tần số chung nhằm tách riêng biệt các đỉnh của nhóm tín hiệu. Tính Cepstrum chính là sự chuyển đổi phổ ngược lại dạng tín hiệu trong miền thời gian, dạng mà có các đỉnh tương ứng với chu kỳ của các khoảng cách tần số chung trong phổ. Các đỉnh này có thể được sử dụng để tìm các đỉnh mang ý nghĩa trong phổ gốc. Hình 4.25: Phổ tương ứng với Cepstrum sau khi lọc Sử dụng Cepstrum trong việc đánh giá cường độ và các tần số đỉnh cộng hưởng. Nếu không có sự dao động tuần hoàn trong phổ thì trong Cepstrum tương ứng sẽ không có đỉnh xuất hiện. Do đó, với mọi âm thanh có chu kỳ cường độ ngắn nhất, đỉnh cường độ xuất hiện trong các vùng nơi mà các thành phần Cepstrum khác đã suy giảm đi đáng kể, nên khó phát hiện xung nhảy vọt. Vì vậy, tốt nhất nên sử dụng một ngưỡng thấp (có thể là 0.1) trong quá trình tìm kiếm đỉnh cường độ. Hình 4.25: Tín hiệu không tuần hoàn Hình 4.26: Phổ của tín hiệu không tuần hoàn Quan sát Cepstrum tương ứng ta thấy không có đỉnh nổi trội. Hình 4.27: Cepstrum tương ứng Tuy nhiên, với một độ dài cửa sổ thích hợp tại đầu vào, sự định vị và biên độ của đỉnh Cepstrum cung cấp một cường độ đáng tin cậy, và phần lớn các đánh giá theo thời gian. Trong những trường hợp mà Cepstrum không hiển thị rõ cường độ và âm, ta có thể cải thiện bằng cách thêm vào một số thông tin phụ như tỷ lệ bắt chéo không (zero-crossing rate) và năng lượng... Các đỉnh có ý nghĩa trong Cepstrum tương ứng với các tần số có khả năng mang ý nghĩa cơ bản. So sánh các tần số này với các đỉnh trong Cepstrum mà chúng không liên quan tới bất cứ tần số ép buộc cơ bản nào. Tuy nhiên, Cepstrum có thể được tách thành hai phần: phần dạng thời gian ngắn chứa tần số đỉnh cộng hưởng, xung thuộc thanh môn, và thông tin mang tính bức xạ; và thành phần dạng thời gian dài chứa thông tin về chu kỳ. Các đỉnh định vị tại chu kỳ cơ bản của tín hiệu và sự tăng bội của chu kỳ về sau đó với biên độ giảm. Nên, nếu tín hiệu được lấy mẫu một cách thích đáng, thì Cepstrum sẽ không có bất cứ sự giả mạo nào qua một vài chu kỳ đầu tiên này. Việc nhặt ra một hay một số đỉnh của một vài chu kỳ đầu tiên và đánh giá đánh giá chu kỳ cơ bản là một phương thức khác trong quá trình đánh giá tần số cơ bản của tín hiệu. 3. Một vài trợ giúp khác 3.1. Xác định tần số trội (tần số trung bình vùng biên độ đỉnh) Đây là giải thuật dùng để xác định tần số trội hơn trong dãy dữ liệu ra của phép tính FFT. Hàm trả về tần số theo Hz của phần phổ tần số có đỉnh cực đại. Những giá trị trở về có thể nằm trong khoảng các số nguyên của phép tính Fourier dựa trên tần số f0 = Tần số lấy mẫu/Số mẫu. Hình 4.28: Tần số vùng biên độ đỉnh Thực chất, phép toán tính giá trị trung bình của phần phổ trội hơn xung quanh tần số đỉnh. Điều này giúp ta hình dung được dáng phổ, và tăng độ chính xác khi xác định tần số đỉnh thực sự. Cơ sở của phép toán chính là việc xác định trọng tâm của một cửa sổ có khoảng cách cho trước, và cửa sổ này dịch chuyển tịnh tiến trên trục ngang (trên suốt trục tần số). Mô tả thuật toán Tính biên độ của các mẫu tương ứng. Suy giảm biên độ về 0 của các mẫu có tần số thấp hơn ngưỡng. Dịch chuyển cửa sổ trên các mẫu với độ rộng cửa sổ tuỳ chọn. Tính tổng biên độ của các mẫu trong cửa sổ tại vị trí đang xét. So sánh, xác định vị trí cửa sổ có tổng biên độ cực đại. Xác định vị trí mẫu xấp xỉ tương ứng với cửa sổ, từ đó tính tần số trung bình vùng biên độ đỉnh. 3.2. Tính phổ của mẫu cho trước Khi ta không cần xét tới toàn bộ phổ của tín hiệu, mà chỉ cần một vài mẫu tần số nào đó thì ta có thể sử dụng thủ tục tính toán các mẫu tần số theo các chỉ số đưa ra. Nếu n là số điểm tính FFT, thì chỉ số là các số trong khoảng 1.. n. Số phép tính của thuật toán này giảm xuống chỉ còn O(n) thay vì O(n*log(n)). Hơn nữa, cách tính này cũng rất hữu hiệu khi tính DFT cho một số không phải là bội của 2. Ta có thể tính DFT cho 100 điểm thay vì phải đệm thêm 28 điểm giá trị 0 để đạt được 128 điểm. Chương 9 Hướng dẫn sử dụng 1. Giao diện chương trình Chương trình sử dụng một màn hình giao diện chính để hiển thị các menu chức năng và biểu diễn tín hiệu trong các thao tác soạn thảo và phân tích tín hiệu. Hình 4.29: Màn hình giao diện chính Trong đó, gồm 2 màn hình: màn hình biểu diễn tín hiệu và màn hình soạn thảo. Các chức năng soạn thảo, thu phóng tín hiệu cũng như biểu diễn tín hiệu qua các phép tiền xử lý (lọc, hàm cửa sổ) được biểu diễn trên màn hình giao diện chính này. Sau đó, trong phép phân tích tín hiệu, phổ và cepstrum của tín hiệu được biểu diễn trên màn hình hiển thị FFT và Cepstrum tương ứng. 2. Tuỳ chọn chức năng Các chức năng của chương trình được thực hiện qua tuỳ chọn menu tương ứng. Sau đây là một số menu chính: Menu File Bao gồm các chức năng mở tệp âm thanh, ghi tạo tệp âm thanh mới, ghi ảnh tín hiệu... Hình 4.30: Menu File Hình 4.31: Menu Soạn thảo Menu Soạn thảo Gồm các chức năng soạn thảo: sao chép, cắt, dán, thu phóng, chọn mầu vẽ ... tạo ra các phân đoạn sóng mới để lưu tạo tệp âm mới. Menu Tuỳ chọn Gồm các chức năng xử lý tín hiệu: các phép lọc, giới hạn qua hàm cửa sổ, tính FFT hay Cepstrum... Tuỳ theo chức năng sẽ biểu diễn tín hiệu hay gọi màn hình hiển thị khác. Hình 4.32: Menu Tuỳ chọn Đánh giá chương trình 1. Đánh giá chương trình Do thời gian và khả năng có hạn, hơn nữa với khuôn khổ của một đồ án tốt nghiệp nên chương trình em thiết kế không thể xử lý hết được những vấn đề cần thiết trong lĩnh vực âm thanh rộng lớn. Tuy nhiên, chương trình đã giải quyết được những vấn đề cơ bản: tìm hiểu về các khuôn dạng lưu trữ dữ liệu âm thanh, các cách định dạng dữ liệu để từ đó có thể thao tác với dữ liệu giúp cho việc hiểu rõ cấu trúc các tệp âm thanh. Ngoài ra, chương trình còn có các modul nhằm trợ giúp cho quá trình phân tích tín hiệu âm thanh với khâu tiền xử lý (lọc, hàm cửa sổ) và phép xử lý homomorphic. Với việc tính FFT và Cepstrum, ta sẽ xác định được các đặc tính của âm thanh. Hơn nữa, chương trình mang tính chất hoàn chỉnh: bắt đầu quá trình thu thanh tạo tệp âm thanh từ micro, qua quá trình xử lý và phân tích dữ liệu âm, sau đó có thể phát âm thanh ra loa. Mặc dù vậy, chương trình cũng có các nhược điểm như mới chỉ đáp ứng các thao tác và các phép phân tích với dữ liệu trên các tệp Wave và tệp Voc. Nhưng đây là hai khuôn dạng lưu trữ âm thanh thông dụng nhất nên cũng cần hiểu rõ trước hết, và từ hai khuôn dạng cơ bản này giúp ta dễ dàng thao tác với các khuôn dạng khác. Và, một nhược điểm khác là tốc độ xử lý của chương trình còn chậm, nhất là khi thực hiện các chức năng soạn thảo với một số lớn các mẫu tín hiệu của một tệp âm thanh có kích thước lớn. Ngoài ra, quy trình thực hiện các chức năng của chương trình có thể chưa được hợp lý, các chức năng phụ thuộc nhiều vào nhau, nhưng mặc dù vậy chương trình có cấu trúc các thủ tục rõ ràng, dễ hiểu với ngôn ngữ lập trình Delphi. 2. Hướng phát triển Chương trình mang tính trợ giúp cho việc tìm hiểu về các đặc tính của âm thanh, các phép xử lý và phân tích tín hiệu số. Do đó, nếu có điều kiện ta có thể phát triển chương trình với các chức năng xử lý sâu hơn nữa. Đáp ứng với nhiều khuôn dạng tệp khác nhau với các phép lọc, trộn, và tổng hợp âm. Ngoài ra, trong chương trình có sử dụng FFT như là một phép biến đổi đặc trưng trong mọi quá trình phân tích, và giải thuật FFT có vẻ phù hợp với phép phân tích của các quá trình thu thanh âm số hoá hơn là so với các quá trình lọc hay tổng hợp các âm thanh. Ví dụ như khi ta muốn xây dựng một phần mềm tương ứng với thiết bị như bộ phân tích phổ để hiển thị đồ thị tần số của một tín hiệu điện. Trong đó, FFT thường được sử dụng trong việc xác định xem các tần số nào được hiển thị trong một tín hiệu tương tự. Bằng cách cung cấp một công cụ để nhận dạng các sóng âm đã định trước bởi các thành phần phổ của nó, FFTs có thể được sử dụng để so sánh các tín hiệu với một tín hiệu khác hay với một tập các mẫu hình. Ngoài ra, phép biến đổi này cũng được sử dụng trong lĩnh vực dò tìm tiếng nói và trong các bộ cảm biến về sự hỏng hóc của động cơ. FFTs cũng đã được sử dụng trong các hệ thống ảo ảnh nơi mà chúng nhận dạng các đối tượng qua việc so sánh các nét phác thảo của chúng, và trong các đơn vị radar để dò tìm sự dịch chuyển được tạo ra bởi các vật thể chuyển động. Ta cũng có thể sử dụng FFT để xác định tần số của nốt nhạc được phát trong một bản nhạc đã được thu thanh, để có thể xác định giữa các dạng khác nhau của âm thanh. Ngoài ra, FFT cũng rất hữu hiệu cho những vấn đề mà chúng không có liên quan gì tới âm thanh, như trong lĩnh vực xử lý ảnh (sử dụng phép tính FFT 2 chiều). FFT cũng có các ứng dụng trong lĩnh vực về khoa học/thống kê, như việc xác định các thay đổi mang tính tuần hoàn trong lĩnh vực cổ phiếu, sự phân bố về mật độ động vật, vv... Ngoài ra, FFTs cũng được sử dụng trong việc phân tích các thông tin về địa chấn (seismographic) để tạo "sonograms" bên trong trái đất. Thậm chí, các phương thức biến đổi Fourier còn được sử dụng cho việc phân tích các chuỗi DNA. 3. Kết luận Nói chung, để có thể hiểu rõ cũng như có thể xử lý một cách đầy đủ các vấn đề trong lĩnh vực âm thanh số thì cần phải có thời gian cũng như kiến thức sâu hơn nữa. Với nền khoa học kỹ thuật phát triển thì mọi vấn đề đều có thể được giải quyết. Do đó, bất cứ một trình xử lý nào cũng đều có thể được phát triển hơn nữa để có thể đáp ứng thêm các phép xử lý đa dạng và chính xác. Hơn nữa, các kỹ thuật xử lý không chỉ được áp dụng trong lĩnh vực âm thanh, mà còn được phát huy trong các lĩnh vực khác, các môi trường làm việc đa dạng. Chính vì vậy, trong khuôn khổ của một đồ án tốt nghiệp với đề tài "Xây dựng chương trình xử lý âm thanh số", em đã giải quyết được những vấn đề cơ bản mặc dù vẫn còn nhiều thiếu sót. Em rất mong nhận được những ý kiến đóng góp của các Thầy giáo, Cô giáo và tất cả bạn bè. Phụ lục A Giải thích thuật ngữ PAM (Pulse Amplitude Modulation) Khuôn dạng trung gian trong các quá trình chuyển đổi tín hiệu tương tự - số và ngược lại. Mỗi mẫu âm thanh được biểu diễn qua một xung với độ cao tương ứng độ mạnh của âm. PWM (Pulse Width Modulation) Mỗi mẫu âm thanh được biểu diễn qua một xung với độ rộng tương ứng độ mạnh của âm. PCM (Pulse Code Modulation) Mỗi mẫu âm thanh được thể hiện qua một chuỗi các xung biểu diễn mã nhị phân của nó. DPCM (Differential PCM), (Delta Modulation) Một dạng mã hoá khác của PCM với ưu điểm giảm kích thước lưu trữ bằng cách lưu trữ sự khác nhau giữa các mẫu thay vì bản thân các mẫu. Dạng này được sử dụng khi có tốc độ lấy mẫu cao dẫn đến sự khác nhau giữa các mẫu kế tiếp là nhỏ. FFT (Fast Fourier Transform) Phép biến đổi Fourier nhanh được dùng trong các phép phân tích phổ tín hiệu. Cepstrum Dạng viết đảo của từ Spectrum (phổ). Đây là phép phân tích phổ của một phổ biên độ đã có. Homomorphic Đây là một hệ thống xử lý với các khối biến đổi nghịch đảo của nhau qua một hệ thống tuyến tính, bất biến làm trung gian. Trong đó, Cepstrum là một phần lý thuyết cơ bản. Phụ lục B Tài liệu tham khảo 1. Xử lý tín hiệu số, NXBGD - 1997, Quách Tuấn Ngọc. 2. Xử lý tín hiệu số, NXBKH & KT - 1993, Hồ Anh Tuý. 3. Xử lý tín hiệu và lọc số, NXBKH & KT - 1998, Nguyễn Quốc Trung. 4. A Programmer's Guide To sound, Addison Wesley Developers Press - 1998, Tim Kientzle. 5. Digital Processing of Speech Signal, Prentice Hall - 1978, Rabiner L.R & R.W. Shaffer. 6. Traitement de la parole, Presses Polytechniques Romandes - 1987, René Boite et Murat Kunt. 7. A Digital Signal Processing Primer: With Applications to Digital Audio and Computer Music, Addison - Wesley - 1996, Ken Steiglitz. Mục lục

Các file đính kèm theo tài liệu này:

  • docXây dựng chương trình xử lý âm thanh số.doc