III.1. Khái niệm về file Wave và file RIFF :
File Wave là một dạng file theo chuẩn của Microsoft cho phép lưu trữ dữ
liệu sĩng âm được số hĩa. Nĩ hỗ trợ rất đa dạng các thơng số của âm thanh như số bit lượng tử hĩa, tốc độ lấy mẫu, số kênh. Dạng file này rất phổ biến
trên các thế hệ máy tính IBM và được sử dụng rộng rãi trong các chương trình chuyên nghiệp để xử lý các sĩng âm được số hĩa.
SVTH : Bùi Danh Đạt Trang 31
File Wave là một trong số các file thuộc chuẩn của file RIFF (Resource
Interchange File Format - Dạng file trao đổi tài nguyên). File RIFF sử dụng phương pháp lưu trữ dữ liệu trong các chunk. Mỗi chunk sẽ gồm 3 trường :
Tên nhận dạng của chunk (ID) : gồm 4 byte kiểu Char
Kích thước của chunk (Size) : Kiểu DoubleWord. Giá trị này khơng bao gồm 4 byte của ID và 4 byte của Size
Dữ liệu của chunk đĩ (Data)
Đặc biệt, chunk RIFF cĩ thể chứa các chunk khác trong trường dữ liệu. Các chunk này được gọi là subchunk và chunk RIFF lúc này được gọi là
parent chunk.
Một file RIFF luơn bắt đầu bằng một chunk RIFF. Kích thước của chunk
RIFF là kích tổng số byte mà trường dữ liệu của nĩ chiếm, nĩi cách khác chính là kích thước của file RIFF - 8 .
Tất cả các chunk khác trong file RIFF đều là subchunk của chunk RIFF.
Chunk RIFF cĩ thêm một trường bổ sung nằm ở 4 byte đầu tiên trong trường
dữ liệu của nĩ. Trường bổ sung này được gọi là kiểu định dạng (form type) ,
gồm 4 byte kiểu Char. Nĩ cho biết dạng dữ liệu được lưu trữ bên trong file RIFF là gì. Ví dụ, đối với các file Wave trường này sẽ cĩ tên là “WAVE” ,
đối với các file Avi trường này sẽ cĩ tên là “AVI ”
Hình sau minh họa 2 subchunk trong chunk RIFF của file RIFF :
Trường dữ liệu (Data)
SVTH : Bùi Danh Đạt Trang 32
III.2. Cấu trúc file Wave :
Một file wave là một tập hợp các loại chunk khác nhau. Vì file Wave
chính là file RIFF nên chunk đầu tiên sẽ là chunk RIFF. Ngồi ra, cĩ 2 chunk rất quan trọng khơng thể thiếu là chunk Format mơ tả các thơng số của sĩng âm như tốc độ lấy mẫu, số bit lượng tử hĩa, vv... Chunk thứ hai là chunk Data
để chứa dữ liệu âm thanh đã được số hĩa. Các chunk khác tùy trường hợp cĩ
thể cĩ, cĩ thể khơng.
III.2.1. Chunk Format :
Cấu trúc của chunk Format được định nghĩa như sau :
Trước hết chunk Format luơn cĩ tên nhận dạng là “fmt ”. Kích thước
của chunk Format cĩ thể thay đổi tùy theo giá trị của wFormatTag. Giá trị này cho biết chuẩn nén âm thanh. Cĩ hơn 50 chuẩn của
Microsoft và các hãng khác được định nghĩa trong file mmreg.h .
Thơng thường chuẩn PCM (Pulse Code Modulation) của Microsoft
là chuẩn phổ biến nhất. Với chuẩn này, các mẫu âm thanh được lưu
trữ sẽ khơng được nén và cĩ giá trị được định nghĩa là 1.
wChannels là số kênh âm thanh. Giá trị 1 cho âm thanh mono, 2 cho
âm thanh stereo, 4 cho âm thanh 4 kênh, vv ...
dwSamplesPerSec là tốc độ lấy mẫu, nghĩa là số mẫu được phát
trong một giây, đơn vị là Hertz . Cĩ 3 giá trị thơng dụng là : 11025, 22050 và 44100 Hz mặc dù các tốc độ khác vẫn được dùng. typedef struct { WORD wFormatTag; WORD nChannels; DWORD nSamplesPerSec; DWORD nAvgBytesPerSec; WORD nBlockAlign; WORD wBitsPerSample; WORD cbSize; } WAVEFORMATEX;
SVTH : Bùi Danh Đạt Trang 33
dwAvgBytesPerSec sẽ chỉ ra cĩ bao nhiêu byte được phát mỗi giây.
Nếu là chuẩn PCM thì giá trị này chính là dwSamplesPerSec *
wBlockAlign. Ngược lại, giá trị này phải được tính tốn phù hợp với
chuẩn tương ứng.
wBlockAlign là kích thước của một khung mẫu âm thanh, tính theo
byte. Ví dụ một khung mẫu âm thanh 16-bit mono là 2 byte, 16-bit stereo là 4 byte. Nếu chuẩn là PCM thì giá trị này bằng wChannels *
(wBitsPerSample / 8)
wBitsPerSample cho biết số bit dùng để lượng tử hĩa mỗi điểm lấy
mẫu. Nếu chuẩn là PCM thì giá trị này là 8 hoặc 16. Vì các mẫu phải được lưu dạng BYTE hoặc WORD nên khi lưu trữ vẫn phải lưu hẳn
1 BYTE hoặc 1 WORD. Ví dụ số bit lượng tử hĩa là 12 thì sẽ cĩ 4
bit thừa khơng dùng tới.
cbSize là kích thước của những thơng tin mở rộng thêm được thêm
vào cuối cấu trúc WAVEFORMATEX. Thơng tin này được dùng khi chuẩn khác PCM. Với chuẩn PCM thì giá trị này bẳng 0
III.2.2. Chunk Data :
Sau chunk Format là chunk Data. Chunk này chỉ đơn giản chứa các
mẫu âm thanh đã được số hĩa. Tùy theo số kênh được chọn và số bit dùng để lượng tử hĩa mà các mẫu âm thanh này được sắp xếp khác nhau trong chunk
Data. Cĩ 2 khái niệm về điểm mẫu và khung mẫu
Một điểm mẫu chính là một giá trị đại diện cho một mẫu âm thanh được lấy tại một thời điểm nào đĩ. Nếu số bit dùng để lượng tử hĩa là 8 thì giá trị của một điểm mẫu dao động từ 0 đến 255. Nếu số bit dùng để lượng tử hĩa
là 16 thì giá trị của một điểm mẫu dao động từ đến -32768 đến 32767. Đối với
âm thanh cĩ nhiều kênh, các điểm mẫu từ mỗi kênh sẽ được xếp xen kẽ. Ví dụ
với âm thanh stereo, các điểm mẫu sẽ được lưu trữ như sau : mẫu đầu tiên của
kênh trái rồi tới mẫu đầu tiên của kênh phải, tiếp đĩ là mẫu thứ hai của kênh trái rồi tới mẫu thứ hai của kênh phải, ... và cứ như thế.
SVTH : Bùi Danh Đạt Trang 34
Một khung mẫu bao gồm nhiều điểm mẫu được phát đồng thời. Ví
dụ, với âm thanh stereo, 2 điểm mẫu thuộc 2 kênh sẽ tạo thành một khung mẫu
Khung mẫu 1 Khung mẫu 2 Khung mẫu N
Kênh 1 Kênh 2 Kênh 1 Kênh 2 ... Kênh 1 Kênh 2
= 1 điểm mẫu
Với âm thanh mono thì mỗi khung mẫu chỉ cĩ 1 điểm mẫu. Đối với âm thanh
cĩ nhiều kênh thì tùy theo số lượng kênh mà các thứ tự của các điểm mẫu
trong một khung mẫu sẽ khác nhau :
1 2
Stereo Trái Phải
1 2 3
3 kênh Trái Phải Giữa
1 2 3 4 Quad Trái - Trước Phải - Trước Trái - Sau Phải - Sau 1 2 3 4
4 kênh Trái Giữa Phải Surround
1 2 3 4 5 6
6 kênh Giữa -
Trái Trái Giữa
Giữa -
SVTH : Bùi Danh Đạt Trang 35
Tĩm lại cấu trúc file Wave được mơ tả như bảng sau :
Mơ tả Kích thước Giá trị thơng thường
Tên của chunk RIFF
(RIFF chunk ID) 4 byte “RIFF”
Kích thước chunk RIFF
(RIFF chunk size) 4 byte Kích thước file RIFF - 8
Định dạng của file RIFF
(Form type) 4 byte "WAVE"
Tên của chunk Format
(Format chunk ID) 4 byte “fmt “
Kích thước chunk Format
(Format chunk size) 4 byte 16
Chuẩn của file Wave
(wFormatTag) 2 byte PCM = 1 Số kênh (wChannels) 2 byte mono = 1 stereo = 2 Tốc độ lấy mẫu (dwSamplesPerSec) 4 byte 11025 Hz, 22050 Hz, 44100 Hz Số byte/1 giây (dwAvgBytesPerSec) 4 byte dwSamplesPerSec * wBlockAlign
Kích thước khung mẫu
(wBlockAlign) 2 byte
wChannels * (wBitsPerSample / 8) Số bit lượng tử hĩa
(wBitsPerSample) 2 byte
8 16 Tên của chunk Data
(Data chunk ID) 4 byte "data"
Kích thước chunk Data
(Data chunk size) 4 byte
wBlockAlign * Tổng số
khung mẫu
SVTH : Bùi Danh Đạt Trang 36
IV. Các phương pháp phát một file Wave : IV.1. Dùng hàm sndPlaySound hoặc PlaySound :
Windows cung cấp 2 hàm sau để phát một file wave : sndPlaySound và PlaySound . Hai hàm này tuy gọn, nhẹ, đơn giản nhưng sẽ nạp toàn bộ dữ liệu
âm thanh vào bộ nhớ, và cũng vì vậy mà kích thước của file sẽ bị giới hạn đến
100 KB. Ngồi ra, hai hàm này cũng địi hỏi định dạng của dữ liệu âm thanh
phải được nhận biết bởi trình điều khiển âm thanh và chỉ phát ra soundcard.
IV.2. Dùng MCI (Media Control Interface) :
Các hàm của MCI được chứa trong thư viện Winmm.lib của Windows. Các khai báo đặc tả liên quan được cung cấp trong 2 file Mmsystem.h và Windows.h
Để phát một file Wave cĩ kích thước lớn hơn, Windows cung cấp một
giao tiếp MCI (Media Control Interface). Đây là một giao tiếp rất mạnh thực
hiện cơng việc giao tiếp giữa ứng dụng và thiết bị âm thanh để thu hoặc phát
rất nhiều loại file âm thanh như : phát các bản nhạc từ CD Audio, các file
Wave, Midi, Video, vv...
MCI là tập hợp các hàm, mỗi hàm cĩ một chức năng riêng biệt. Điều đặc
biệt là MCI sử dụng các chuỗi lệnh để nhận biết cơng việc cần làm. Ví dụ,
hàm mciSendString() sẽ gửi các chuỗi lệnh sau để phát 10000 mẫu âm thanh :
mciSendString(
"open c:\Sound\MyWave.wav type waveaudio alias finch", lpszReturnString, lstrlen(lpszReturnString), NULL);
mciSendString("set finch time format samples", lpszReturnString, lstrlen(lpszReturnString), NULL);
mciSendString("play finch from 1 to 10000", lpszReturnString, lstrlen(lpszReturnString), NULL);
mciSendString("close finch", lpszReturnString, lstrlen(lpszReturnString), NULL);
IV.3. Dùng các hàm cấp thấp của Windows :
Các hàm này được chứa trong thư viện Winmm.lib của Windows. Các khai báo đặc tả liên quan được cung cấp trong 2 file Mmsystem.h và Windows.h
SVTH : Bùi Danh Đạt Trang 37
4 hàm chính sau đây sẽ luơn được dùng để điều khiển việc phát một file
Wave :
waveOutOpen()
waveOutPrepareHeader() waveOutWrite()
waveOutClose()
Trong đĩ, hàm waveOutOpen() sẽ yêu cầu cung cấp địa chỉ của một hàm
gọi là CallBack. Hàm CallBack này sẽ cho biết một trong 3 sự kiện liên quan
sẽ xảy ra , và 3 sự kiện này tương ứng với 3 thơng điệp sau được gửi đến hàm
CallBack :
MM_WOM_OPEN Được gửi khi thiết bị được mở bằng hàm
waveOutOpen()
MM_WOM_DONE
Được gửi khi thiết bị đã phát xong khối dữ
liệu âm thanh mà được gửi đi bằng hàm
waveOutWrite()
MM_WOM_CLOSE Được gửi khi thiết bị được đĩng bằng hàm
waveOutClose()
Ngồi ra, hàm waveOutOpen() cịn địi hỏi một số tham số quan trọng như :
mã nhận dạng thiết bị âm thanh, handle của thiết bị sau khi mở, con trỏ tới
một cấu trúc mơ tả file Wave. Để chọn thiết bị âm thanh mặc định, ta dùng hằng WAVE_MAPPER thay cho mã nhận dạng thiết bị âm thanh.
Hàm waveOutPrepareHeader() sẽ tạo ra một header cho khối dữ liệu âm
thanh sẽ phát bao gồm cả các mẫu âm thanh đã được nạp vào bộ nhớ.
Cuối cùng, hàm waveOutWrite() sẽ bắt đầu gửi khối dữ liệu âm thanh
này ra thiết bị để phát với header đĩ.
Sau khi phát xong, ta phải gọi hàm waveOutClose() để đĩng thiết bị đã mở nhằm giải phĩng tài nguyên hệ thống.
Tất cả các hàm liên quan đến cơng việc phát âm thanh này đều hoạt động
SVTH : Bùi Danh Đạt Trang 38
Nhận xét chung về 3 cách phát file Wave :
- Theo thứ tự của 3 cách nêu trên thì tính đơn giản tỷ lệ
nghịch với tính linh động, uyển chuyển trong việc phát một file
Wave, nghĩa là ta muốn nắm quyền kiểm sốt, điều khiển càng nhiều thì phải thực hiện càng nhiều thao tác.
- Trong 3 cách phát file Wave trên thì 2 cách đầu (dùng hàm sndPlaySound, PlaySound hoặc MCI) ta khơng cần quan tâm đến việc đọc file Wave và nạp các mẫu âm thanh vào bộ
nhớ. Riêng cách thứ ba thì điều này là bắt buộc. Phần dưới đây sẽ nĩi sơ về cách đọc dữ liệu âm thanh vào bộ nhớ trước khi gọi các hàm đĩ.
V. Cách đọc file Wave vào bộ nhớ :
Để thao tác với file Wave, Windows cung cấp hàng loạt các hàm được chứa trong thư viện Winmm.lib. Sau đây là một số hàm chính thực hiện cơng việc đọc file Wave :
Để làm việc với file Wave, ta phải mở file đĩ bằng hàm :
mmioOpen()
Sau đĩ định vị vào chunk ta cần bằng hàm :
mmioDescend()
Lúc này con trỏ file sẽ trỏ vào đầu phần dữ liệu của chunk đĩ và ta sẽ đọc dữ liệu vào bộ nhớ bằng hàm :
mmioRead()
Khi làm việc xong với 1 chunk, trước khi muốn định vị vào một chunk
khác, ta phải ra khỏi chunk cũ bằng hàm :
mmioAscend()
Sau khi hồn tất cơng việc, ta sẽ đĩng file Wave đã mở bằng hàm :
SVTH : Bùi Danh Đạt Trang 39
Trước khi đọc dữ liệu âm thanh vào bộ nhớ, ta nên đọc header của file
Wave trong chunk Format. Từ header này ta sẽ xác định tổng số byte mà bộ
nhớ cần để lưu trữ dữ liệu âm thanh và tiến hành cấp phát bộ nhớ bằng hàm :
GlobalAlloc()
Sau đĩ ta chỉ việc đọc dữ liệu vào vùng nhớ đĩ. Bất cứ lúc nào cần ta
cũng cĩ thể giải phĩng vùng nhớ đĩ bằng hàm :
GlobalFree()
Ngồi ra, nếu ta muốn thay đổi vị trí hiện tại của con trỏ file sau khi đã mở file, ta cĩ thể dùng hàm :
mmioSeek()
VI. Phương pháp thu âm :
Với MCI đã giới thiệu ở phần trên để phát một file Wave, ta cũng cĩ thể dùng MCI để thu âm. Cách thứ hai là dùng các hàm cấp thấp của Windows. Như đã giới thiệu, các hàm này sẽ cho ta sự linh hoạt trong mọi thao tác.
Trước hết ta phải mở thiết bị âm thanh bằng hàm :
waveInOpen()
Tương tự như khi phát, ta phải cung cấp địa chỉ của một hàm gọi là hàm
CallBack mà sẽ phát ra các sự kiện liên quan đến quá trình thu âm. Các thơng
điệp tương ứng với các sự kiện này là :
MM_WIM_OPEN Được gửi khi thiết bị được mở bằng hàm
waveInOpen()
MM_WIM_DATA Được gửi khi thiết bị hoàn tất việc thu âm
sau khi gọi hàm waveInStart()
MM_WIM_CLOSE Được gửi khi thiết bị được đĩng bằng hàm
waveInClose()
Ngồi ra, ta cũng cần cung cấp mã nhận dạng thiết bị âm thanh và một cấu
trúc mơ tả các thơng số định dạng của file Wave. Để chọn thiết bị âm thanh
mặc định, ta dùng hằng WAVE_MAPPER thay cho mã nhận dạng thiết bị âm
SVTH : Bùi Danh Đạt Trang 40
Một việc khác khơng thể thiếu là cấp phát bộ nhớ để lưu các mẫu âm thanh thu được. Dựa vào các thơng số được mơ tả trong cấu trúc file Wave, ta
phải tính tốn dung lượng bộ nhớ tối thiểu cần được cấp phát trong một
khoảng thời gian nào đĩ. Cụ thể là :
dwAvgBytesPerSec * thời gian thu âm
Kế đĩ, ta sẽ tạo ra header file sẽ thu âm bao gồm cả vùng nhớ vừa cấp
phát bằng hàm :
waveInPrepareHeader()
Sau đĩ ta sẽ gửi những thơng tin này đến thiết bị thu âm bằng hàm :
waveInAddBuffer()
Cuối cùng, quá trình thu âm sẽ được bắt đầu bằng hàm :
waveInStart()
SVTH : Bùi Danh Đạt Trang 41 PHẦN 3 T THHIIẾẾTT KKẾẾ H HỆỆ TTHHỐỐNNGG
SVTH : Bùi Danh Đạt Trang 42
Chương 1
SƠ ĐỒ HOẠT ĐỘNG CỦA HỆ THỐNG
I. Lưu đồ giải thuật :
Nếu nhìn một cách tổng quát thì chương trình sẽ gồm 4 giai đoạn chính :
Kết nối cuộc gọi tới
Tiếp nhận yêu cầu của người gọi
Tìm dữ liệu trong máy tính
Thơng báo kết quả tìm được
Dưới đây là lưu đồ hoạt động tổng quát của chương trình :
Bắt đầu
Chuơng reo Kết nối
Cĩ phím bấm Tìm dữ liệu Thơng báo kết quả F
T
T F
SVTH : Bùi Danh Đạt Trang 43
II. Sơ đồ luồng hoạt động của hệ thống :
Sau khi cuộc gọi đã được kết nối với máy tính, hệ thống sẽ ở một trong
11 trạng thái sau đây :
Trạng thái Ý nghĩa
MENU Đang thơng báo các mục trong menu
MASO Đang nhận vào mã số học sinh
NGHIHOC Đang lấy ra thơng tin về các lần nghỉ học của học sinh
VIPHAM Đang lấy ra thơng tin về các lần vi phạm nội quy của
học sinh
KQKIEMTRA Đang lấy ra kết quả của các lần kiểm tra trong tháng
KQTHI Đang lấy ra kết quả thi học kỳ
KQTHANG Đang lấy ra kết quả cuối tháng
KQHOCKY Đang lấy ra kết quả cuối học kỳ
KQNAMHOC Đang lấy ra kết quả cuối năm học
HOCSINH Đang lấy ra thơng tin chi tiết về học sinh
NAMHOC Đang chọn năm học
Dựa vào các trạng thái này mà hệ thống biết được cơng việc hiện tại cần
thực hiện là gì. Hoạt động của hệ thống được mơ tả qua sơ đồ dưới đây :
Mỗi hình elip tượng trưng cho một thủ tục để thực hiện cơng việc