XÂY DỰNG CHƯƠNG TRÌNH NGHE NHẠC

Một phần của tài liệu đồ án công nghệ thông tin XÂY DỰNG CHƯƠNG TRÌNH CHƠI NHẠC FLAC TRÊN T-ENGINE BOARD (Trang 54)

4.1 Giải mã file FLAC

4.1.1 Đọc thông tin của file

Đầu tiên, chương trình sẽ đọc các thông tin cơ bản của file để phục vụ cho mục đích giải mã file FLAC. Thông tin cơ bản của file nằm trong metadata block STREAMINFO, block này nằm ngay sau 4 byte “FLAC”.

Các metadata block bao gồm header 32 bit (4 byte) và phần data.

Header của block gồm 1 bit là flag, để xác định block cuối cùng trong stream (flag =1), ngay sau block này sẽ là các frame audio. 7 bit tiếp theo là để xác định loại metadata. STREAMINFO thì 7 bit này sẽ là 000.0000. 24 bit còn lại để xác định độ dài của phần data đứng sau nó.

STREAMINFO có phần data là 272 bit (34 byte).

Chương trình sẽ đọc phần header để xác định loại metadata. Sau đó đọc phần data để lấy các thông tin gồm block size min/max(tính theo mẫu), frame size min/max (tính theo byte), tần số lấy mẫu, số kênh, số bit trên một mẫu, tổng số mẫu, MD5.

4.1.2 Đọc frame, giải mã file FLAC

Frame FLAC bao gồm header, subframe và footer.

Hình 4.1: Cấu trúc của frame

Trong đó:

Header gồm 14 bit sync code 11.1111.1111.1110 , các bit chứa các thông tin về file, và cuối cùng là 8 bit CRC.

Footer gồm 16 bit CRC.

Bảng 4.1: Thông tin chi tiết của file từ frame header

Bits Kích thước block Tần số mẫu Kênh Bits

Số kênh Phân kênh

0000 Lấy từ

STREAMINFO

Lấy từ STREAMINFO

1 Mono 0000

0001 192 88200 2 Trái, phải 0001

0010 576 176400 3 Trái, phải, giữa 0010

0011 1152 192000

4 Trái, phải, trái sau, phải sau

0011

0100 2304 8000

5 Trái, phải, giữa, trái sau, phải sau

0100

0101 4608 16000

6 Trái, phải, giữa, trái sau, phải sau, LFE

0101 0110 8 bits cuối của

header (+1)

22050

0111 16 bits cuối của heade r(+1) 24000 8 0 trái, 1 khác 0111 1000 256 32000 2 0 khác, 1 phải 1000 1001 512 44100 2 0 trung bình, 1 khác 1001 1010 1024 48000 2 1010 1011 2048 96000 Dự trữ 1011

1100 4096 Lấy 8 bit cuối của header (kHz)

Dự trữ 1100

1101 8192 Lấy 16 bit cuối của header (Hz)

Dự trữ 1101

1110 16384 Lấy 16 bits của header (Hz trong 10s)

Dự trữ 1110

1111 32768 Vô hiệu Dự trữ 1111

Bảng 4.2: số bit trên một mẫu tương ứng trong trường “bit persample”

Subframe: mỗi kênh sẽ có một subframe, có 4 loại subframe là constant, fixed, LPC, verbatim. Mỗi subframe gồm header và data của một trong bốn loại trên.

Header của subframe sẽ chỉ ra đó là loại subframe nào và giá trị bậc của dự đoán tuyến tính (nếu subframe đó là fixed hay LPC).

Bảng 4.3: Các loại subframe

Kiểu subframe

Bits Type

000000 SUBFRAME_CONSTANT

Số bit trong 1 mẫu Bits Bit trong mẫu

000 Lấy trong STREAMINFO

001 8 010 12 011 Dự trữ 100 16 101 20 110 24 111 Dự trữ

000001 SUBFRAME_VERBATIM 00001x Dự trữ 0001xx Dự trữ 001xxx SUBFRAME_FIXED (xxx = Bậc Predictor ) 01xxxx Dự trữ 1xxxxx SUBFRAME_LPC (xxxxx =Bậc LPC - 1)

Subframe constant: đây là subframe đơn giản nhất, chứa một giá trị duy nhất có kích thước bằng với số bit trên một mẫu của frame. Ví dụ, một frame 16 bit sẽ có một subframe có chiều dài 16 bit. Giá trị của subframe là giá trị của tất cả các mẫu mà subframe chứa. Subframe này được sử dụng để lưu trữ các tín hiệu câm (mẫu có giá trị là 0) rất hiệu quả.

Subframe verbatim: subframe này có chiều dài là tích của số bit trên một mẫu của frame với kích thước của frame (block size). Subframe này không được nén và chỉ đơn giản là lưu các mẫu audio thô, nên nó chỉ thích hợp với những phần âm thanh đặc biệt ồn ào của một bản nhạc, phần mà rất khó để dự đoán.

Sample1 Sample2 Sample3 … Samplen

0

Hình 4.2 : Cấu trúc của Verbatim subframe

Subframe fixed: số lượng mẫu “warm-up” bằng với số bậc dự đoán (được chỉ ra trong header của subframe). Các mẫu này được xem như là các mẫu trong quá khứ, bộ giải mã sẽ dùng các mẫu này để dựa vào đó dự đoán các mẫu tiếp theo. Sau đó tùy theo bậc dự đoán và residual được kèm theo mà đưa ra công thức tính toán để giải mã để lấy lại tín hiệu gốc.

Warm-Up Sample1 Warm-Up Sample2 … Phần dư

0

Hình 4.1 : Cấu trúc của Fixed subframe

Bảng 4.4 Công thức tính giá trị mẫu trong Fixed subframe

Bậc dự đoán

Phép tính

0 Mẫu i = dưi

1 Mẫu i = mẫui-1 + dưi

2 Mẫu i = (2 x mẫui-1 ) - mẫui-2 + dưi

3 Mẫu i = (3 x mẫui-1 ) - (3 x mẫui-2) + mẫui-3 + dưi

4 Mẫu i = (4 x mẫui-1) - (6 x mẫui-2) - (4 x mẫui-3) - mẫui-4 + dưi

Bảng 4.5 Ví dụ đơn giản về cách tính mẫu

Inde x Dư Mẫu 0 (Warm-up)10 1 1 10+1=11 2 2 11+2=13 3 -2 13-2=11 4 1 11+1=12 5 -1 12-1=11

Subframe LPC: số lượng mẫu “warm-up” bằng với số bậc dự đoán (được chỉ ra trong header của subframe). Kích thước của hệ số QLP bằng với số bit của precision QLP cộng 1. Giá trị của các hệ số QLP là a signed two’s- complement integer. Số hệ số QLP bằng chính bậc của LPC. Công thức dự đoán mẫu tiếp theo là :

Giống như các subframe fixed, subframe LP cũng có các warm-up làm các mẫu đầu tiên để tính toán tự đoán các mẫu tiếp theo.

Warm-up sample1 Warm-up sample2 … Warm-up samplen

0

QLP Precision QLP Shift Needed QLP Coefficient1 QLP Coefficient2 …

0 3 4 8 9 ? Residual

Hình 4.2: Cấu trúc của LPC subframe

Ví dụ: với bậc LPC là 5, QLP Shift Needed là 9 thì 5 hệ số QLP lần lượt là:

QLP Coefficient0 = 1241

QLP Coefficient0 = 944

QLP Coefficient0 = 14

QLP Coefficient0 = 342

QLP Coefficient0 = -147

Bảng 4.6 Ví dụ tính giá trị mẫu trong LPC subframe

Inde x Dư Mẫu 0 (warm-up) 1053 1 (warm-up) 1116 2 (warm-up) 1257 3 (warm-up) 1423 4 (warm-up) 1529 5 11 (1241 × 1529) + (−944 × 1423 ) + (14 × 1257) + (342 × 1116)

+ (−147 × 1053 ) = 798656 (798656 / 29) = 1559 +11 = 15 70 6 79 (1241 × 1570) + (−944 × 152 9) + (14 × 1423 ) + (342 × 1257) + (−147 × 1116) = 790758 (790758 / 29) = 1544 + 79 = 1623 7 24 (1241 × 1623) + (−944 × 15 70) + (14 × 1529) + (342 × 1423 ) + (−147 × 1257) = 855356 (855356/ 29) = 1670 + 24 = 1694 8 -81 (1241 × 1694) + (−944 × 1623) + (1 4 × 15 70) + (342 × 1529) + (−147 × 1423 ) = 905859 (905859/ 29) = 1769 − 81 = 1688 9 -72 (1241 × 1688 ) + (−944 × 1694) + (14 × 1623) + (342 × 1570) + (−147 × 152 9) = 830571 (830571/ 29) = 1622 − 72 = 1550 4.1.3 Residual coding

Hinh 4.5: Cấu trúc của Residual (phần dư)

Mặc dù định dạng FLAC cho phép nhiều dạng khác nhau của mã hóa phần dư (residual coding), nhưng hiện nay chỉ có hai dạng được hỗ trợ. Sự khác biệt giữa hai dạng này chính là ở phương thức mã hóa (Coding Method), nếu Coding Method =0, thì tham số Rice là 4 bit, nếu Coding Method =1, thì tham số Rice là 5 bit.

2 bậc partition số partition. Số mẫu giải mã trong một partition phụ thuộc vào vị trí của nó trong subframe. Partition đầu tiên trong subframe chứa:

Các partition còn lại chứa:

Nếu bậc partition (partition order) bằng 0, trong trường hợp này chỉ có một partition. Và trong trường hợp này thì:

Nếu tất cả các bit trong tham số Rice (Rice Parameter) được set lên 1, partition sẽ không đươc mã hóa bởi một số nhị phân mà sử dụng số “ Escape Code ” với số bit bằng với số bit trên một mẫu.

4.1.4 Mã Rice

Phần dư / lỗi (residual) sử dụng mã hóa Rice để nén nhiều giá trị nhỏ trong một vùng không gian rất nhỏ. Để giải mã nó, đầu tiên cần một tham số Rice. Lấy một giá trị đơn nguyên từ chuỗi bit, ở đây được lưu trữ dưới dạng most significant bits (MSB). Sau đó lấy tham số trong số bit thêm vào, được lưu trữ dưới dạng least significant bits (LSB). Kết hợp hai giá trị trên để tạo ra một giá trị mới, với MSB được xem như là bit cao, LSB được xem như là bit thấp. Bit 0 của giá trị mới này là một bit dấu (sign bit). Nếu nó bằng 0, thì giá trị thực sự bằng phần còn lại của chuỗi bit. Nếu nó bằng 1, thì giá trị thực sự bằng với phần còn lại của chuỗi bit nhân với 1 và trừ đi 1.

Hình 4.63 Giải mã residual với tham số Rice là 16

Ví dụ với tham số Rice là 4:

Hình 4.4 Giải mã residual với tham số Rice là 4

4.1.5 Kênh

Vì hầu hết các âm thanh hiện nay có nhiều hơn một kênh, nên việc hiểu FLAC làm như thế nào để xử lí nó trở lại ban đầu là rất quan trọng. Khi các kênh được lưu trữ độc lập, một trong những cách để đưa nó trở lại đơn giản nhất là sắp xếp theo thứ tự. Ví dụ một âm thanh có hai kênh, thì 16 bit của nó được lưu như sau:

Hình 4.5 Cách lưu dữ liệu với 2 kênh

Bảng 4.7 Tái tạo kênh

Đây là trường hợp đơn giản nhất, tuy nhiên có thể có những trường hợp phức tạp hơn, các kênh khác nhau thì một subframe sẽ chứa một kênh là dữ liệu thật và một cái khác sẽ chứa một kênh là dữ liệu sai khác(signed difference data), dữ liệu này được áp dụng trong kênh đầu tiên để tái tạo lại cả hai kênh. Có một điều rất quan trọng cần ghi nhớ là kênh sai khác (difference channel) có một bit trên mẫu thêm vào để sử dụng trong quá trình tái tạo.

4.2 Thiết kế chương trình nghe nhạc

4.2.1 Phân tích vấn đề

Chương trình nghe nhạc sẽ chơi các định dạng file phổ biến như WAV, MP3, và định dạng file mà nhóm đã tìm hiểu và giải mã là file FLAC.

Chương trình sẽ tìm và chơi tất cả các file có định dạng trên trong USB và PC card. Vì vậy cần phải xác định từng loại file để có giải thuật đọc và giải mã phù hợp.

Giải mã file FLAC khá phức tạp do đó nhóm sẽ tìm hiểu thư viện libflac là một mã open source trên nền LINUX, sau khi tìm hiểu sẽ tiến hành giải mã và thiết kế chương trình để phù hợp với đáp ứng của phần cứng.

Chương trình sẽ xây dựng giao diện đồ họa để người dùng có thể dễ dàng sử dụng hơn. Giao diện phải có những chức năng cơ bản của một trình nghe nhạc như:

 Các chế độ chơi như normal, random, repeat .

 Các nút điều khiển như play, stop, pause, next, pre.

Phân kênh

Trường hợp Kênh 1 Kênh 0 Kênh trái Kênh phải

1000 Left Difference left left − difference

1001 Difference Right right + difference right

1010 Mid Side (((mid << 1) | (side

& 1)) + side) >> 1

(((mid << 1) | (side & 1)) - side) >> 1

 Play list hiển thị tên và thời gian chơi của các file nhạc định dạng MP3, WAV, FLAC được tìm thấy trong USB và PC card.

 Nút điều chỉnh độ lớn của âm thanh/loa và đồng hồ hiển thị thời gian

chơi được của file.

4.2.2 Hoạt động của chương trình

Chương trình nghe nhạc trên PC card sẽ hiển thị giao diện lên LCD, đọc file FLAC âm thanh trên USB, giải mã file, sau đó Driver âm thanh sẽ phát nhạc qua cổng audio của board T-Egine. Đường đi dữ liệu của chương trình được mô rtả trong hình 4.9

Hình 4.6: Đường đi dữ liệu của chương trình

Chương trình sẽ bắt đầu bằng việc đọc USB và tìm kiếm tất cả các file có định dạng MP3, FLAC, WAV để xây dựng một list gồm các file tìm thấy.

Sau đó, màn hình sẽ hiển thị thông tin của mười file đầu tiên đọc được (nếu số file lớn hơn mười) hoặc hiển thị tất cả các file (nếu số file ít hơn mười) gồm tên bài hát (tên file) và thời gian chơi tương ứng.

Usb

Pc card

LCD

Để chọn lựa chơi giữa các file thì dùng nút giữa (SW2) gạt lên hay xuống.

File được chọn sẽ được làm nổi với màu nền file khác so với màu nền của toàn list nhạc.

Nếu số lượng file lớn hơn mười thì để xem hay chọn chơi các file sau, dùng phím SW2 để gạt lên hay xuống.

Sau khi chọn được file để chơi thì bấm SW2 (tương đương với phím enter) hay chạm nhẹ phần tên file trên màn hình cảm ứng, chương trình sẽ bắt đầu chơi với file được chọn.

Chương trình nghe nhạc bắt đầu chơi một file nào đó thì màn hình sẽ thay đổi qua giao diện của trình nghe nhạc.

Giao diện này sẽ hiển thị tên file đang được chơi, thời gian mà file này chơi hết, thời gian hiện tại file đang chơi được, và một thanh chạy tượng trưng cho phần dung lượng file đã chơi được.

Giao diện cũng bao gồm các nút như:

 PAUSE/PLAY: chuyển trạng thái từ play sang pause, pause sang

 NEXT: chuyển sang chơi bài tiếp theo trong list (tùy theo chế độ chơi).

 PRE: chuyển sang chơi bài trước đó trong list (tùy theo chế độ chơi).

 STOP: chuyển từ trạng thái pause sang stop hay play sang stop.

 GOTO LIBRARY: chuyển sang màn hình play list để hiển thị tất cả

các file nhạc được tìm thấy trong chương trình.

Sau khi một file được chơi xong thì chương trình sẽ tự động chơi file tiếp theo tùy thuộc vào chế độ mà người dùng chọn. Mặc định của chương trình là chế độ NORMAL.

Giao diện cũng bao gồm các nút NORMAL, RANDOM, REPEAT tương ứng với ba chế độ chơi:

 NORMAL: chế độ mặc định, sau khi chơi xong một file thì chương trình sẽ

chơi file nằm ngay sau nó trong list nhạc.

 RANDOM: chế độ chơi ngẫu nhiên, chương trình sẽ chọn ngẫu nhiên một

file trong list để chơi.

 REPEAT: chế độ lặp lại, sau khi chơi xong một file thì sẽ chơi lại file này.

Để điều chỉnh âm thanh cho trình nghe nhạc có thể sử dụng SW2. Nếu gạt lên thì âm thanh sẽ lớn hơn và ngược lại gạt xuống thì âm thanh sẽ được giảm lại.

Ngoài các phím trên màn hình có thể sử dụng các phím nhấn có sẵn trên T Engine (các SW1, SW2, SW3) có chức năng tương đương.

 SW2: nhấn phím giữa tương đương với nút PAUSE/PLAY, gạt sang trái tương

đương với nút PRE, gạt sang phải tương đương với nút NEXT.

 SW1: tương đương với nút STOP.

 SW3: nút exit khỏi chương trình.

4.2.3 Hiện thực chương trình

Chương trình được xây dựng dựa trên task chính là task main. Task main sẽ tạo ra sáu task tương ứng với sáu chức năng của chương trình và năm message buffer để đồng bộ giữa các task với nhau.

Hình 4.70: Hoạt động của main task

6 task là : audio_task, input_task, usb_task, flac_player_task, mp3_player_task, wav_player_task.

5 message buffer là: mbf_audio, mbf_input, mbf_mp3_player, bmf_flac_player,

mbf_wav_player. Trong đó:

audio_task đóng vai trò là task trung tâm kiểm soát toàn bộ chương trình.

usb_task nhận sự kiện từ thiết bị USB và gửi tín hiệu cho audio_task.

input_task là task nhận các tín hiệu input từ touch screen hay từ phím nhấn và gửi tín hiệu đến audio_task để xử lí. Sau khi xử lí, tùy vào tín hiệu nhận được mà audio_task sẽ điều khiển hoạt động của ba task còn lại.

Các task flac_player_task, mp3_player_task, wav_player_task nhận tín hiệu từ auido_task, đồng thời giao tiếp với driver để hiện thực việc giải mã và điều khiển driver phát nhạc.

Cấu trúc tổng quát của chương trình

α. Usb_task

Hình 4.91: Hoạt động của usb_task

- Phát hiện sự kiện về usb như usb được cắm hay usb được rút ra.

- Gửi message tương ứng với từng sự kiện tới message buffer mbf_audio để task audio_task xử lí.

Có 2 loại message :

 MSG_ATT_USB: phát hiện USB được cắm vào cổng usb.

 MSG_DET_USB: phát hiện USB được rút ra khỏi cổng usb.

- Chờ nhận message từ mbf_audio do task audio_task gửi đến.

- Sau khi nhận được message thông báo quá trình đọc thông tin file của tất cả

các file hoàn tất, task này sẽ xây dựng một list nhạc gồm các file có trong chương trình dựa trên danh sách mà task audio_task trả về.

- Sau đó, task sẽ hiển thị play list ra màn hình của T Engine board.

- Task sẽ nhận các sự kiện như phím nhấn, touch screen để xử lí giao diện và

đồng thời gửi tín hiệu đến task audio_task.

Đồng thời, task này cũng tạo ra một cyclic có thời gian đếm là 0.1s có tác dụng như một ngắt timer 0.1s để hiển thị bộ đếm thời gian chơi nhạc và thanh chạy của chương trình chơi nhạc.

Các vấn đề của input_task

- Giao diện sẽ gồm có hai hình ảnh hiện thị, mỗi với hình thì các nút nhấn

hay touch screen sẽ có những chức năng khác nhau, cần phải phân biệt hai trường

Một phần của tài liệu đồ án công nghệ thông tin XÂY DỰNG CHƯƠNG TRÌNH CHƠI NHẠC FLAC TRÊN T-ENGINE BOARD (Trang 54)

Tải bản đầy đủ (DOC)

(90 trang)
w