Tổng hợp tiếng nói bằng phương pháp tổng hợp trực tiếp

Hệ điều hành Windows cung cấp rất nhiều cơ chế để truy nhập và điều khiển các thiết bị có chức năng thu/phát âm thanh như sound card, modem. Tùy theo yêu cầu mà người lập trình có thể chọn các cách tiếp cận khác nhau từ mức thấp đến mức cao và từ đơn giản đến phức tạp. Dưới đây sẽ trình bày một số phương pháp điều khiển các thiết bị thu/ phát âm thanh trong Windows.

doc11 trang | Chia sẻ: oanh_nt | Lượt xem: 1166 | Lượt tải: 0download
Nội dung tài liệu Tổng hợp tiếng nói bằng phương pháp tổng hợp trực tiếp, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Xử lý tiếng nói Đề số 7: TỔNG HỢP TIẾNG NÓI BẰNG PHƯƠNG PHÁP TỔNG HỢP TRỰC TIẾP Nội dung Mục đích của đồ án Tìm hiểu phương pháp tổng hợp tiếng nói bằng phương pháp trực tiếp, với đơn vị ghi âm là từ và tổ hợp từ. Yêu cầu Thực hiện ghi âm với micro và tái tạo lại tín hiệu ở loa của máy tính PC. Ghép các từ và tổ hợp từ đã ghi âm thành câu có nghĩa sao cho chất lượng tốt nhất. Yêu cầu từ các từ đã ghi âm sẵn “đây”, “là”, “phương pháp”, “tổng hợp”, “trực tiếp” thực hiện tổng hợp thành câu “Đây là phương pháp tổng hợp trực tiếp”. Hiển thị tín hiệu tiếng nói vừa tổng hợp được. Các nội dung đã tìm hiểu và thực hiện Hoạt động thu/phát âm thanh trong Windows Hệ điều hành Windows cung cấp rất nhiều cơ chế để truy nhập và điều khiển các thiết bị có chức năng thu/phát âm thanh như sound card, modem. Tùy theo yêu cầu mà người lập trình có thể chọn các cách tiếp cận khác nhau từ mức thấp đến mức cao và từ đơn giản đến phức tạp. Dưới đây sẽ trình bày một số phương pháp điều khiển các thiết bị thu/ phát âm thanh trong Windows. Phương pháp sử dụng thư viện MCI Khái niệm về MCI MCI (Media Control Interface) là một bộ thư viện cấp cao cho phép truy nhập điều khiển các thiết bị multimedia như cd audio, waveform audio, digital video, scanner... MCI cung cấp một giao diện thống nhất và độc lập với thiết bị để thực hiện các hoạt động thu/phát trên tất cả các thiết bị multimedia được hỗ trợ. Giao diện này được thể hiện bởi một tập hợp các hàm chuẩn có dạng mcixxx. Khi sử dụng các hàm MCI, việc play các file âm thanh có định dạng khác nhau như audio cd, video, avi, wave, midi đều theo một dạng thức như nhau. Sử dụng MCI MCI sử dụng hai cách khác nhau để ra lệnh điều khiển các thiết bị multimedia dưới dạng command message và command string command message: giống như cơ chế thông điệp trong Windows, các lệnh được gửi đến thiết bị bởi mã lệnh đồng thời dữ liệu trao đổi với thiết bị là các dữ liệu có cấu trúc xác định tùy theo loại thiết bị và mã lệnh. command string: các lệnh được gửi đến thiết bị dưới dạng các xâu ký tự có nghĩa chẳng hạn như "open digitalvideo". Thực chất thì xâu này cũng được chuyển thành dạng command message rồi mới gửi đến thiết bị tuy nhiên sử dụng các lệnh dạng này sẽ dễ nhớ hơn so với dạng command message. MCI hỗ trợ rất nhiều thiết bị multimedia và việc thao tác là hoàn toàn độc lập với các thíết bị. Các thiết bị được MCI hỗ trợ bao gồm Cdaudio Dat digitalvideo Other Overlay Scanner sequencer Vcr videodisc waveaudio Các hàm MCI cơ bản MCIERROR mciSendCommand: là hàm sử dụng cơ chế command message để ra lệnh cho thiết bị. Để điều khiển thiết bị thực hiện các thao tác khác nhau như open, recording phải truyền cho hàm các tham số tương ứng với thao tác cần thực hiện. MCIERROR mciSendString: sử dụng các xâu ký tự để ra lệnh cho thiết bị. Các hạn chế của MCI: Các hàm mcixxxx là các hàm cấp cao, thao tác không phụ thuộc thiết bị tuy nhiên lại không linh hoạt, không cho phép người sử dụng truy nhập điều khiển trực tiếp quá trình thu/phát âm thanh. Do đó, với những ứng dụng đòi hỏi tính linh hoạt cao thì sử dụng MCI là không thích hợp Phương pháp sử dụng thư viện waveform-audio API Đây là thư viện truy nhập các thiết bị thu/phát âm thanh ở mức thấp cho phép thao tác rất linh hoạt và nhanh chóng. Tuy nhiên sử dụng thư viện waveform-audio API sẽ khó hơn so với sử dụng MCI vì người lập trình phải quản lý hoàn toàn việc cấp phát bộ nhớ cho thiết bị làm việc. Waveform API chia các thiết bị audio thành loại waveIn devices là các thiết bị cho phép thu tín hiệu âm thanh từ bên ngoài thành tín hiệu số lưu trong máy tính. waveOut devices là thiết bị thực hiện biến đổi tín hiệu số thành tín hiệu âm thanh phát ra loa. Ứng với mỗi loại thiết bị đều có các hàm tương ứng là waveInxxxx và waveOutxxxx để thao tác. Nguyên lý hoạt động của các hàm waveIn và waveOut đều giống nhau, chỉ khác nhau ở chiều dữ liệu được chuyển đi. Nếu không tính đến chiều di chuyển luồng dữ liệu là vào hay ra thì hoạt động của các thiết bị được thể hiện như sau: Theo sơ đồ trên,việc quản lý các buffer cho các thiết bị là rất quan trọng để đảm bảo cho các thiết bị multimedia hoạt động bình thường. Có nhiều cách có thể áp dụng nhưng giải pháp được thực hiện trong đồ án là sử dụng các hàm callback. Các thao tác vào ra với file wave Chunk Cấu trúc của file wave thuộc vào lớp file được sử dụng bởi các hàm Multimedia của Windows, cụ thể là: file RIFF (dạng file trao đổi tài nguyên). Một file RIFF gồm một hoặc nhiều chunk, trong mỗi chunk lại chứa con trỏ chỉ đến chunk kế tiếp. Mỗi chunk bao gồm: Loại chunk Dữ liệu theo sau loại chunk đó. Một ứng dụng muốn đọc file RIFF có thể đi qua lần lượt từng chunk, đọc dữ liệu ở 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 file RIFF luôn bắt đầu bằng một header có cấu trúc như sau: typedef struct { FOURCC ckid; DWORD cksize; FOURCC fccType; DWORD dwDataOffset; DWORD dwFlags; } MMCKINFO; Trong đó: Trường ckid: Kích thước 4 byte, xác đinhl loại chunk Mang giá trị “WAVE”, nếu là file WAVE. Chú ý: 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 thêm vào các khoảng trắng. Trong trường FOURCC phân biệt giữa chữ hoa và chữ thườ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 byte. Chunk có thể chứa các subchunk. Subchunk cũng là một chunk. Một file RIFF luôn bắt đầu bằng một chunk loại “RIFF”. Cấu trúc file Wave File Wave bắt đầu là chunk loại “RIFF”. Hai subchunk “fmt” và “data” trong wave chunk đặc tả thông tin về âm thanh của file wave, tiếp đó là dữ liệu của từng subchunk.Cụ thể: a. Subchunk “fmt” Dữ liệu của fmt chunk là đối tượng WAVEFORMAT có cấu trúc như sau: typedef struct { WORD wFormatTag; WORD nChannels; DWORD nSamplesPerSec; DWORD nAvgBytesPerSec; WORD nBlockAlign; WORD wBitsPerSample; WORD cbSize; } WAVEFORMATEX; Trong đó: wFormatTag thường có giá trị là WAVE_FORMAT_PCM được định nghĩa trong tập tin MMSYSTEM.H như sau: #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ã hoá dữ liệu âm thanh sang dữ liệu số là kiểu mã hoá PCM. Hiện nay đây là kiểu mã hoá 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 stereo. nSamplesPerSec: cho biết tốc độ lấy mẫu, có các giá trị: 11025 -- 11.025 kHz 22050 -- 22.050 kHz 44100 -- 44.100 kHz nAvgBytesPerSec: cho biết số byte yêu cầu trung bình trong một 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 hay ít hơn sẽ yêu cầu 1 byte, mẫu 9 đến 16 bit sẽ yêu cầu 2 byte. Nếu âm thanh là stereo thì yêu cầu số byte gấp 2 lần âm thanh mono. Ta thấy trong WAVEFORMAT chưa có thông tin về số bit dùng để lượng tử hoá 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 đó như sau: typedef struct { WAVEFORMAT wf; WORD wBitsPerSample; } PCMWAVEFORMAT; Trong đó: wBitsPerSample: cho biết số bit trong một mẫu dữ liệu. Chú ý: 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ử hoá một mẫu sóng âm thì sẽ phải lưu trữ 4 bit thừa không dùng đến. b. 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ố hoá. Đố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ị trong khoảng 0-255) của các mẫu âm thanh. Đối với mẫu âm thanh 16 bit, mỗi mẫu dữ liệu gồm 2 byte (có giá trị trong khoảng từ -32768 đến 32767). Điều này không có nghĩa là file wave 16 bit sẽ nghe to hơn 256 lần file wave 8 bit, mà nó có nghĩa là âm thanh được lượng tử hoá chính xác hơn, nghe trung thực hơn. Trong mẫu mono 8 bit, dữ liệu của data subchunk gồm chuỗi các giá trị 1 byte. Với stereo 8 bit, mỗi mẫu gồm 2 byte, dữ liệu sẽ được sắp xếp xen kẽ (interleave), với 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 Đọc File RIFF Để làm việc với file RIFF, ta phải mở nó và “descend” vào chunk mà ta cần. Điều này có nghĩa là ta cầ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 ta 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*/ return(0); } Trong đó: Thông số path chứa đường dẫn của file wave. Cờ MMIO_READ báo cho mmioOpen mở file để đọc. Ta 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 thất bại, nó sẽ 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 (mmioDescend(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; Trong đó: Để “đ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ề giá trị 0 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 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 fmt subchunk của nó: MMIOCKINFO mmSub; MmSub.ckid=mmioFOURCC(‘f’,’m’,’t’); if (mmioDescend(h,(LPMMCKINFO)& mmSub,(LPMMCKINFO)& mmParent,MMIO_FINDCHUNK)) { mmioClose(h,0); /* báo lỗi */ return(0); } Đến đây ta đã có thể bắt đầu đọ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); } Trong đó: Đối số đầu tiên của mmioRead là handle của file đang đọc. Đối số thứ hai là con trỏ tới vùng đệm để chứa 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); Trong đó: Đố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 thanh của Wave file vào bộ nhớ. Chú ý rằng giá 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 Tổng hợp các từ đã ghi âm Để thực hiện tổng hợp câu “Đây là phương pháp tổng hợp trực tiếp” phải qua các bước như sau: Hiển thị tín hiệu tiếng nói Các tín hiệu tiếng nói đã ghi âm và tổng hợp được hiển thị ngay trên form bằng cách vẽ liên tiếp các mẫu lên một vùng hiển thị. Các mẫu này được cập nhật khi dịch chuyển thanh trượt ở phía dưới.

Các file đính kèm theo tài liệu này:

  • docXL tiengnoi-7.DOC