Đề tài Nén âm thanh file WAV theo chuẩn MPEG

L3_compress( ) : Đây là hàm quan trọng nhất trong chương trình, nó mô tả tồn bộ giải thuật của ứng dụng. Vòng lặp nén cũng nằm trong hàm này. Mỗi vòng lặp thực hiện công việc nén cho một frame d ữ liệu đọc từ file nguồn. Cũng từ vòng lặp này, ta cho thanh tiến trình hoạt động nhờ vào kích thước biết trước của file đọc vào. Vòng lặp kết thúc cũng là lúc thanh tiến trình được điền đầy và thông báo “Compress complete !” xuất hiện.

pdf79 trang | Chia sẻ: lylyngoc | Lượt xem: 2755 | Lượt tải: 2download
Bạn đang xem trước 20 trang tài liệu Đề tài Nén âm thanh file WAV theo chuẩn MPEG, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
. Các sub-band nên phù hợp với tai người., nghĩa là mỗi sub-band cần có các tần số có cùng các tính chất âm học tâm lý. Trong MPEG layerII, mỗi sub-band có độ rộng 625Hz, do đó cần phải có những bộ lọc băng thông phức tạp. Để các bộ lọc đỡ phức tạp, người ta thêm FFT (Fast Fourie Transform) vào song song với bộ lọc và sử dụng các thành phần phổ từ FFT như là các thông tin thêm vào bộ mã hóa. Bằng cách này ta sẽ lấy mật độ bit cao hơn đối với các tần số thấp mà tai người nhạy cảm hơn. Còn nhiều vấn đề cần phải bàn tới. Chúng ta chỉ mới giải thích sự che đồng bộ, hiệu qủa che còn xảy ra trước và sau một âm mạnh. 3. Các lớp của âm thanh MPEG. Có nhiều sự nhầm lẫn về lớp âm thanh MPEG. Tất cả các lớp đều dựa trên cùng một lược đồ mã hóa (mã hóa theo nhận thức). Mức độ phức tạp của bộ mã hóa và giảûi mã tuỳ thuộc vào mỗi lớp. Sau đây là hình ảnh cho thấy tỉ số nén mà ta cần phải đạt tới 100% chất lượng CD với các bộ mã hóa và giải mã khác nhau. Hình 4.8 Sau đây là chi tiết về các lớp. Khoa CNTT – ĐHBKHN GVHD thầy: Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 41 a. Lớp I (Layer I): Đây là lớp đơn giản nhất phù hợp cho ứng dụng của người dùng. Mô hình âm học tâm lý của lớp này chỉ sử dụng các tần số che. Điều này có nghĩa rằng nó sẽ bỏ qua các tần số bị khuất sau các tần số khác. Phạm vi tốc độ bit từ 32 kbit/s (mono) đến 448 kbit/s (stereo). Tùy thuộc vào mức độ phức tạp của bộ mã hóa, một âm thanh chất lượng cao (gần với âm thanh CD) yêu cầu tốc độ bit khoảng 256 - 384 kb/s trên một chương trình stereo. Không nên mã hóa với mức nén cao hơn 384 kb/s. Độ phức tạp của bộ giải mã thấp, độ phức tạp của bộ mã hóa cao hơn 1.5 - 3 lần. Lớp I được dùng nhiều trong DDC và Solid State Audio. b. Lớp II (Layer II): Lớp II đề nghị mức độ nén cao hơn lớp I và mức độ lọc sâu hơn. Nó có những ứng dụng số cho cả âm thanh chuyên nghiệp và tài tử, như qua đài phát thanh, TiVi...Phạm vi tốc độ bit từ 32 - 192 kb/s cho âm thanh mono, và từ 64 - 384 kb/s cho âm thanh stereo. Tùy thuộc vào mức độ phức tạp của bộ mã hóa, một âm thanh chất lượng cao (gần với âm thanh CD) yêu cầu tốc độ bit khoảng 256 - 384 kb/s trên một chương trình stereo. Mức độ phức tạp của bộ giải mã 25% cao hơn so với lớp I, và bộ mã hóa có mức phức tạp cao hơn 2 - 4 lần. c. Lớp III (Layer III). Lớp III còn đưa ra mức độ nén và lọc cao hơn cả lớp II và sử dụng một bộ mã hóa Huffman. Layer Complexity Encoder Decoder I 1.5 – 3 1 II 2 – 4 1.25 III > 7.5 2.5 Trong bảng trên, độ phức tạp của bộ giải mã lớp I được dùng để so sánh. III. CÁC THÔNG SỐ DÙNG TRONG MPEG. Chuẩn MPEG cho phép ta chọn lựa các thông số cho việc nén âm thanh tốt nhất phù hợp với ứng dụng mà ta sử dụng. Lược đồ mã hóa cho các loại là tổng quát. Các thông số có thể chọn lựa trong bộ mã hóa MPEG bao gồm: Mode, Sampling frequency, bitrate, và Layer. Khoa CNTT – ĐHBKHN GVHD thầy: Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 42 a. Mode. Chuẩn MPEG có 4 chế độ:  Mono.  Dual channel.  Stereo.  Intensity Stereo (còn gọi là Joint Stereo). Chế độ Mono rõ ràng được dùng cho âm thanh 1 kênh. Để chọn chế độ cho các ứng dụng 2 kênh, đầu tiên ta phải xác định đâu là tín hiệu trái và đâu là tín hiệu phải để chia chúng ra thành 2 files khác nhau, nhằm sau này ta có thể làm việc độc lập trên kênh trái hoặc phải. Lúc đó ta sẽ chọn chế độ Mono. Nếu 2 kênh không cần hoạt động độc lập, ta chọn Stereo, Dual hay Intensity Stereo để tạo một file duy nhất. Chế độ Stereo hay kênh Dual là hồn tồn đồng nhất khi chúng cùng sinh ra một file duy nhất cho tín hiệu stereo. Tuy nhiên một bit chỉ thị sẽ nhận dạng xem một file là ở chế độ nào và có thể được dùng cho những áp dụng nào... Chế độ Intensity Stereo xem xét sự dư thừa giữa các kênh trái và phải nhằm tối ưu mã. Chất lượng chủ quan của Intensity Stereo thay đổi theo hình ảnh stereo của tín hiệu đã mã hóa. Tuy nhiên nó đặc biệt thích hợp cho tốc độ truyền bit thấp. b. Sampling Frequency (tốc độ lấy mẫu). Một số tốc độ lấy mẫu: 32kHz, 44.1kHzvà 48kHz đối với MPEG1 (Tiêu chuẩn ISO/IEC 11172-3). 16kHz, 22.05kHzvà24kHz đối với MPEG2 (Tiêu chuẩn ISO/IEC13818-3). Khi chọn lựa tốc độ lấy mẫu cần xem xét các vấn đề:  Tần số lấy mẫu càng lớn thì chất lượng âm thanh càng cao(độ dài frame nhỏ hơn).  Băng thông tín hiệu giới hạn ở mức 15 kHz khi lấy mẫu ở tốc độ 32 kHz và 8 kHz ở tốc độ 16 kHz. Khoa CNTT – ĐHBKHN GVHD thầy: Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 43  Tần số lấy mẫu (kHz) và tốc độ của âm thanh mã hóa (kbps) có thể chọn độc lập.  Tần số lấy mẫu 44.1 kHz hay 22.05 kHz là không thiết thực cho việc chọn lọc vì độ dài frame (byte) là thay đổi.  Những file được lấy mẫu ở những tần số khác nhau thì rất khó khăn khi hòa trộn.  Khi dùng đường nhập số AES/EBU, tần số lấy mẫu bị cố định bởi tín hiệu nhập. Nếu không bắt buộc, Digigram yêu cầu lấy mẫu ở 48 kHz hoặc 44.1 kHz cho phát thanh hay ứng dụng multimedia. Nếu ta phải sử dụng tốc độ bit thấp cho sự truyền có hiệu qủa, tốc độ 24 kHz là thích hợp. c. Bit Rate. Mỗi Layer và chế độ có nhiều cách chọn lựa tốc độ bit (bit rate). Việc chọn tốc độ bit tùy thuộc trước tiên vào chất lượng âm yêu cầu. Băng thông tín hiệu là hẹp hơn nếu tốc độ bit thấp, khiến cho nó không thực tế đối với một số ứng dụng. Tốc độ bit được đo theo kilobits/sec(kbps). Khi chọn lựa tốc độ bit cần xem xét các vấn đề:  Tại 128 kbps trên mỗi kênh (hay 256 kbps stereo), chất lượng âm thanh CD sẽ đạt được với Layer I hay Layer II.  Tại 192 kbps trên mỗi kênh, chất lượng âm thanh là hồn tồn trong suốt. Tốc độ 128 kbps/kênh được dùng phổ biến nhất trong phát thanh. Nó tương ứng với tỉ số nén 1:6 ở tốc độ lấy mẫu 48 kHz. Tốc độ thấp hơn 128 kbps/kênh được dùng trong các ứng dụng yêu cầu tỉ số nén lớn hơn do giới hạn của băng thông truyền hay thiết bị lưu trữ. Một số tốc độ bit cung cấp bởi chuẩn âm thanh MPEG :  MPEG 1: 32 kHz, 44.1 kHz và 48 kHz - Layer I : 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 kbps. Những tốc độ này là có thể ở chế độ Mono hay stereo.. - Layer II : Khoa CNTT – ĐHBKHN GVHD thầy: Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 44 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 kbps. 32, 48, 56, 80 kbps chỉ có thể ở chế độ Mono; •64, 96, 112, 128, 160, 192 kbps có thể ở cả hai chế độ Mono và Stereo;•224, 256, 320, 384 kbps chỉ có thể ở chế độ Stereo.  MPEG 2 : 16 kHz, 22.05 kHz và 24 kHz - Layer I : 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 kbps Những tốc độ này là có thể ở chế độ Mono hay stereo.. - Layer II : 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 kbps. Những tốc độ này là có thể ở chế độ Mono hay stereo. d. Layers. Chuẩn MPEG có ba layer. Khi chọn lựa tốc độ bit cần xem xét các vấn đề:  Ở cùng tốc độ bit, Layer II mang lại chất lượng âm thanh tốt hơn Layer I. Kết luận này là chủ quan, vì sự chênh lệch là rất khó phân biệt ở tốc độ bit 128 kbps và lớn hơn.  Dùng Layer I thì việc chọn lọc chính xác hơn Layer II bởi vì độ phân giải của Layer I gấp ba lần Layer II. Resolution Table Sampling frequency Layer I (384 samples) Layer II (1152 samples) 32 kHz 12 ms 36 ms 44.1 kHz # 8.71 ms # 26.12 ms 48 kHz 8 ms 24 ms 16 kHz 24 ms 72 ms 22.05 kHz # 17.42 ms # 52.24 ms Khoa CNTT – ĐHBKHN GVHD thầy: Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 45 24 kHz 16 ms 48 ms Các điểm kỹ thuật mấu chốt. Chuẩn mã hóa âm thanh MPEG chỉ định việc ghi một số cố định các mẫu (384 cho Layer I và 1152 cho Layer II) để tạo ra một chuỗi các bytes gọi là “frame”. “Frame” là thực thể nhỏ nhất được điều khiển bởi một ứng dụng. Việc chọn tốc độ bit(kbps) thiết lập nên kích thước của frame đó theo byte. Ví dụ: Ở 48 kHz, 128 kbps, chế độ Mono, Layer II:  48,000 mẫu, tương ứng 1000 ms hay 1s, 1152 mẫu tương ứng 24 ms.  Ở tốc độ bit 128,000 bits/s, 3072 bits (384 bytes) cần cho 24 ms.  Chiều dài frame vì thế là 384 byte.  Để lưu 1 phút, cần 960,000 byte (hay khoảng 1 Megabyte) đĩa trống. Khoa CNTT – ĐHBKHN GVHD thầy: Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 46 CHƯƠNG 5. CÁC GIẢI THUẬT NÉN ÂM THANH. I. NỀN TẢNG LÝ THUYẾT THÔNG TIN. Theo Shannon, entropy của một nguồn thông tin S được định nghĩa: H(S) =  = ipilog2(1/pi) Trong đó: - pi là xác suất mà ký hiệu Si xuất hiện trong S. - log2(1/pi) chỉ ra số lượng thông tin chứa đựng trong Si, nghĩa là số bit cần thiết để mã hóa Si.  Ví dụ: một hình ảnh được tô đều với cùng một cường độ màu xám, tức là pi=1/256, thì số bit cần thiết để mã hóa cho mỗi mức xám là 8 bits. Entropy của hình này là 8. Giải thuật Shannon - Fano: Ta dùng một ví dụ đơn giản để mô tả giải thuật: Ký hiệu A B C D E --------------------------------------------------- Số lần 15 7 6 6 5 Mã hóa cho giải thuật Shannon - Fano: Dùng cách tiếp cận từ trên xuống.  Sắp thứ tự các ký hiệu theo tần số xuất hiện của nó, nghĩa là: ABCDE.  Chia thành hai phần, mỗi phần tương đương với cùng số lần đếm. Hình 5.1 Ký hiệu Số lần log(1/p) Mã Cộng(số bit) Khoa CNTT – ĐHBKHN GVHD thầy: Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 47 ---------- -------- ---------- ----- --------------- A 15 1.38 00 30 B 7 2.48 01 14 C 6 2.70 10 12 D 6 2.70 110 18 E 5 2.96 111 15 Tổng cộng(số bit) : 89 II. CÁC GIẢI THUẬT NÉN KHÔNG CÓ TỔN THẤT. 1. Mã hóa Huffman.  Khởi tạo: đưa tất cả các node vào danh sách OPEN theo thứ tự tại mọi thời điểm. Ví dụ: ABCDE.  Lặp lại cho đến khi danh sách OPEN chỉ còn một node bên trái như sau: - Từ danh sách OPEN, chọn hai node có xác suất thấp nhất, tạo node cha cho chúng. - Gán tổng các xác suất cho node cha và đưa node cha vào danh sách OPEN. - Gán các mã 0, 1 vào các nhánh của cây, xóa các node con khỏi danh sách OPEN. Hình 5.2 Ký hiệu Số lần log(1/p) Mã Cộng(số bit) Khoa CNTT – ĐHBKHN GVHD thầy: Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 48 ---------- --------- ---------- ----- --------------- A 15 1.38 0 30 B 7 2.48 100 14 C 6 2.70 101 12 D 6 2.70 110 18 E 5 2.96 111 15 Tổng cộng (số bit) : 87  Việc giải mã cho cả hai giải thuật trên là tầm thường chừng nào mà bảng mã (thống kê) được gửi trước dữ liệu. Có một bit bên trên công việc truyền này, nhưng không đáng kể nếu file dữ liệu lớn.  Tính chất tiền tố duy nhất: không có mã nào là tiền tố cho một mã khác (tất cả các ký hiệu đều là node lá)  rõ ràng là lớn đối với bộ giải mã.  Nếu việc thống kê có thể tiến hành được trước đó và với độ chính xác cao, thì mã Huffman là rất tốt. Trong ví dụ trên:Entropy=(15x1.38+7x2.48+ 6x2.7 + 6x2.7 + 5x2.96)/39 = 85.26 / 39 = 2.19. Số bit cần thiết cho mã hóa Huffman là : 87 / 39 = 2.23 2. Mã Huffman sửa đổi. (a) Các giải thuật trên đây yêu cầu kiến thức về thống kê là điều mà khó có thể thực hiện (ví dụ âm thanh, hình ảnh sống..). (b) Ngay cả khi nếu điều đó là có thể làm được thì chi phí cho nó khá nặng, đặc biệt khi có nhiều bảng phải được truyền mà mô hình non-order() được sử dụng, nghĩa là việc đưa vào tính tốn sự ảnh hưởng của các ký hiệu trước đó với xác suất của ký hiệu hiện hành (ví dụ: “qu” thường đi với nhau,..). Giải pháp đưa ra là dùng giải thuật sửa đổi cho thích hợp. Như ví dụ, việc mã hóa Huffman sửa đổi được khảo sát sau đây với ý tưởng là làm thế nào có thể áp dụng vào các giải thuật nén thích hợp khác. Bộ mã hóa Initialize_model(); while ((c = getc (input)) != eof) { encode(c, output); Bộ giải mã Initialize_model(); while ((c = decode (input)) != eof) { putc(c, output); Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 49  Mấu chốt ở đây là cả hai bộ mã hóa và giải mã đều dùng cùng các hàm Initialize_model và update_model .  Hàm update_model có hai lưu ý: (a) Tăng biến đếm. (b) Cập nhật cây Huffman. - Trong suốt qúa trình cập nhật, cây Huffman sẽ được duy trì tính kế thừa, các nodes (node trong và lá) được sắp xếp theo thứ tự tăng dần của trọng lượng . - Khi cần thiết trao đổi (swapping), node xa nhất với trọng lượng W được trao đổi với node mà trọng lượng của nó tăng lên 1 đơn vị W+1. Lưu ý: nếu node trọng lượng W có cây con bên dưới nó thì cây con đó cũng phải dời cùng với nó. Cây Huffman có thể nhìn rất khác so với trước khi trao đổi, ví dụ trong cây thứ 3 , node A được trao đổi và trở thành node 5. Bây giờ nó được mã hóa chi bằng 2 bit. 3. Mã hóa số học. Mã hóa Huffman sử dụng một số nguyên k các bit cho mỗi ký hiệu, vì thế k không bao giờ nhỏ hơn 1. Đôi khi, ví dụ phải truyền một hình ảnh 1 bit, thì không thể nén được. Ý tưởng: giả sử mẫu tự là [X,Y] và P(X) = 2/3 P(Y) = 1/3.  Nếu ta chỉ quan tâm với chiều dài mã hóa là 2 thông điệp, thì ta có thể ánh xạ tất cả thông điệp có thể có vào những đoạn trong phạm vi [0..1] X Y XX XY YX YY  Để mã hóa thông điệp, chỉ dùng vừa đủ số bit cần thiết cho mỗi đoạn.  Tương tự, ta có thể ánh xạ tất cả chiều dài 3 thông điệp vào các đoạn trong [0..1].  Nói chung, số bit được xác định bằng kích thước của đoạn. Ví dụ: Đoạn đầu tiên là 8/27, cần 2 bit 2/3 bit cho mỗi ký tự. Đoạn cuối là 1/27, cần 5 bit. Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 50  Tóm lại, cần -[logp] bit để biểu diễn cho đoạn có kích thước p.  Vấn đề đặt ra là làm thế nào để xác định được xác suất? Ý tưởng đơn giản là dùng mô phỏng: bắt đầu bằng việc đốn tần số của một ký hiệu. Cập nhật tần số cho mỗi ký hiệu mới. 4. Giải thuật Lempel-Ziv-Welch(LZW). Giả sử chúng ta muốn mã hóa cho một cuốn tự điển Tiếng Anh 159,000 từ. Như vậy mỗi từ cần 18 bit để mã hóa. Nhược: - Dùng qúa nhiều bit. - Chỉ làm việc cho ký tự tiếng Anh. Giải pháp: - Cần phải tìm một cách mã hóa cuốn từ điển cho thích hợp. - Các phương pháp ban đầu được đề xuất bởi Ziv và Lempel vào năm 1978 và 1979. Terry Welch phát triển lược đồ vào năm 1981 và trở thành giải thuật LZW. Giải thuật: w = NIL; while (read a character k) { if wk exists in the dictionary w = wk; else add wk to the dictionary; output the code for w; w = k; } LZW nguyên gốc sử dụng từ điển với 4K mục từ, 256 từ đầu tiên là mã ASCII. Ví dụ: chuỗi ký tự là “^WED^WE^WEE^WEB^WET”. w k output index symbol ------------------------------------------------------------------ NIL ^ ^ W ^ 256 ^W W E W 257 WE E D E 258 ED Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 51 D ^ D 259 D^ ^ W ^W E 256 260 ^WE E ^ E 261 E^ ^ W ^W E ^WE E 260 262 ^WEE E ^ E^ W 261 263 E^W W E WE B 257 264 WEB B ^ B 265 B^ ^ W ^W E ^WE T 260 266 ^WET T EOF T 19 ký hiệu nhập được giảm xuống 7 ký tự và 5 mã. Mỗi mã/ký hiệu sẽ cần nhiều hơn 8 bit, ta lấy 9 bit. Thông thường, công việc nén chỉ được bắt đầu khi có một số lớn byte được đọc vào (ví dụ >100). Giải thuật giải nén LZW: read a character k; output k; w = k; while ( read a character k ) /* k could be a character or a code. */ { entry = dictionary entry for k; output entry; add w + entry[0] to dictionary; w = entry; } III. CÁC GIẢI THUẬT NÉN CÓ TỔN THẤT. 1. Các phương pháp nén âm thanh đơn giản:  Các phương pháp nén khảo sát ở trên không hiệu quả trong việc nén âm thanh.  Sau đây là các phương pháp nén có tổn thất: - Nén “silence” : dò các khoảng “yên lặng”, giống như mã hố run-length. - LPC (Linear Predictive Coding). - CELP (Code Excited Linear Predictor). 2. Nén âm thanh dùng mô hình ââm - tâm lý. Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 52 a. Hệ thống nghe và phát âm của con người.  Phạm vi nghe được từ 20 Hz đến 20 kHz, nhạy cảm ở 2 - 5kHz.  Phạm vi phát âm bình thường từ 500 Hz đến 2 kHz. b. Che tần số (Frequency masking) “Ngưỡng che” (Threshold masking): sinh ra từ hiệu ứng che, mỗi âm với một tần số và mức to (dB) xác định sẽ có một “ngưỡng che” (xem hình 4.3 và 4.4) c. Băng giới hạn.  Thước đo tần số đồng bộ không tương xứng với độ rộng của đường cong che.  Băng giới hạn có độ rộng là 100Hz đối với các tần số che < 500Hz, và càng tăng lên đối với các tần số >500Hz.  Định nghĩa một đơn vị mới cho tần số là bark ( Barkhausen) 1 Bark = bề rộng của băng giới hạn: - Tần số <500Hz : 1 bark = freq/100. - Tần số >500Hz : 1 bark = 9 + 4log(freq/1000).  Ngưỡng che trên thước đo băng giới hạn: Hình 5.3 d. Che nhất thời (Temporal masking): che theo thời gian. Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 53 Tai người cũng có đặc tính lưu âm. Nếu có một âm thanh lớn, rồi ngưng nó lại, mãi một lúc sau ta mới có thể nghe được một âm lân cận nhỏ hơn (xem hình 4.5 và 4.6). 3. Nén âm thanh MPEG. Vài thông số:  MPEG-1 : 1.5Mbits/s cho âm thanh và hình ảnh. Khoảng 1.2 Mbits cho hình ảnh và 0.3Mbits/s cho âm thanh. Aâm thanh CD không nén dùng: (44,100 mẫu/s * 16bit/mẫu * 2 kênh) > 1.4 Mbits/s  Aâm thanh MPEG cung cấp các tần số lấy mẫu là 32, 44.1 và 48 kHz.  Giải thuật: 1. Dùng bộ lọc thông để chia tín hiệu âm thanh thành các sub-band theo tần số, tương ứng với 32 băng giới hạn  lọc sub-band. 2. Xác định số lượng che của mỗi band gây bởi các band lân cận bằng các kết qủa bước 1  mô hình âm - tâm lý. 3. Nếu mức to của một băng mà nhỏ hơn ngưỡng che thì không mã hóa nó. 4. Ngược lại, xác định số bit cần thiết để mã hóa sao cho nhiễu sinh ra bởi việc lượng tử hóa này thấp hơn đường cong che. 5. Định dạng dòng dữ liệu bit : Hình 5.4 Ví dụ: Sau khi phân tích, 16 band đầu tiên trong số 32 band như sau: _________________________________________________________ Band 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Level(dB) 0 8 12 10 6 2 10 60 35 20 15 2 3 5 3 1 Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 54 _________________________________________________________  Nếu mức to của âm thứ 8 là 60dB, nó sẽ che band thứ 7 ở mức 12dB và band thứ 9 ở mức 15dB. Mức to ở band 7 là 10dB (<12dB) nên bị bỏ qua, không mã hóa. Mức to band 9 là 35 (> 15dB) nên được tiếp tục xử lý.  Layer I: bộ lọc loại DCT với 1 frame và độ rộng tần số như nhau trên mỗi sub-band. Mô hình âm-tâm lý chỉ sử dụng hiệu quả che tần số (Frequency masking).  Layer II: sử dụng 3 frame trong bộ lọc (trước, hiện tại và kế tiếp, tổng cộng 1152 mẫu). Mô hình âm-tâm lý có sử dụng hiệu quả che nhất thời (Temporal masking).  Layer III: dùng bộ lọc băng giới hạn tốt hơn, mô hình âm-tâm lý có sử dụng hiệu quả che nhất thời, và có dùng bộ mã hố Huffman. Phần II THIẾT KẾ CHƯƠNG TRÌNH Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 55 CHƯƠNG 6. LƯU ĐỒ GIẢI THUẬT VÀ CẤU TRÚC DỮ LIỆU. I. SƠ ĐỒ KHỐI. Thay đổi hay giữ nguyên cấu hình Cấu hình mặc định Set_default() Đặt input và output file; Mở input file và kiểm tra; Wave_open(); Open_bit_stream_w(); Memset(); Dùng mô hình âm-tâm lý để phân tích dữ liệu L3_psycho_analise(); Chuẩn bị Frame dữ liệu L3_psycho_initialise(); L3_subband_initialise(); L3_mdct_initialise(); L3_loop_initialise(); Dùng bộ lọc nhiều pha để xử lý dữ liệu L3_window_subband(); L3_filter_subband(); Tính MDCT cho các đường ra nhiều pha L3_mdct_sub(); Xác định số bit để mã hoá một Làm sạch buffer L3_FlushBitstream(); Đóng thiết bị ghi Close_bit_stream_w(); Đóng file nguồn Wave_close(); Kết thúc Chuẩn bị vùng đệm Khởi tạo mô hình âm-tâm lý Tính các hệ số của bộ lọc tần số Khởi tạo dữ liệu tính MDCT Khởi tạo mảng pow43[I].0<I<1024 Start compress () Đ S wave_get(buffer)0 Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 56 II. CẤU TRÚC DỮ LIỆU VÀ ĐỊNH NGHĨA. A. Cấu trúc dữ liệu. 1. Các cấu trúc về file: - Tập tin tiêu đề : - Sử dụng : truy xuất các tập tin dạng *.wav và *.mp3. Trong chương trình, các cấu trúc này sử dụng ở các giai đoạn mở file, đọc cấu hình file, truy xuất các thông tin về cấu hình file. a. Cấu trúc FILE WAVE : typedef struct { FILE *file; int type; int channels; int bits; long samplerate; long total_samples; long length; } wave_t; b. Cấu trúc FILE MPEG: typedef struct { FILE *file; int type; int layr; int mode; int bitr; int psyc; int emph; int padding; long samples_per_frame; long bits_per_frame; long bits_per_slot; long total_frames; int bitrate_index; Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 57 int samplerate_index; int crc; int ext; int mode_ext; int copyright; int original; int mode_gr; } mpeg_t; c. Cấu trúc config_t : typedef struct { time_t start_time; char* infile; wave_t wave; char* outfile; mpeg_t mpeg; } config_t; 2. Cấu trúc dòng bit dữ liệu: bitstream_t - Tập tin tiêu đề : - Sử dụng: dùng trong quá trình đọc hoặc ghi dữ liệu từ file lên vùng đệm và ngược lại. typedef struct bit_stream_struc { FILE *pt; /* con trỏ đến file bit dữ liệu */ unsigned char *buf; /* vùng đệm cho dòng bit dữ liệu */ int buf_size; /* kích thước vùng đệm tính theo số byte */ long totbit; /* đếm bit */ int buf_byte_idx; /* chỉ byte trên cùng trong vùng đệm */ int buf_bit_idx; /* bit trên cùng của byte trên cùng trong vùng đệm */ int mode; /* mở dòng bit ở chế độ đọc hay ghi */ int eob; /* chỉ đến cuối vùng đệm */ int eobs; /* đầu cuối của cờ dòng bit */ char format; /* định dạng file ở chế độ đọc (BINARY/ASCII) */ } bitstream_t; 3. Các cấu trúc để định dạng dòng bit dữ liệu: - Tập tin tiêu đề : a. Kiểu số nguyên: typedef unsigned int uint32; /* định nghĩa số nguyên không dấu 32 bit */ typedef unsigned short uint16; /* định nghĩa số nguyên không dấu 16 bit */ b. Con trỏ hàm (*BitsFcnPtr): Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 58 Đây là một nguyên mẫu hàm con trỏ cần phải có để ghi các bit vào dòng dữ liệu. Nó ghi “length” bits từ “value” bits, theo cách ghi msb-first. Các bit trong value giả định là right-justified. typedef void (*BitsFcnPtr)( uint32 value, uint16 length ); c. Cấu trúc BF_BitstreamElement: Một BitstreamElement chứa đựng dữ liệu đã mã hố sẽ được ghi vào dòng bit. “length” bit trong số “value” sẽ được ghi vào dòng bit theo msb-first. typedef struct { uint32 value; uint16 length; } BF_BitstreamElement; d. Cấu trúc BF_BitstreamPart: Một BitstreamPart bao gồm một nhóm các “nrEntries” của BitstreamElements. Mỗi BitstreamElement sẽ được ghi vào dòng bit theo thứ tự mà nó xuất hiện trong dãy 'element'. typedef struct { uint32 nrEntries; BF_BitstreamElement *element; } BF_BitstreamPart; e. Cấu trúc BF_FrameData Cấu trúc này chứa đựng tất cả những thông tin cần thiết cho bộ định dạng dòng bit để mã hố một frame dữ liệu. Ta phải điền đầy nó và trỏ tới khi định dạng. typedef struct BF_FrameData { BitsFcnPtr putbits; /* your low-level bitstream function */ int frameLength; int nGranules; int nChannels; BF_BitstreamPart *header; BF_BitstreamPart *frameSI; BF_BitstreamPart *channelSI[MAX_CHANNELS]; BF_BitstreamPart *spectrumSI[MAX_GRANULES][MAX_CHANNELS]; BF_BitstreamPart *scaleFactors[MAX_GRANULES][MAX_CHANNELS]; BF_BitstreamPart *codedData[MAX_GRANULES][MAX_CHANNELS]; BF_BitstreamPart *userSpectrum[MAX_GRANULES][MAX_CHANNELS]; BF_BitstreamPart *userFrameData; Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 59 } BF_FrameData; f. Các cấu trúc liên quan dến bộ định dạng: Cấu trúc này chứa đựng thông tin được cung cấp bởi bộ định dạng dòng bit. Ta có thể sử dụng nó để kiểm tra và xem thử bộ mã của ta có chấp nhận các kết quả của việc gọi bộ định dạng hay không. typedef struct BF_FrameResults { int SILength; int mainDataLength; int nextBackPtr; } BF_FrameResults; typedef struct BF_PartHolder { int max_elements; BF_BitstreamPart *part; } BF_PartHolder; typedef struct { int frameLength; int SILength; int nGranules; int nChannels; BF_PartHolder *headerPH; BF_PartHolder *frameSIPH; BF_PartHolder *channelSIPH[MAX_CHANNELS]; BF_PartHolder *spectrumSIPH[MAX_GRANULES][MAX_CHANNELS]; } MYSideInfo; 4. Cấu trúc huffcodetab: - Tập tin tiêu đề : - Sử dụng : dùng trong quá trình mã hố dữ liệu theo thuật tốn Huffman. struct huffcodetab { unsigned int xlen; /*max. x-index+ */ unsigned int ylen; /*max. y-index+ */ unsigned int linbits; /*number of linbits */ unsigned int linmax; /*max number to be stored in linbits */ HUFFBITS *table; /*pointer to array[xlen][ylen] */ unsigned char *hlen; /*pointer to array[xlen][ylen] */ }; 5. Các cấu trúc tính MDCT. Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 60 - Tập tin tiêu đề : - Sử dụng : trong tính tốn MDCT, định dạng dòng bit, tính tốn mô hình tâm lý, mã hố dữ liệu.. typedef struct { unsigned part2_3_length; unsigned big_values; unsigned count1; unsigned global_gain; unsigned scalefac_compress; unsigned window_switching_flag; unsigned block_type; unsigned mixed_block_flag; unsigned table_select[3]; int /* unsigned */ subblock_gain[3]; unsigned region0_count; unsigned region1_count; unsigned preflag; unsigned scalefac_scale; unsigned count1table_select; unsigned part2_length; unsigned sfb_lmax; unsigned sfb_smax; unsigned address1; unsigned address2; unsigned address3; double quantizerStepSize; /* added for LSF */ unsigned *sfb_partition_table; unsigned slen[4]; } gr_info; typedef struct { int main_data_begin; /* unsigned -> int */ unsigned private_bits; int resvDrain; unsigned scfsi[2][4]; struct { struct { gr_info tt; } ch[2]; } gr[2]; } L3_side_info_t; typedef struct { double l[2][2][21]; double s[2][2][12][3]; } L3_psy_ratio_t; typedef struct { Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 61 double l[2][2][21]; double s[2][2][12][3]; } L3_psy_xmin_t; typedef struct { int l[2][2][22]; /* [cb] */ int s[2][2][13][3]; /* [window][cb] */ } L3_scalefac_t; 6. Cấu trúc scalefac_struct: - Tập tin tiêu đề : struct scalefac_struct { int l[23]; int s[14]; }; B. Các định nghĩa. 1. Các định nghĩa dùng trong truy xuất dòng bit dữ liệu: - Tập tin tiêu đề : #define MINIMUM 4 /* Minimum size of the buffer in bytes */ #define MAX_LENGTH 32 /* Maximum length of word written or read from bit stream */ #define READ_MODE 0 #define WRITE_MODE 1 #define ALIGNING 8 #define BINARY 0 #define ASCII 1 #define TRUE 1 #define FALSE 0 #ifndef BS_FORMAT #define BS_FORMAT ASCII /* BINARY or ASCII = 2x bytes */ #endif #define BUFFER_SIZE 4096 #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MAX(A, B) ((A) > (B) ? (A) : (B)) 2. Các định nghĩa dùng trong tính tốn FFT: - Tập tin tiêu đề : #define BLKSIZE_S 256 Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 62 #define LOGBLKSIZE_S 8 3. Các định nghĩa dùng trong định dạng dòng dữ liệu: - Tập tin tiêu đề: #define MAX_CHANNELS 2 #define MAX_GRANULES 2 4. Các định nghĩa dùng trong bộ mã hố Huffman: - Tập tin tiêu đề: #define HUFFBITS unsigned long int #define HTN 34 #define MXOFF 250 5. Các định nghĩa dùng trong phân tích dữ liệu : - Tập tin tiêu đề: #define e 2.71828182845 #define CBLIMIT 21 #define SFB_LMAX 22 #define SFB_SMAX 13 #define PRECALC_SIZE 1024 /* WAS 256 !!! */ 6. Các định nghĩa dùng trong mô hình âm tâm lý: - Tập tin tiêu đề: #define HBLKSIZE 513 #define CBANDS 63 #define CBANDS_s 42 #define BLKSIZE_s 256 #define HBLKSIZE_s 129 #define TCBMAX_l 63 #define TCBMAX_s 42 #define SBMAX_l 21 #define SBMAX_s 12 /* #define switch_pe 1800 */ #define NORM_TYPE 0 #define START_TYPE 1 #define SHORT_TYPE 2 #define STOP_TYPE 3 #define maximum(x,y) ( (x>y) ? x : y ) #define minimum(x,y) ( (x<y) ? x : y ) 7. Các định nghĩa dùng trong truy xuất dữ liệu nhâp: - Tập tin tiêu đề: #define Read32BitsLowHigh(f) Read32Bits(f) Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 63 #define WriteString(f,s) fwrite(s,strlen(s),sizeof(char),f) #define Read32BitsLowHigh(f) Read32Bits(f) 8. Các định nghĩa dùng trong cấu trúc file wave và file mpeg: #define PI 3.14159265358979 #define PI4 PI/4 #define PI64 PI/64 #define SQRT2 1.41421356237 #define LOGBLKSIZE 10 #define LN_TO_LOG10 0.2302585093 #define BLKSIZE 1024 #define HAN_SIZE 512 #define SCALE_BLOCK 12 #define SCALE_RANGE 64 #define SCALE 32768 #define SBLIMIT 32 #define WAVE_RIFF_PCM 0 #define WAVE_PCM_LOHI 1 #define WAVE_PCM_HILO 2 #define WAVE_PCM_AIFF 3 #define TYPE_MPEG_I 1 #define LAYR_III 2 #define MODE_STEREO 0 #define MODE_JSTEREO 1 #define MODE_DUAL 2 #define MODE_MONO 3 #define PSY_NONE 0 #define PSYC_MUSICAM 1 #define PSYC_ATT 2 Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 64 III. LƯU ĐỒ Thay đổi hay giữ nguyên cấu hình Cấu hình mặc định Set_default() Đặt input và output file; Mở input file và kiểm tra; Wave_open(); Open_bit_stream_w(); Memset(); Config.mpeg.mode_gr=2; Config.mpeg.sample_per_frame=1152; ___________________________________ Chuẩn bị Frame dữ liệu L3_psycho_initialise(); L3_subband_initialise(); L3_mdct_initialise(); L3_loop_initialise(); Config.wave.bits_per_slot =8; Frames_processed =0; Sideinfo_len =32; Chuẩn bị vùng đệm Khởi tạo mô hình âm-tâm lý Tính các hệ số của bộ lọc tần số Khởi tạo dữ liệu tính MDCT Khởi tạo mảng pow43[I].0<I<1024 StartL3-Compress () Mở thiết bị ghi Config.mpeg.total_frames=(config.wave.total _samples /config.mpeg.samples_per_frame); config,wave.channels=1 S Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 65 avg_slots_per_frame = ((double)config.mpeg.samples_per_frame / ((double)config.wave.samplerate / 1000))* ((double)config.mpeg.bitr / (double)config.mpeg.bits_per_slot) ; whole_slots_per_frame = (int) avg_slots_per_frame ; frac_slots_per_frame = avg_slots_per_frame - (double) whole_slots_per_frame ; slot_lag = - frac_slots_per_frame ; config.mpeg.padding = 0 Update_stastus(frames_processed ++); L3_FlushBitstream( ); close_bit_stream_w( ); wave_close( ) ; Kết thúc buffer_windows[0] = buffer[0]; buffer_windows[1] = buffer[1]; slot_lag -= frac_slots_per_frame; config.mpeg.padding = 0 ; slot_lag -= frac_slots_per_frame; config.mpeg.padding = 0 ; config.mpeg.bits_per_frame = 8*(whole_slot_per_frame + config.mpeg.padding); mean_bit = (config.mpeg.bits_per_frame - sideinfo_len)/ config.mpeg.mode_gr ; 1 4 frac_slots_per_frame = 0 wave_get(buffer) 0 frac_slots_per_frame 0 slot_lag > (frac_slots_per_frame - 1) Đ S Đ S Đ S Đ S Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 66 L3_mdct_sub( ); L3_iteration_loop( ); L3_format_bitstream( ); frame_bits = sstell(&bs) - sent_bits 3 gr = 0 ; channel = 0 ; L3_psycho_analise( ) ; channel ++ ; gr ++ ; gr = 0 ; channel = 0 ; i = 0 ; L3_window_subband( ); L3_filter_subband( ); i ++ ; i < 18 channel ++ ; gr ++ ; 3 2 Đ Đ Đ Đ Đ S S S S channel < config.wave.channels gr < config.mpeg.mod_gr channel < config.wave.channels gr < config.mpeg.mod_gr S Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 67 CHƯƠNG 7. GIAO DIỆN VÀ THUYẾT MINH CHƯƠNG TRÌNH I. Giới thiệu. Giao diện là công cụ trợ giúp đắc lực cho người sử dụng. Những phần mềm có giao diện tốt luôn được ưa chuộng. Đó cũng chính là ưu điểm tuyệt vời của Windows. Lập trình trong Windows hỗ trợ những công cụ cho phép ta tạo ra những giao diện rất dễ dàng và thân thiện. Tuy nhiên, thiết kế giao diện để cho ai cũng có thể sử dụng được và không bị nhầm lẫn không phải là chuyện dễ dàng. Nó đòi hỏi ta phải có một cái nhìn bao quát, thậm chí phải hiểu sâu về giải thuật của chương trình thì mới có thể loại trừ những sai lầm khi sử dụng. Lập trình trong Windows là lập trình theo tình huống. Mọi nút nhấn, ô đối thoại trên giao diện đều có thể được truy cập tới bất kỳ lúc nào mà không theo một trình tự nhất định. Do đó người lập trình cần phải dự trù đến mọi tình huống và cần phải đưa ra một số đề nghị dưới dạng những thông số định sẵn cho người sử dụng theo đó mà vận hành. Ngồi ra, giao diện cần có phần trợ giúp để hướng dẫn cho người sử dụng ở bất kỳ lúc nào. II. Giao diện. Dựa trên sơ đồ khối và lưu đồ giải thuật. Giao diện bao gồm các phần như hình vẽ sau: 1. Input group. Nhóm các thông tin cấu hình và lệnh về tập tin nguồn ( *.wav). Bao gồm các thông tin như : bitrates, samplerates, mode, File path name.. 1 2 3 4 5 6 7 8 2 9 10 11 12 13 14 Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 68 2. Open button. Mở hộp thoại File Open của Windows để chọn file cần nén. Phần mở rộng mặc định là .wav 3. Text Edit box. Dùng gõ file nguồn bằng tay. Mặc định là *.wav. 4. Bitrates. Cho biết chỉ số tốc độ bit của tập tin nguồn .wav đã chọn trên mục 2 hoặc 3. Chỉ số mặc định là 128. Không sửa bằng tay được. 5. Samplerates. Cho biết tần số lấy mẫu của tập tin nguồn .wav đã chọn trên mục 2 hoặc 3. Tần số mặc định là 44100 Hz. Không sửa bằng tay được. Các tần số có thể bao gồm : 32000, 44100 và 48000 Hz. 6. Output. Nhóm các thông tin cấu hình và lệnh về tập tin đích ( *.mp3). Bao gồm các thông tin như : bitrates, samplerates, mode, File path name.. 7. Save button. Mở hộp thoại File Save của Windows để ghi đường dẫn và tên file nén. Phần mở rộng mặc định là .mp3. 8. Text Edit box. Dùng gõ đường dẫn à tên tập tin đích bằng tay. Mặc định là *.mp3. Khi đã chọn được tập tin nguồn trong phần 2 hoặc 3 thì trong ô này sẽ tự động xuất hiện đường dẫn và tên tập tin đích. 9. Bitrates. Định chỉ số tốc độ bit của tập tin đích đã chọn trên mục 7 hoặc 8. Chỉ số mặc định là 128. Có thể chọn các chỉ số khác trong ô kéo xuống, bao gồm các giá trị : 16, 32, 40, 48, 56, 64, 80, 96, 112, 128, 156, 160, 192, 224, 256, 320. 10. Samplerates. Cho biết tần số lấy mẫu của tập tin đích, phụ thuộc và bằng với tần số lấy mẫu của tập tin nguồn. Tần số mặc định là 44100 Hz. Không sửa bằng tay được. 11. Mode group. Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 69 Nhóm các chế độ Stereo hay Mono. Mặc định là Stereo. 12. Progress bar. Thanh tiến trình, xuất hiện trong quá trình nén từ tập tin nguồn .wav sang tập tin đích .mp3 . 13. Compress button. Nút nhấn này chỉ có thể sau khi đã chọn và định cấu hình đầy đủ cho các tập tin nguồn và đích. Nghĩa là chỉ có thể nhấn được nút này sau khi đã nhấn nút Update. Khi nhấn nút này, quá trình nén từ tập tin nguồn sang tập tin đích mới thực sự bắt đầu. Đồng thời thanh tiến trình mới bắt đầu hoạt động. Kết thúc quá trình nén sẽ có thông điệp báo cho biết đã hồn tất công việc 14. Update button. Phím này được nhấn sau khi đã chọn các tập tin nguồn và đích để cập nhật các thông số chuẩn bị cho quá trình nén và kích hoạt phím Compress. III. Chương trình. Chương trình có nền là hộp thoại MP3 COMPRESSOR hiển thị các phím nhấn cho người sử dụng lựa chọn và chạy ứng dụng. Do đó, tất cả các hàm chính đều được đặt trong lớp CMp3Dlg. Sau đây ta sẽ lần lược khảo sát một số hàm quan trọng. 1. OnInitDialog( ) : Hàm này khởi tạo một số giá trị mặc định cho hộp thoại, nhằm giúp cho người sử dụng có một cái nhìn tồn cục và hiểu được ngay ứng dụng, để từ đó có thể chọn lựa các thông số thích hợp cho ứng dụng. Đồng thời, cũng cài đặt sẵn một số giá trị ban đầu cho các đối tượng được dùng cho chương trình. BOOL CMp3Dlg::OnInitDialog() { CDialog::OnInitDialog(); ... // Khởi tạo giá trị ban đầu cho hộp thoại m_stereo_in = 0; m_stereo_out = 0; m_file_in = "*.wav"; m_file_out = "*.mp3"; m_samplerates_in = "44100"; m_samplerates_out = "44100"; Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 70 m_bitrates_in = "128"; m_bitrates_out.AddString("32"); m_bitrates_out.AddString("40"); m_bitrates_out.AddString("48"); m_bitrates_out.AddString("56"); m_bitrates_out.AddString("64"); m_bitrates_out.AddString("80"); m_bitrates_out.AddString("96"); m_bitrates_out.AddString("112"); m_bitrates_out.AddString("128"); m_bitrates_out.AddString("160"); m_bitrates_out.AddString("192"); m_bitrates_out.AddString("224"); m_bitrates_out.AddString("256"); m_bitrates_out.AddString("320"); m_bitrates_out.SetCurSel(8); UpdateData(FALSE); bOpen = FALSE; bSave = FALSE; // Gán các hằng cho các đối tượng config.mpeg.type = TYPE_MPEG_I; config.mpeg.layr = LAYR_III; config.mpeg.mode = MODE_STEREO; config.mpeg.bitr = 128; config.mpeg.psyc = PSYC_ATT; config.mpeg.emph = EMPH_NONE; config.mpeg.crc = 0; config.mpeg.ext = 0; config.mpeg.mode_ext = 0; config.mpeg.copyright = 0; config.mpeg.original = 0; GetDlgItem(IDC_COMPRESS)->EnableWindow(FALSE); m_pbar.SetRange(0, 10000); ... return TRUE; // return TRUE unless you set the focus to a control } 2. OnFileOpen( ) : Hàm mở hộp thoại Open của Windows để chọn file nguồn có phần mở rộng mặc định là .wav, gán cho biến m_file_in đường dẫn và tên file đã chọn. Đồng thời cũng tạo đường dẫn và tên file mặc định cho tập tin đích có phần mở rộng .mp3 và gán cho biến m_file_out. void CMp3Dlg::OnFileOpen() { // Mở hộp thoại File Open của Windows bằng hàm thành viên dlgOpen của // lớp CFileDialog trong thư viện MFC. Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 71 CFileDialog dlgOpen(TRUE, "wav", "*.wav"); if (dlgOpen.DoModal() == IDOK) { m_file_in = dlgOpen.GetPathName(); // gán đường dẫn file nguồn // cho đối tượng m_file_in int len; str1 = m_file_in; len = str1.GetLength(); str2 = str1.Left(len - 3); str2 += "mp3"; m_file_out = str2; // gán đường dẫn file đích // cho đối tượng m_file_out bOpen = TRUE; UpdateData(FALSE); } } 3. OnFileWrite( ) : Hàm mở hộp thoại Save của Windows để chọn đường dẫn và tên tập tin đích trong trường hợp không muốn đường dẫn và tên file mặc định do hàm OnFileOpen( ) tạo ra, và gán nó cho biến m_file_out. void CMp3Dlg::OnFileWrite() { CFileDialog dlgWrite(FALSE, "mp3", str2); if (dlgWrite.DoModal() == IDOK) { m_file_out = dlgWrite.GetPathName(); // gán đường dẫn file đích // cho đối tượng m_file_out UpdateData(FALSE); bSave = TRUE; } } 4. OnUpdate( ) : Hàm cập nhật tất cả các thông số đã chọn trên hộp thoại, đưa vào các đối tượng được dùng trong chương trình. Đồng thời kích hoạt phím nhấn COMPRESS cho phép phím này đã có thể bắt đầu được sử dụng. Nếu các thông số nhập không hợp lệ sẽ cho hiện ra các thông báo để nhập lại. void CMp3Dlg::OnUpdate( ) { UpdateData(TRUE); if (!m_file_in.Compare("*.wav")) MessageBox("Enter the Input file, please!"); else if (!m_file_out.Compare("*.mp3")) { int len; str1 = m_file_in; Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 72 len = str1.GetLength(); str2 = str1.Left(len - 3); str2 += "mp3"; m_file_out = str2; } config.infile = m_file_in.GetBuffer(5); // Chuyển giao con trỏ chỉ // đến file nguồn if (!wave_open()) { MessageBox("Unable to open input file..."); bWaveOpen = FALSE; } else bWaveOpen = TRUE; // Gán giá trị cấu hình bitrates cho biến config.mpeg.bitr tuỳ theo giá trị đã // chọn trên hộp thoại. if (m_bitrates_out.GetCurSel()==0) config.mpeg.bitr = 32; if (m_bitrates_out.GetCurSel()==1) config.mpeg.bitr = 40; if (m_bitrates_out.GetCurSel()==2) config.mpeg.bitr = 48; if (m_bitrates_out.GetCurSel()==3) config.mpeg.bitr = 56; if (m_bitrates_out.GetCurSel()==4) config.mpeg.bitr = 64; if (m_bitrates_out.GetCurSel()==5) config.mpeg.bitr = 80; if (m_bitrates_out.GetCurSel()==6) config.mpeg.bitr = 96; if (m_bitrates_out.GetCurSel()==7) config.mpeg.bitr = 112; if (m_bitrates_out.GetCurSel()==8) config.mpeg.bitr = 128; if (m_bitrates_out.GetCurSel()==9) config .mpeg.bitr= 160; if (m_bitrates_out.GetCurSel()==10) config.mpeg.bitr = 192; if (m_bitrates_out.GetCurSel()==11) config.mpeg.bitr = 224; if (m_bitrates_out.GetCurSel()==12) config.mpeg.bitr = 256; if (m_bitrates_out.GetCurSel()==13) config.mpeg.bitr = 320; config.mpeg.bitrate_index = find_bitrate_index(config.mpeg.bitr); bOpen = FALSE; bSave = FALSE; // Hàm GetDlgItem(IDC_ ) cho phép phím nhấn có IDC_ làm thông số có thể // hoạt động được if (bWaveOpen) GetDlgItem(IDC_COMPRESS)->EnableWindow(); UpdateData(FALSE); } 5. OnCompress( ) : Khi gọi hàm này, quá trình nén từ tập tin nguồn .wav sang tập tin đích .mp3 sẽ bắt đầu thực hiện. Kết thúc quá trình nén sẽ có hộp thoại xuất hiện thông báo đã hồn tất. void CMp3Dlg::OnCompress() { CCompressDlg compDlg; config.outfile = m_file_out.GetBuffer(5); L3_compress(); wave_close(); compDlg.DoModal(); // Cho hiển thị hộp thoại thông báo Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 73 // công việc nén đã hồn tất m_pbar.SetPos(0); // Trả trạng thái thanh tiến trình về vị trí đầu GetDlgItem(IDC_COMPRESS)->EnableWindow(FALSE); } 6. Wave_open( ) : Hàm mở file nguồn và kiểm tra xem định dạng file có hợp lệ không, nếu không thì sẽ hiện thông bào và chọn lại file khác. bool CMp3Dlg::wave_open() { static char *channel_mappings[] = {NULL,"mono","stereo"}; unsigned short wFormatTag; unsigned long dAvgBytesPerSec; unsigned short wBlockAlign; long filesize; long header_size; if((config.wave.file = fopen(config.infile,"rb")) == NULL) { MessageBox("Unable to open file"); return false; } if(!checkString(config.wave.file,"RIFF")) { MessageBox("Input not a MS-RIFF file"); return false; } filesize = Read32BitsLowHigh(config.wave.file); // complete wave chunk size if(!checkString(config.wave.file,"WAVE")) { MessageBox("Input not WAVE audio"); return false; } /* WAVE FMT format chunk */ if(!checkString(config.wave.file,"fmt ")) { MessageBox("Can't find format chunk"); return false; } /* my total header size calculations don't work, so this is bogus... */ header_size = Read32BitsLowHigh(config.wave.file); /* chunk size */ wFormatTag = Read16BitsLowHigh(config.wave.file); if(wFormatTag!=0x0001) { MessageBox("Unknown WAVE format"); return false; } config.wave.type = WAVE_RIFF_PCM; config.wave.channels = Read16BitsLowHigh(config.wave.file); Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 74 config.wave.samplerate = Read32BitsLowHigh(config.wave.file); dAvgBytesPerSec = Read32BitsLowHigh(config.wave.file); wBlockAlign = Read16BitsLowHigh(config.wave.file); /* PCM specific */ if(config.wave.channels>2) { MessageBox("More than 2 channels\n"); return false; } if(config.wave.channels>1) { m_stereo_in = 0; m_stereo_out = 0; config.mpeg.mode = MODE_STEREO; MessageBox("WAVE audio, mode stereo"); } else { m_stereo_in = 1; m_stereo_out = 1; config.mpeg.mode = MODE_MONO; MessageBox("Microsoft RIFF , WAVE audio, mode mono"); } switch (config.wave.samplerate) { case 32000: m_samplerates_in = "32000"; m_samplerates_out = "32000"; config.mpeg.samplerate_index = 2; break; case 44100: m_samplerates_in = "44100"; m_samplerates_out = "44100"; config.mpeg.samplerate_index = 0; break; case 48000: m_samplerates_in = "48000"; m_samplerates_out = "48000"; config.mpeg.samplerate_index = 1; break; default: MessageBox("Samplerate not supported !!"); exit(-1); } config.wave.bits = Read16BitsLowHigh(config.wave.file); if(config.wave.bits!=16) { MessageBox("NOT 16 Bit !!!"); return false; } if(!checkString(config.wave.file,"data")) { MessageBox("Can't find data chunk"); return false; } header_size = ftell(config.wave.file); fseek(config.wave.file, 0, SEEK_END); Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 75 filesize = ftell(config.wave.file); fseek(config.wave.file, header_size, SEEK_SET); config.wave.total_samples =(filesize-header_size)/(2*config.wave.channels); config.wave.length = config.wave.total_samples/config.wave.samplerate; return true; } 7. L3_compress( ) : Đây là hàm quan trọng nhất trong chương trình, nó mô tả tồn bộ giải thuật của ứng dụng. Vòng lặp nén cũng nằm trong hàm này. Mỗi vòng lặp thực hiện công việc nén cho một frame dữ liệu đọc từ file nguồn. Cũng từ vòng lặp này, ta cho thanh tiến trình hoạt động nhờ vào kích thước biết trước của file đọc vào. Vòng lặp kết thúc cũng là lúc thanh tiến trình được điền đầy và thông báo “Compress complete !” xuất hiện. void CMp3Dlg::L3_compress() { int frames_processed; int m_step; int total_frames; static short buffer[2][1152]; int channel; int i; int gr; short sam[2][1344]; double snr32[32]; L3_psy_ratio_t ratio; double pe[2][2]; L3_side_info_t side_info; short *buffer_window[2]; double win_que[2][HAN_SIZE]; double l3_sb_sample[2][3][18][SBLIMIT]; double mdct_freq[2][2][576]; int l3_enc[2][2][576]; L3_scalefac_t scalefactor; bitstream_t bs; double vg_slots_per_frame; ouble rac_slots_per_frame; ong hole_slots_per_frame; ouble lot_lag; nt mean_bits; unsigned long sent_bits = 0; unsigned long frame_bits = 0; int sideinfo_len; // Mở thiết bị để ghi vào open_bit_stream_w(&bs, config.outfile, BUFFER_SIZE); memset((char*)snr32,0,sizeof(snr32)); memset((char *)sam,0,sizeof(sam)); Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 76 memset((char *)&side_info,0,sizeof(L3_side_info_t)); L3_psycho_initialise(); L3_subband_initialise(); L3_mdct_initialise(); L3_loop_initialise(); config.mpeg.mode_gr = 2; config.mpeg.samples_per_frame = 1152; config.mpeg.total_frames = config.wave.total_samples/config.mpeg.samples_per_frame; total_frames = config.mpeg.total_frames; config.mpeg.bits_per_slot = 8; frames_processed = 0; sideinfo_len = 32; if(config.wave.channels==1) sideinfo_len += 136; else sideinfo_len += 256; if(config.mpeg.crc) sideinfo_len += 16; /* Figure average number of 'slots' per frame. */ avg_slots_per_frame = ((double)config.mpeg.samples_per_frame / ((double)config.wave.samplerate/1000)) * ((double)config.mpeg.bitr / (double)config.mpeg.bits_per_slot); whole_slots_per_frame = (int)avg_slots_per_frame; frac_slots_per_frame = avg_slots_per_frame - (double)whole_slots_per_frame; slot_lag = -frac_slots_per_frame; if(frac_slots_per_frame==0) config.mpeg.padding = 0; while(wave_get(buffer)) { frames_processed++; m_step = (int)(10000 * frames_processed / total_frames); m_pbar.SetPos(m_step); buffer_window[0] = buffer[0]; buffer_window[1] = buffer[1]; if(frac_slots_per_frame!=0) if(slot_lag>(frac_slots_per_frame-1.0)) { /* No padding for this frame */ slot_lag -= frac_slots_per_frame; config.mpeg.padding = 0; } else { /* Padding for this frame */ slot_lag += (1-frac_slots_per_frame); config.mpeg.padding = 1; } config.mpeg.bits_per_frame = 8*(whole_slots_per_frame + config.mpeg.padding); Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 77 mean_bits = (config.mpeg.bits_per_frame - sideinfo_len) / config.mpeg.mode_gr; /* psychoacousic model */ for(gr=0;gr<config.mpeg.mode_gr;gr++) for(channel=0;channel<config.wave.channels;channel++) L3_psycho_analize(channel, &buffer[channel][gr*576], &sam[channel][0], &snr32[0], &ratio.l[gr][channel][0], &ratio.s[gr][channel][0], &pe[gr][channel], &side_info.gr[gr].ch[channel].tt); /* polyphase filtering */ for(gr=0;gr<config.mpeg.mode_gr;gr++) for(channel=0;channel<config.wave.channels;channel++) for(i=0;i<18;i++) { L3_window_subband(&buffer_window[channel], &win_que[channel][0], channel); L3_filter_subband(&win_que[channel][0], &l3_sb_sample[channel][gr+1][i][0]); } /* apply mdct to the polyphase output */ L3_mdct_sub(l3_sb_sample, mdct_freq, &side_info, &config); /* bit and noise allocation */ L3_iteration_loop(pe,mdct_freq,&ratio,&side_info, l3_enc, mean_bits,&scalefactor, &config); /* write the frame to the bitstream */ L3_format_bitstream(l3_enc, &side_info, &scalefactor, &bs, mdct_freq, NULL , 0, &config); frame_bits = sstell(&bs) - sent_bits; sent_bits += frame_bits; } L3_FlushBitstream(); close_bit_stream_w(&bs); } Khoa CNTT – ĐHBKHN GVHD Thầy:Dư Thanh Bình SVTH: Đỗ Văn Tuấn Trang 78 Tài liệu tham khảo 1. Giáo trình âm học Kiến trúc. KTS. Việt Hà - Nguyễn Ngọc Giả Trường Đại học kiến trúc – 1993 2. Kỹ năng lập trình Windows bằng Visual C++6. Lê Minh Trí Nhà xuất bản thanh niên – 2001 (Tập 1&2) 3. Xử lý tín hiệu số. Quách Tuấn Ngọc Nhà xuất bản Giáo dục – 1997 4. Digital Signal Processing John G.Proakis - Dimitris G.Manolakis Prentice Hall 5. C Language Algorithms for Digital Signal Processing Paul M.Embree - Bruce Kimble Prentice Hall 6. Địa chỉ Internet :

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

  • pdfĐề tài- Nén âm thanh file WAV theo chuẩn MPEG.pdf