Mã hĩa Huffman

Một phần của tài liệu tìm hiểu về các phương pháp mã hố và nén âm thanh theo chuẩn Mpeg (Trang 47)

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) --- --- --- --- --- 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.

SVTH: Đỗ Văn Tuấn Trang 48

Bộ mã hĩa

Initialize_model();

while ((c = getc (input)) != eof) {

encode(c, output); update_model(c);

Bộ giải mã

Initialize_model();

while ((c = decode (input)) != eof) {

putc(c, output); update_model(c);

• 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. (adsbygoogle = window.adsbygoogle || []).push({});

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.

• 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 (adsbygoogle = window.adsbygoogle || []).push({});

^ 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: 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ý.

• 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. 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 (adsbygoogle = window.adsbygoogle || []).push({});

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

• 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

CHƯƠNG 6. LƯU ĐỒ GIẢI THUẬT VÀ CẤU TRÚC DỮ LIỆU.

I. SƠ ĐỒ KHỐI.

SVTH: Đỗ Văn Tuấn Trang 55

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ã hố một mẫu dữ liệu L3_interation_loop(); Ghi frame vào dịng bit

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 (adsbygoogle = window.adsbygoogle || []).push({});

II. CẤU TRÚC DỮ LIỆU VÀ ĐỊNH NGHĨA.A. Cấu trúc dữ liệu. A. Cấu trúc dữ liệu.

1. Các cấu trúc về file: - Tập tin tiêu đề : <types.h>

- 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 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 đề : <bitstream.h>

- 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 đề : <FormatBitstream.h> 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):

Đâ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_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; (adsbygoogle = window.adsbygoogle || []).push({});

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 đề : <Huffman.h>

- 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] */ };

- Tập tin tiêu đề : <Layer3.h>

- 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];

Một phần của tài liệu tìm hiểu về các phương pháp mã hố và nén âm thanh theo chuẩn Mpeg (Trang 47)