.7 Tái tạo kênh

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 63 - 90)

Bảng 2 .1 Kết quả mã hóa các kí tự bằng mã Huffman

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 hợp này.

- Trong trường hợp hiển thị play list, khi người dùng chọn bài để chơi thì cần

xác định chính xác file mà người dùng chọn và vị trí của mỗi file trên màn hình có thể thay đổi nếu số file lớn hơn 10.

Hướng giải quyết

- Dùng một biến status để quản lí, với mỗi hình ảnh hiển thị trên màn hình, sẽ

có một giá trị được gán cho status để xác định trạng thái là play list hay giao diện chương trình nghe nhạc. Hai giá trị là:

 Status = LIST: đang ở trong play list

 Status = INTERFACE: đang ở trong giao diện chương trình chơi

nhạc. Đây là trạng thái ban đầu của chương trình.

typedef struct LIST_MUSIC{ RECT r;

audioNode *node; int vitri;

struct LIST_MUSIC *next; struct LIST_MUSIC *pre; } LIST_MUSIC;

Trong danh sách này gồm hai con trỏ next và pre để xác định địa chỉ của hai node trước và sau nó. Biến vitri để chỉ vị trí của file trên màn hình. Trên màn hình chia làm 10 khung, file mà biến vitri có giá trị từ 0 đến 9 sẽ được hiển thị lên màn hình. Con trỏ node kiểu audioNode sẽ chỉ đến một node trong danh sách headAudioList. Danh sách này chứa thông tin của file. Biến r có kiểu RECT, xác định khung trên màn hình của file.

Khi các nút up, down của phím SW2 được nhấn thì biến vitri của mỗi node sẽ thay đổi. Task sẽ cập nhật vị trí mới và hiển thị lại play list mới.

Mảng RECT list[10] là 10 khung trên màn hình, khi vị trí thay đổi thì sẽ cập nhật lại khung bằng cách gán node->r =list[vitri].

Khi người dùng chọn một bài, từ biến vitri sẽ xác định chính xác file cần phải chơi.

Hoạt động

- Task này được xem như một task trung tâm quản lí của toàn bộ chương trình. Nó

giao tiếp với tất cả các task còn lại để nhận thông tin, xử lí, đồng thời gửi thông tin đến các task khác.

- Đầu tiên, nó nhận thông tin từ task usb_task thông qua message của message

buffer mbf_audio. Tùy vào message nhận được, nó sẽ cập nhật các file đọc được từ USB và PC card.

- Sau đó, nó sẽ phân loại các file và với mỗi file sẽ có một giải thuật đọc tương ứng

phù hợp.

- Sau khi đọc xong các thông tin cơ bản của mỗi file, sẽ có một node được tạo ra

tương ứng với file đó và gắn vào trong một danh sách để quản lí.

- Sau khi danh sách được xây dựng hoàn tất, nó sẽ gửi một message đến mbf_input

để thông báo với task input_task rằng quá trình đọc thông tin của tất các file đã hoàn tất.

- Đồng thời, nó sẽ chờ nhận message từ input_task qua mbf_audio để thực hiện việc

chơi nhạc cũng như điều khiển các trạng thái chơi như play, pause, stop hay điều chỉnh về độ lớn của âm thanh / loa.

- Khi nhận thông tin từ input_task, audio_task sẽ kiểm tra xem loại file nào được

chơi để gửi message đến task của từng loại file tương ứng (flac_player_task,

mp3_player_task hay wav_player_task) thông qua message buffer như mbf_flac_player, bmf_wav_player, bmf_mp3_player.

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

- Xây dựng một kiểu cấu trúc dữ liệu để lưu trữ các file cũng như thông tin cơ bản

của các file mà chương trình nhận được.

- Xác định được các trạng thái hiện tại của trình chơi nhạc, xác định file hiện tại

- Thiết lập các giá trị cho driver.

Hướng giải quyết

- Kiểu cấu trúc dữ liệu để lưu trữ thông tin của file được chọn là một danh sách liên

kết có kiểu struct là audioNode. typedef struct{ QUEUE node; char*filename; UB name[512]; VP *audio_fp; W number; W type; W duration; W remainingTime; W starttime; W locate; } audioNode;

Con trỏ char *filename lưu đường dẫn của file. Biến number giữ vị trí của node trong danh sách, con trỏ VP *audio_fp kiểu void sẽ trỏ đến một kiểu cấu trúc dữ liệu lưu trữ các thông tin cơ bản của file, tùy từng loại file mà cấu trúc đó được xác định khác nhau. Biến duration lưu thời gian chơi của file. Biến type sẽ xác định loại file. Các số biến còn lại được sử dụng để xử lí chuyển các trạng thái của chương trình.

- Chương trình gồm bốn trạng thái cơ bản được lưu trong biến audioStatus: PAUSE,

- Dựa vào trạng thái hiện tại của chương trình mà audio_task sẽ có những xử lí thích hợp với từng loại tín hiệu được nhận từ input_task.

- Chương trình sử dụng con trỏ audioNode *curAudioNode để lưu node hiện tại

đang được chơi.

- Chương trình sẽ giao tiếp với driver thông qua các hàm điều khiển driver, vì driver

chỉ có thể nhận thông tin từ chương trình bằng cách sử dụng hàm system call tk_swri_dev.

- Các thông tin cần thiết phải thiết lập cho driver là kích thước của driver buffer, ID

của message buffer để driver gửi lại tín hiệu cho chương trình, và các thiết lập về độ lớn của âm thanh.

e. Flac_player_task

Hoạt động

- Nhận message từ audio_task thông qua mbf_flac_player.

- Sau khi nhận được tín hiệu bắt đầu chơi file FLAC, chương trình sẽ khởi tạo kích

thước của buffer driver để phù hợp với kích thước của mỗi frame của file FLAC.

- Đầu tiên, task sẽ thực hiện giải mã với kích thước bằng với kích thước của buffer

driver và ghi tất cả lên buffer driver.Lúc này, buffer driver đã đầy nên task sẽ gửi message đến driver để bắt đầu phát nhạc.

- Sau đó, task này tiến hành đọc các frame của file FLAC và thực hiện giải mã với

kích thước của mỗi lần giải mã bằng một nửa kích thước của buffer driver.

- Nó sẽ chờ tín hiệu từ driver để tiếp tục ghi vào driver, để tránh trường hợp mất dữ

liệu, khi driver phát được một nửa buffer thì driver mới gửi tín hiệu.

- Quá trình đọc dữ liệu- giải mãi- ghi lên driver được tiếp tục cho đến hết file.

Hình 4.10: Hoạt động của flac_player_task

- Cấu trúc dữ liệu dùng lưu trữ các thông tin của file FLAC.

- File FLAC có dung lượng khá lớn, thường khoảng từ 20Mb đến trên 100Mb, tốc

độ đọc từ cổng USB của T Engine board lại không cao nên cần phải đồng bộ tốt giữa các quá trình đọc dữ liệu, giải mã, đẩy dữ liệu ra buffer driver và điều khiển driver phát nhạc.

- Vấn đề đặt ra là chất lượng âm thanh phải được đảm bảo tốt nhất với những đáp

ứng của phần cứng.

- Tốc độ giải mã giữa các file khác nhau thì khác nhau, nên cần một giải thuật tốt để

có thể tổng quát hóa chương trình phù hợp với tất cả các file.

Hướng giải quyết

Cấu trúc dữ liệu dùng lưu trữ file FLAC là một struct có kiểu FLAC_FILE

typedef struct { char *filename; W file_handle; W fileSize; W audioFormat; W numChannels; W sampleRate; W byteRate; W blockAlign; W bitsPerSample; W numData; W duration; W total_samples; UB* file_buffer;

UW file_buffer_size;

FLAC__FileDecoder *decoder; stream_info_struct stream_info; } FLAC_FILE;

Trong đó FLAC__FileDecoder *decoder để chứa bit stream và các thông số còn lại cần thiết để giải mã file FLAC như total_sample, sampleRate, numChannels, bitspersample, …

File FLAC được giải mã theo frame, mỗi lần giải mã một frame, kích thước dữ liệu thô sau khi giải mã là 16Kb. Thế nên kích thước driver buffer được chọn là 512Kb, một bội số của 16Kb.

Đầu tiên chương trình sẽ giải mã 512Kb dữ liệu, và tất cả được đẩy vào buffer driver. Sau khi quá trình đẩy data hoàn tất, flac_player_task sẽ gửi tín hiệu điều khiển yêu cầu driver phát nhạc.

Sau đó, flac_player_task tiếp tục decode 16Kb dữ liệu tiếp theo. Sau khi quá trình decode hoàn tất, flac_player_task sẽ chờ tín hiệu từ driver trong thời gian là 0s, tức là nó sẽ kiểm tra ngay lập tức xem có message từ driver hay không, nếu không thì nó sẽ tiếp tục

giải mã 16Kb tiếp theo. Nếu phát hiện có message thì chứng tỏ quá trình giải mã chậm hơn quá trình phát nhạc. Lúc đó nó sẽ đẩy dữ liệu mới giải mã được vào driver. Quá trình được lặp lại cho đến khi nó mã hóa được đúng một nửa kích thước của buffer driver.

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 63 - 90)

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

(90 trang)
w