Tải bản đầy đủ (.docx) (7 trang)

Thông báo kết quả học tập của học sinh qua điện thoại-TỔ CHỨC TRUY XUẤT VÀ PHÁT FILE TIẾNG NÓI

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (125.08 KB, 7 trang )

TỔ CHỨC TRUY XUẤT VÀ PHÁT FILE TIẾNG
NÓI
Sau khi đã tìm kiếm dữ liệu trong cơ sở dữ liệu , công việc cuối cùng là thông báo kết
quả bằng giọng nói qua điện thoại cho người gọi nghe, tức là chuyển dữ liệu từ dạng chữ,
số sang tiếng nói. Công việc này chủ yếu gồm 2 giai đoạn chính : tìm dữ liệu tiếng nói
tương ứng và phát qua điện thoại . Trước hết, em sẽ giới thiệu về cách tổ chức và lưu trữ
tiếng nói.
I Chọn phương pháp tổng hợp tiếng nói :
Ở phần cơ sở lý thuyết tổng hợp tiếng nói, em đã nêu bốn phương pháp ghép âm,
trong đó đáng chú ý là phương pháp ghép âm loại một và phương pháp ghép từng từ đơn.
Để đảm bảo chất lương âm cho ứng dụng, em dùng phương pháp ghép từ đơn.
II Chọn định dạng (format) cho file tiếng nói :
Có rất nhiều chuẩn khác nhau cho file âm thanh. Tuy nhiên nếu chọn chuẩn cho ra
tiếng nói chất lượng càng cao thì kích thước dữ liệu thu âm cũng sẽ càng lớn. Ở đây, tiếng
nói sẽ được truyền qua điện thoại nên không cần chất lượng cao như các bài nhạc, nhưng
cũng không quá thấp khiến người gọi khó nghe. Sau khi thử nghiệm, em chọn chuẩn với
các thông số như sau :
Kiểu mã hóa PCM
Số kênh 1 (mono)
Tần số lấy mẫu 11025 Hz
Số byte trên 1 giây 11025
Số byte trên 1 mẫu 1
Số bit trên một mẫu 8
IIICách tổ chức file tiếng nói :
Tiếng Việt có khoảng hơn 6000 từ đơn thông dụng. Dù tổ chức như thế nào thì ta
cũng phải thu âm cho từng từ. Ngoài ra còn có một số câu nói sẽ được thu nguyên văn
như : lời chào, lời tạm biệt, lời yêu cầu, thông báo lỗi , vv... Có hai cách tổ chức file tiếng
nói :
1. Tổ chức thành từng file .wav :
Ta sẽ tiến hành thu âm mỗi từ thành một file .wav . Khi cần từ nào thì phát file
.wav tương ứng. Đây là cách bình thường nhất, đơn giản nhất và dễ thực hiện nhất. Với


một file .wav đúng chuẩn thì ta có thể dùng bất kỳ chương trình thu nhạc nào để thu, và lúc
phát thì cũng có rất nhiều điều khiển hoặc hàm để phát file .wav này. Vì thế ta sẽ đỡ mất
thời gian và công sức để lập trình lại.
Tuy nhiên, với số lượng hơn 6000 từ thì đây không phải là cách giải quyết tốt. Lý
do là vì sau khi thu âm xong tất cả, ta sẽ có tổng cộng 6000 file .wav được lưu trên đĩa
cứng, chưa kể một số file .wav để thu các câu nói nguyên văn. Với số lượng lớn các
file .wav như vậy, công việc sao chép hoặc di chuyển sẽ gặp nhiều khó khăn và mất thời
gian, Ngoài ra dung lượng đĩa để lưu trữ sẽ bị lãng phí rất nhiều vì cơ chế cấp phát dung
lượng đĩa theo cluster. Hơn hết, đối với chương trình này thì cách tổ chức này có một
nhược điểm rất lớn, đó là để đọc ra một câu nói, chương trình sẽ phải mở và đóng liên tục
rất nhiều file .wav. Điều này làm cho tiếng nói giữa các từ bị gián đoạn, không liên tục một
cách tự nhiên, đồng thời tốc độ thực hiện cũng chậm đi rất nhiều.
2. Tổ chức thành các file dữ liệu tiếng nói (chỉ lưu trữ các mẫu âm thanh) :
Như đã giới thiệu trong phần cơ sở lý thuyết, mỗi file âm thanh sẽ gồm 2 phần :
phần header và phần dữ liệu (data) . Mặc dù ta phải thu âm từng từ nhưng các lần thu này
đều phải theo một chuẩn nhất định, hay nói cách khác là các thông số trong phần header
phải hoàn toàn giống nhau. Dựa vào đặc điểm này, ta có thể cắt bỏ các header ra, chỉ lưu
trữ các mẫu âm thanh.
Như vậy ta có thể chỉ cần 1 file duy nhất để lưu trữ các mẫu âm thanh này. Tuy
nhiên, kích thước file này sẽ lên tới hàng chục MB. Điều này sẽ làm chậm quá trình đọc
file để phát cũng như sẽ làm chậm quá trình cập nhật hoặc xóa dữ liệu trong file này (tức là
khi thu hoặc xóa 1 từ). Để giải quyết vấn đề này, em chia thành 24 file (*.sam) tương ứng
với 24 chữ cái tiếng Anh. Mỗi file này sẽ chứa dữ liệu của các từ thuộc cùng 1 chữ cái đầu
tiên (ví dụ : “trinh”, “thành” thuộc file T.sam). Với tiếng Việt thì có thêm 1 số chữ cái
riêng như : Đ , Ă , Â , Ê, Ô , Ổ, Ở , Ú, vv.... Đây thực ra chỉ là các chữ cái cơ bản có ghép
thêm dấu vào. Vì vậy, em sắp chúng theo chữ cái cơ bản, tức là “Đ” sẽ thuộc file D.sam ,
“Ă” sẽ thuộc file A.sam, “Ú” sẽ thuộc file U.sam
Song song đó, ta phải tổ chức một bảng chỉ mục (index) cho các từ đã được thu
âm. Bảng chỉ mục này sẽ gồm có 4 mục : từ được thu âm, vị trí bắt đầu (FileOffset) , kích
thước của phần dữ liệu tiếng nói (DataSize) và tên nhóm (chữ cái cơ bản đầu tiên) ứng với

từ này trong file *.sam . Thông thường, bảng chỉ mục này sẽ được tổ chức thành một file
riêng lẻ. Khi cần sẽ mở file này, dùng một thuật toán để tìm kiếm từ đã được thu âm, sau
đó đọc ra giá trị FileOffset , DataSize và tên nhóm tương ứng. Dựa vào 3 giá trị này, ta sẽ
mở file *.sam tương ứng để đọc phần dữ liệu tiếng nói vào bộ nhớ , sau đó phát đi cùng
với một header được quy định trước. Tuy nhiên, ở chương trình này, em sẽ ghép bảng chỉ
mục này vào trong file cơ sở dữ liệu KQHT.mdb . Khi cần ta chỉ việc dùng phương thức
Seek của đối tượng Recordset để tìm từ được thu âm và tiếp tục tương tự như trên.
Với cách tổ chức dữ liệu tiếng nói như thế này, ta đã khắc phục được các nhược
điểm mà cách trên đã mắc phải. Tuy nhiên, mọi công việc từ thu âm, ghi vào file cho đến
đọc file và phát ra âm thanh thì ta phải tự làm lấy, có nghĩa là ta phải viết rất nhiều mã lệnh
để thực hiện. Do đó sẽ mất khá nhiều thời gian và nếu không nghiên cứu kỹ , chương trình
sẽ chiếm nhiều tài nguyên của hệ thống và có thể xảy ra xung đột, tranh chấp tài nguyên
hệ thống với các ứng dụng khác.
Mặc dù vậy, sau khi chạy thử, chương trình hoạt động khá tốt và nhanh hơn. Đây
là cách tổ chức dữ liệu tiếng nói được sử dụng trong chương trình này.
Ngoài ra, còn có thêm một file @.sam chứa dữ liệu của các câu thông báo, lời
chảo . Sở dĩ em chọn tên “@” mà không phải một tên nào khác là vì trong bảng mã ASCII ,
ký tự “@” đứng trước ký tự “A”. Nhờ đó ta có thể đưa vào vòng lặp từ ký tự “@” tới ký tự
“Z” cho một số việc nào đó (ví dụ mở tất cả các file *.sam).
Khi người dùng đang thu lại một số từ nào đó, các file *.sam sẽ bị thay đổi. Vì
vậy, những lúc này, khi có người gọi tới, hệ thống phải thông báo cho người gọi biết hệ
thống đang bận cập nhật dữ liệu. Dữ liệu của câu thông báo này phải để ra một file riêng
(wait.sam). FileOffset và DataSize của khối dữ liệu này cũng được lưu trong bảng chỉ mục
như những khối dữ liệu khác trong các file *.sam .
I. Chọn phương pháp phát và thu tiếng nói :
Vì các dữ liệu tiếng nói được ta tự tổ chức và lưu trữ trong các file *.sam nên để phát
và thu thì ta chỉ có thể sử dụng các hàm multimedia cấp thấp của Windows. Ta sẽ điều
khiển toàn bộ quá trình này, từ việc cấp phát bộ nhớ , định vị khối dữ liệu tiếng nói trong
file *.sam cho đến việc chọn thiết bị âm thanh và phát tiếng nói đi, hoặc thu tiếng nói vào
vùng đệm và lưu vào file *.sam.

II. Đọc dữ liệu tiếng nói vào bộ nhớ :
Để phát một câu nói, ta phải tách câu đó thành các từ đơn lẻ, sau đó tìm dữ liệu tiếng
nói tương ứng của các từ đó rồi phát đi. Tuy nhiên, mỗi lần như thế hệ thống sẽ phải thực
hiện hàng loạt các công việc như khởi tạo và dọn dẹp vùng đệm , mở và đóng thiết bị vào
ra âm thanh. Vì vậy, ở đây em sẽ không phát lần lượt từng từ mà sẽ đọc hết vào bộ nhớ rồi
phát đi một lần. Nhờ đó tốc độ và chất lượng âm thanh được cải thiện đáng kể. Các bước
thực hiện như sau :
- Mở các file *.sam bằng hàm mmioOpen()
- Tách một chuỗi thành các từ đơn
- Kiểm tra nếu từ nào là số thì chuyển thành chữ
- Tìm lần lượt các từ đó trong bảng chỉ mục đồng thời lấy ra 3 giá trị FileOffset ,
DataSize và tên nhóm , nếu từ nào không có thì sẽ bỏ qua.
- Lần lượt đọc vào vùng đệm dữ liệu tiếng nói của từng từ . Vùng đệm này được
tạo ra có kích thước bằng tổng kích thước của các dữ liệu tiếng nói. Để tìm đến đúng offset
trong file *.sam và đọc dữ liệu ra, ta sử dụng 2 hàm thuộc bộ hàm multimedia :
mmioSeek() và mmioRead()
III. Phát dữ liệu tiếng nói từ vùng đệm :
Muốn phát âm thanh đi, ta phải chỉ ra thiết bị mà âm thanh sẽ xuất ra. Ở đây, thiết bị
xuất âm thanh chính là modem. Vậy trước hết, ta phải lấy giá trị ID tương ứng cho cuộc
gọi được kết nối thông qua modem. Cuộc gọi này có handle được lưu giữ ngay khi có tín
hiệu gọi đến, kết hợp với handle của line hiện tại để truyền cho hàm lineGetID(). Giá trị
ID này sẽ thay đổi tương ứng với mỗi cuộc gọi đến. Vì vậy, ta chỉ cần thực hiện việc này
một lần cho mỗi cuộc gọi đến.
Sau khi có ID của thiết bị xuất âm thanh và vùng đệm dữ liệu tiếng nói đã sẵn sàng,
ta lần lượt gọi các hàm waveOutOpen(), waveOutPrepareHeader(), waveOutWrite() để bắt
đầu phát đi cùng với một vài thông số của header đã nêu ở phần 2. Tất cả các hàm này đều
đã được giới thiệu trong phần cơ sở lý thuyết.
IV. Chương trình thu âm :
Mặc dù các từ tiếng Việt cũng như các lời chào và tạm biệt đã được thu âm sẵn trước
khi tới tay người sử dụng, chương trình thông báo kết quả học tập vẫn kèm thêm một

chương trình thu âm nhằm cho phép người dùng thu âm lại nếu cần. Ngoài chức năng thu,
chương trình còn cho phép phát lại hoặc xóa bất cứ từ nào đã thu âm. Nếu một từ đã có mà
ta thu lại thì từ cũ đã thu âm sẽ bị thay bằng từ mới vừa thu âm.
Để thu âm thì người dùng cần trang bị một micro loa nối vào soundcard. Các chức
năng của chương trình thu âm :
1. Thu :
- Các thông số cần cung cấp cho header hoàn toàn giống như đã nêu ở phần 2
- Để điều khiển soundcard dùng để thu âm, ta gọi hàm waveInOpen() với ID
của thiết bị thu âm thanh sẽ được gán bằng hằng WAVE_MAPPER và chương trình sẽ tự
động chọn thiết bị thu âm thanh phù hợp.
- Tiếp đó ta phải tạo ra vùng đệm để lưu trữ các mẫu âm thanh thu được. Vùng
đệm này có kích thước tối đa được tính như sau :
BufferSize = MaxTime * Số mẫu trên 1giây * Số byte trên 1 mẫu

×