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 (853.9 KB, 156 trang )
Tự Động Hóa Đài 116
ẹm
ẹn
ẹo
ếm
ếp
ều
ỉa
ỉm
ịn
iu
óa
óe
ỏi
ỏm
ỏn
ọt
ội
ốm
ốn
ộp
ởi
ởm
ởn
ợt
ụa
uễ
ũi
ũm
ũn
uy
ưa
ức
ừu
ỵt
ảng
ảnh
ẳng
ẩng
ẻng
ếnh
iếc
iềm
iện
iếu
ính
oạc
oãi
oạn
GVHD:
en
eo
ép
ệm
ệp
ểu
ĩa
ịm
ip
íu
òa
òe
õi
õm
õn
ốc
ổi
ồm
ồn
ốt
ỡi
ỡm
ỡn
ua
úc
uệ
ụi
ụm
ụn
úy
ứa
ực
ứu
ách
ãng
ãnh
ẵng
ẫng
ẽng
ềnh
iệc
iên
iếp
iều
ình
oai
oàm
oản
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
én
éo
ẹp
ễm
ết
ệu
ịa
in
íp
ìu
ỏa
ỏe
ọi
ọm
ọn
ộc
ỗi
ổm
ổn
ột
ợi
ợm
ợn
úa
ục
ui
um
un
úp
ùy
ừa
ừm
ựu
ạch
ạng
ạnh
ặng
ậng
ẹng
ểnh
iểm
iến
iệp
iểu
ỉnh
oái
oạm
oãn
èn
èo
ét
ên
ệt
ia
im
ín
ịp
ỉu
õa
oi
om
on
óp
ôi
óc
ỗm
ỗn
ơi
ơm
ơn
ớp
ùa
uế
úi
úm
ún
ụp
ủy
ửa
ứt
ửu
ang
anh
ăng
âng
eng
ếch
ễnh
iễm
iền
iết
iễu
ĩnh
oại
oan
oáp
Phan Đình Mãi – Nguyễn Thanh Liêm
ẻn
ẻo
ẹt
ến
êu
ía
ím
ìn
ít
ĩu
ọa
ói
óm
ón
ọp
ối
ọc
ộm
ộn
ới
ớm
ớn
ợp
ủa
uề
ùi
ùm
ùn
út
ũy
ữa
ựt
ữu
áng
ánh
ắng
ấng
éng
ệch
ích
iệm
iển
iệt
iệu
ịnh
oài
oán
oát
ẽn
ẽo
êm
ển
ếu
ìa
ìm
ỉn
ịt
oa
oe
òi
òm
òn
ót
ồi
ôm
ôn
ốp
ời
ờm
ờn
ớt
ũa
uể
ủi
ủm
ủn
ụt
ụy
ựa
ưu
ýt
àng
ành
ằng
ầng
èng
ênh
ịch
iếm
iễn
iêu
inh
oác
oải
oàn
oạt
Trang 65
Tự Động Hóa Đài 116
GVHD:
oay
oăm
oằn
oèn
ong
oóc
ộng
uận
uậy
ũng
uối
uồm
uồn
uya
uỷu
ửng
ưởi
ượm
ượn
ướu
iêng
oang
oánh
oắng
uâng
uống
uỵch
uyện
ương
yêng
oáy
oắm
oẳn
oẻn
óng
ông
uân
uất
uẩy
ụng
uồi
uổm
uổn
uyn
uỵu
ững
ượi
ươn
ướp
ưộu
iếng
oáng
oành
oẳng
uếch
uồng
uyên
uyết
ướng
yểng
oạy
oằm
oẵn
oeo
òng
ống
uấn
uật
ung
uốc
uổi
uỗm
uỗn
uýp
ưng
ước
ưỡi
ướn
ượp
yếm
iềng
oàng
oảnh
oẵng
uệch
uổng
uyến
uyệt
ường
oảy
oặm
oắt
oèo
ỏng
ồng
uần
uây
úng
uộc
uỗi
uộm
uộn
uỵp
ừng
ược
ươm
ườn
ướt
yểm
iểng
oảng
oãnh
oong
uênh
uỗng
uyền
uynh
ưởng
Phan Đình Mãi – Nguyễn Thanh Liêm
oắc
oăn
oặt
oét
õng
ổng
uẩn
uấy
ùng
uôi
uôm
uôn
uốt
uýt
ứng
ươi
ướm
ưởn
ượt
yên
iễng
oãng
oạnh
oóng
uềnh
uộng
uyển
uýnh
ưỡng
oặc
oắn
oen
oẹt
ọng
ỗng
uẫn
uầy
ủng
uội
uốm
uốn
uột
uỵt
ựng
ưới
ườm
ưỡn
ươu
yến
iệng
oanh
oăng
oòng
uông
uých
uyễn
uỳnh
ượng
Nhận xét:
Một từ tiếng việt bao gồm 2 phần: phần âm đầu và phần vần. Âm đầu chủ yếu là các phụ âm
trong tiếng việt. Qua nghiên cứu và tìm hiểu thêm, chúng em thấy rằng:
-
ứng với một loại âm đầu ( ở đây chủ yếu là phụ âm ) phần vần ở phía sau sẽ thay
đổi theo một quy luật nào đó so với phần vần chuẩn khi chưa có âm đầu tuỳ theo
cách phát âm của phụ âm. Chẳng hạn :
/t/
/ch/
/am/ t
/am/ ch
nếu đem /ch/ ráp với /am/ t thì tiếng phát ra sẽ không trung thực tức là khi xây
dựng mô hình âm thanh phần vần độc lập với so với âm đầu sẽ không tận dụng được hết
tính phân biệt giữa các từ do sự biến đổi phổ tín hiệu phần vần so với tác động của các âm
đầu khác nhau.
Để tìm ra quy luật biến đổi phổ tín hiệu này đòi hỏi ta phải có máy phân tích phổ và đi vào
lĩnh vực xử lý tiếng nói, ta mới có thể quan sát và phân tích mẫu sóng âm tại từng thời điểm
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
Trang 66
Tự Động Hóa Đài 116
GVHD:
Phan Đình Mãi – Nguyễn Thanh Liêm
nhằm tìm ra quy luật. Tuy nhiên, với phạm vi của đề tài, việc nghiên cứu này là chưa cần
thiết.
3.4. Ghép âm từ hai âm loại 2:
Ví dụ "bằng" được ghép từ [bà]+[ằng]
Phương pháp này gần giống phương pháp trên nhưng phần phụ âm đầu được cắt lấn
sang phần vần. Theo đó, ta sẽ có 28*650 phần phụ âm đầu tương ứng với 650 phần vần.
Trong thực tế, ta có khoảng 1400 phần đầu. Như vậy khối lượng lưu trữ tổng cộng sẽ là:
(1400+650)* 8000 *1 * (1/2) * 0.8 = 6,560,000 bytes
Phương pháp này mắc phải một số khuyết điểm:
− Vị trí cắt lấn sang phần vần khó xác định vì đây là vùng trộn lẫn giữa hai âm.
− Tuy khối lượng lưu trữ là nhỏ so với ghép từ (3 lần) nhưng lớn hơn nhiều so với
ghép âm loại 1 (4 lần).
Khi dùng phương pháp ghép âm thì việc chuẩn bị các âm mất thời gian rất lớn. Việc
chuẩn bị âm được thực hiện thủ công do không thể xác định chính xác vị trí cần cắt. Do đó
nếu phương pháp này có số lượng âm lớn gấp 4 lần thì thời gian và chi phí bỏ ra cũng lớn
gấp 4 lần so với phương pháp ghép âm loại một.
Ngoài ra chất lượng âm của phương pháp này cũng chưa được kiểm nghiệm để có thể
đánh giá ưu điểm về chất lượng so với phương pháp loại 1.
IV. Sơ lược về các dạng file âm thanh dùng trong Card Dialogic
Card Dialogic chơi được hai loại file âm thanh : file wav và file vox. Theo như tìm
hiểu qua tài liệu cung cấp theo card, card Dialogic chơi file vox tốt hơn file wav, nhưng nhà
cung cấp không cung cấp tài liệu về file vox nên chúng em dùng file wav thay thế. Do đó
chúng em phải có những tìm hiểu sơ lược về file wav.
∗ Tìm hiểu sơ lược về file wave:
1. Cấu Trúc Wave File:
∗ RIFF file.
Wave File là tập tin chứa các dữ liệu của mẫu âm thanh đã được số hoá. Phương
pháp số hoá âm thanh hiện nay là phương pháp PCM. Phương pháp này sẽ lấy mẫu âm
thanh với tần số khoảng 11.025 kHz cho đến 44.1 kHz. Mỗi lần lấy mẫu , số liệu này lại
được lượng tử hoá bằng 1 hoặc 2 byte cho một mẫu âm thanh . Như vậy tần số lấy mẫu càng
cao, số byte dùng lượng tử hóa càng nhiều thì âm thanh phát lại càng trung thực, nhưng lại
tăng số byte cần lưu trữ. Với một mẫu âm thanh phát ra trong 1 phút cần phải lưu trữ ít nhất
660 kB. Đó là lý do tại sao các Wave File luôn có kích thước khá lớn so với MIDI File.
Cấu trúc của Wave File thuộc vào lớp file được sử dụng bỡi các hàm Multimedia của
Windows : đó là RIFF file. RIFF là chữ viết tắt của Resource Interchange File Format
( Dạng file trao đổi tài nguyên). Một RIFF file gồm một hoặc nhiều loại chunks, trong mỗi
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
Trang 67
Tự Động Hóa Đài 116
GVHD:
Phan Đình Mãi – Nguyễn Thanh Liêm
chunk lại chứa con trỏ để chỉ đến chunk kế tiếp. Mỗi chunk bao gồm loại chunk vàdữ liệu
theo sau loại chunk đó. Một ứng dụng muốn đọc RIFF file có thể đi qua lần lượt từng
chunk, đọc dữ liệu ở những chunk nó quan tâm và có thể bỏ qua các chunk mà nó không
quan tâm. Một chunk của RIFF file luôn bắt đầu bởi một header có cấu trúc như sau:
Typedef struct
{
FOURCC ckID;
DWORD ckSize;
} CK;
Trường FOURCC có 4 bytes chỉ ra loại chunk. Đối với Wave File, trường này có giá
trị là "WAVE". Nếu loại chunk ít hơn 4 ký tự thì các ký tự còn lại bên phải sẽ được đệm
thêm vào các khoảng trắng. Cần chú ý là các ký tự trong FOURCC có phân biệt chữ hoa và
chữ thuờng.
Trường ckSize chứa kích thước vùng dữ liệu của chunk, vùng dữ liệu này nằm ngay
sau header và có kích thước là ckSize bytes.
Chunk có thể chứa các subchunks. Subchunk cũng là một chunk.
Một RIFF file luôn bắt đầu bằng một chunk loại "RIFF"
∗ Cấu trúc Wave file
Wave file bắt đầu là chunk loại "RIFF"
Hai subchunk trong Wave chunk đặc tả thông tin về âm thanh của wave file và tiếp
đó là dữ liệu của từng subchunk. Đó là subchunk "fmt " và subchunk "data".
+ Subchunk "fmt"
Dữ liệu của "fmt " chunk là đối tượng WAVEFORMAT có cấu trúc như sau:
Typedef struct waveformat_tag
{
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
} WAVEFORMAT;
wFormatTag thường có giá trị là WAVE_FORMAT_PCM được định nghĩa trong
tập tin MMSYSTEM.H như sau:
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
Trang 68
Tự Động Hóa Đài 116
GVHD:
Phan Đình Mãi – Nguyễn Thanh Liêm
#define WAVE_FORMAT_PCM 1
Giá trị này báo cho phần mềm đang đọc Wave File biết kiểu mã hóa dữ liệu âm
thanh sang dữ liệu số là kiểu mã hóa PCM. Hiện nay đây là kiểu mã hóa duy nhất của Wave
File.
nChannels có hai giá trị: bằng 1 cho âm thanh mono và bằng 2 cho âm thanh steréo.
nSamplesPerSec cho biết tốc độ lấy mẫu. Giá trị thông thường của trường này là:
11025 -- 11.025 kHz •
22050 -- 22.05 kHz •
44100 -- 44.1 kHz
nAvgBytesPerSec cho biết số byte trung bình yêu cầu trong 1 giây để phát lại mẫu dữ
liệu của sóng âm.
nBlockAlign cho biết số byte dùng để chứa một mẫu âm thanh. Như vậy, mẫu 8 bit
hoặc ít hơn sẽ yêu cầu 1 byte, mẫu 9 đến 16 bit sẽ yêu cầu 2 bytes. Nếu âm thanh là steréo
thì yêu cầu gấp 2 lần số byte dùng trong âm thanh mono.
Ta thấy trong WAVEFORMAT chưa có thông tin về số bit dùng để lượng tử hóa
một mẫu dữ liệu của sóng âm. Thực tế, Wave File sẽ xác lập số bit dùng cho một mẫu dữ
liệu bằng một trường gắn vào cuối cấu trúc của WAVEFORMAT. Cấu trúc đó có thể được
định nghĩa như sau:
typedef struc pcmwaveformat_tag
{
WAVEFORMAT wf;
WORD wBitsPerSample;
} PCMWAVEFORMAT;
wBitsPerSample cho biết số bit trong một mẫu dữ liệu. Chú ý rằng các mẫu dữ liệu
vẫn phải lưu trữ ở dạng byte hoặc word. Do đó, nếu một Wave File dùng 12 bit để lượng tử
hóa một mẫu sóng âm thì sẽ phải lưu trữ cả 4 bit thừa không dùng đến.
+ Subchunk "data"
Dữ liệu của "data" subchunk của Wave File chứa các số liệu của âm thanh đã được
số hóa. Đối với mẫu âm thanh 8 bit, dữ liệu của "data" subchunk bao gồm các giá trị 1 byte
(có giá trị từ 0 – 255) của các mẫu âm thanh. Đối với mẫu âm thanh 16 bits, mỗi mẫu dữ
liệu gồm 2 bytes (có giá trị từ -32768 tới 32767). Điều này không có nghĩa là file wave 16
bits sẽ nghe to hơn 256 lần file wave 8 bits mà nó có nghĩa là âm thanh được lượng tử hóa
chính xác hơn, nghe trung thực hơn.
Trong mẫu Mono 8 bits, dữ liệu của subchunk "data" gồm chuỗi các giá trị 1 bytes.
Với Stereo 8 bits, mỗi mẫu gồm 2 bytes, dữ liệu sẽ được sắp xếp xen kẻ (interleave), với
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
Trang 69
Tự Động Hóa Đài 116
GVHD:
Phan Đình Mãi – Nguyễn Thanh Liêm
byte đầu (byte chẳn) là mẫu âm thanh của kênh bên trái, byte sau (byte lẻ) là của kênh bên
phải.
Tóm lại cấu trúc của Wave File như sau:
Kích thước (số
bytes)
Giá trị
4 bytes
"RIFF"
4
Kích thước file RIFF
4
"WAVE"
4
"fmt "
4
Kích thước subchunk "fmt "
2
2
Kiểu mã hóa dữ liệu của file
wave
Số kênh: 1 – mono
2 – stereo
4
Số mẫu/1giây
4
Số bytes/1 giây
2
Số bytes/1mẫu
2
Số bits/1mẫu
4
"data"
4
Kích thước dữ liệu
Dữ liệu sóng âm
2. Đọc RIFF files:
Để làm việc với file RIFF, bạn phải mở nó và "descend" vào chunks mà bạn cần.
Điều này có nghĩa là bạn phải định vị được chunk này, rồi chuyển con trỏ file vào đầu khối
dữ liệu của chunk. Khi làm việc xong với 1 chunk, bạn phải "ascend" ra khỏi chunk và
"descend" xuống chunk khác.
Các hàm dùng xử lý RIFF file đều có tiền tố là mmio và làm việc với file handle
dạng HMMIO. Để bắt đầu, ta phải mở file bằng đoạn mã sau:
HMMIO h;
If ((h=mmioOpen(path,NULL,MMIO_READ))==NULL)
{
/* báo lỗi */
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
Trang 70
Tự Động Hóa Đài 116
GVHD:
Phan Đình Mãi – Nguyễn Thanh Liêm
return(0);
}
Thông số path chứa đường dẫn của file wave. Cờ MMIO_READ báo cho
mmioOpen mở file để đọc. Bạn cũng có thể mở nó để ghi bằng thông số MMIO_WRITE
hay cả đọc và ghi bằng thông số MMIO_READWRITE. Nếu mở file thành công,
mmioOpen sẽ trả về một handle loại HMMIO. Nếu mở file thất bại, nó trả về trị NULL. Sau
khi mở file xong, ta bắt đầu định vị WAVE chunk bằng đoạn mã sau:
MMCKINFO mmParent;
mmParent.fccType=mmioFOURCC('W','A','V','E');
if (mioDescend(h,(LPMMCKINFO)&mmParent,NULL,MMIO_FINDRIFF))
{
mmioClose(h,0);
/* báo lỗi */
return(0);
}
Cấu trúc của MMCKINFO chứa các thông tin về chunk. Nó được định nghĩa trong
MMSYSTEM.H như sau:
typedef struct
{
FOURCC ckid;
DWORD cksize;
FOURCC fcctype;
DWORD dwDataOffset;
DWORD dwFlags;
} MMCKINFO;
Để "đi vào" một chunk, ta cho trường ckid của MMCKINFO ở loại chunk mà ta
muốn định vị. Có một macro thực hiện việc này là mmioFOURCC. Sau đó gọi hàm
mmioDescend để định vị chunk. Nếu định vị thành công, hàm này trả về zero và đối tượng
MMCKINFO truyền cho hàm sẽ được điền vào các thông tin về chunk.
Trường cksize định nghĩa kích thước bằng tính bằng byte của chunk.
Đối số thứ ba của mmioDescend là cờ MMIO_FINDRIFF. Cờ này chỉ thị cho
mmioDescend tìm một file có ID là RIFF với loại chunk được xác định bỡi ckid. Nếu muốn
tìm một chunk trong Wave File ta cho cờ này là MMIO_FINDCHUNK.
Sau khi "đi vào" WAVE chunk, ta bắt đầu đi vào subchunk fmt của nó:
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
Trang 71
Tự Động Hóa Đài 116
GVHD:
Phan Đình Mãi – Nguyễn Thanh Liêm
MMCKINFO mmSub;
mmSub.ckid=mmioFOURCC('f','m','t',' ');
if (mmicDescend(h,(LPMMCKINFO)&mmSub,
(LPMMCKINFO)&mmParent,MMIO_FINDCHUNK))
{
mmioClose(h,0);
/* báo lỗi */
return(0);
}
Đến đây ta đã bắt đầu có thể đọc dữ liệu từ Wave File. Đoạn mã sau đọc đối tượng
PCMWAVEFORMAT từ fmt subchunk:
PCMWAVEFORMAT waveformat;
int n;
n=min ((unsigned int)mmSub.cksize, sizeof(PCMWAVEFORMAT));
if(mmioRead(h,(LPSTR)&waveformat,(long)n) !=(long)n)
{
/* báo lỗi */
return(0L);
}
if(waveformat.wf.wFormatTag !=WAVE_FORMAT_PCM)
{
/* báo lỗi */
mmioClose(h,0);
return(0L);
}
Đối số đầu tiên của mmioRead là handle của file đang đọc. Đối số thứ hai là con trỏ xa
trỏ đến vùng đệm để chưá dữ liệu. Đối số thứ ba là số byte cần đọc. Hàm này sẽ trả về số
byte thực sự đọc được.
Sau khi đã đọc nội dung của chunk, ta "đi ra" khỏi chunk để chuẩn bị đọc chunk kế
tiếp:
mmAscend(h,(LPMMCKINFO)&mmSub,0);
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
Trang 72
Tự Động Hóa Đài 116
GVHD:
Phan Đình Mãi – Nguyễn Thanh Liêm
Đối số thứ hai của mmAscend là đối tượng MMCKINFO của chunk mà ta "đi ra".
Đối số thứ ba là đối số giả.
Công việc còn lại là đọc dữ liệu mã hoá mẫu âm thanh của Wave File vào bộ nhớ.
Chú ý rằng gía trị cksize trả về bởi mmioDescend được sử dụng để xác định kích thước
vùng đệm cần cấp phát để chứa dữ liệu.
GLOBALHANDLE wavehandle;
HPSTR wavepointer;
mmSub.ckid=mmioFOURCC('d','a','t','a');
if(mmioDescend(h,(LPMMCKINFO)&mmSub,
(LPMMCKINFO)&mmParent,MMIO_FINDCHUNK))
{
mmioClose(h,0);
/* báo lỗi */
return(0);
}
if((wavehandle=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,
mmSub.cksize))==NULL)
{
mmioClose(h,0);
/* báo lỗi */
return(0);
}
if(wavepointer=(HPSTR)GlobalLock(wavehandle))==NULL)
{
GlobalFree(wavehandle);
mmioClose(h,0);
/* báo lỗi */
return(0);
}
if(mmioRead(h,wavepointer,mmSub.cksize) !=mmSub.cksize)
{
GlobalUnlock(wavehandle);
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
Trang 73
Tự Động Hóa Đài 116
GVHD:
Phan Đình Mãi – Nguyễn Thanh Liêm
GlobalFree(wavehandle);
mmioClose(h,0);
/* báo lỗi */
return(0);
}
GlobalUnlock(wavehandle);
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
Trang 74
Tự Động Hóa Đài 116
GVHD:
Phan Đình Mãi – Nguyễn Thanh Liêm
PHẦN BA
THIẾT KẾ
HỆ THỐNG
SVTH: Nguyễn Hữu Phú – Trần Lê Trung
Trang 75