IV.1 MƠI TRƯỜNG LẬP TRÌNH SDK ĐỐI VỚI TRUYỀN ÂM THANH

Một phần của tài liệu Đồ án xây dựng thử nghiệm một hệ thống cho phép trao đổi thông tin bằng tiếng nói thoại, tương tác điểm – điểm trên mạng LAN (Trang 37 - 57)

Mơi trường Windows SDK là mơi trường lập trình đa phương tiện dưới Windows, cung cấp các hàm cấp thấp rất thích hợp cho các ứng dụng trên mạng. Một cách thức đơn giản nhất trong việc xuất dữ liệu waveform ra loa là dùng hàm PlaySound. Chúng ta cĩ thể thao tác với dạng dữ liệu waveform bằng các hàm cấp thấp do hệ thống cung cấp. Ngồi ra hệ thống cịn cung cấp một cơ chế giúp người lập trình giao tiếp dễ dàng hơn với thiết bị, đĩ là các hàm MCI. [6]

IV.1.1 CẤU TRÚC FILE WAVE VÀ HÀM PLAYSOUND

IV.1.1.1 Cấu trúc file âm thanh wave

Một file wave thật sự là một phần của một lớp file lớn hơn dùng bởi các hàm multimedia của windows là các file RIFF ( Resource Interchange File Format). Một file Riff bao gồm một hoặc nhiều chunk. Trong mỗi chunk cĩ con trỏ chỉ đến chunk kế tiếp. Mỗi chunk cĩ một mơ tả kiểu theo sau bởi một số dữ liệu. Một ứng dụng để đọc các file RIFF cĩ thể bước qua một số chunk, đọc các chunk cần quan tâm và bỏ qua các chunk khơng liên quan. Chunk file RIFF luơn luơn bắt đầu bằng header sau:

Typedef struct {

FOURCC ckID;

DWORD cksize;

}CK; Trong đĩ:

FOURCC là một vùng 4 bytes định nghĩa loại chunk. Vùng này sẽ chứa từ WAVE đối với file wave.

ckSize đặc tả kích thước dữ liệu trong chunk, sau header này chúng ta sẽ tìm thấy cSize bytes dữ liệu.

Các chunk cĩ thể chứa các subchunks. Cấu trúc thật sự một file wave cơ bản bao gồm một chunk fmt theo sau là một chunk dữ liệu. Cĩ thể cĩ những chunk khác phía sau chunk WAVE nhưng thiết bị sử dụng file WAVE sẽ bỏ qua các chunk này. Hình sau mơ tả cấu trúc file RIFF chứa dữ liệu WAVE.

ID SIZE FROM TYPE "fmt" SIZE "data" SIZE

Hai subchunk trong chunk wave đặc tả thơng tin về một âm thanh file wave và sau đĩ là chính dữ liệu âm thanh. Chunk fmt chứa chủ yếu đối tượng WAVEFORMAT và một số dữ liệu thêm vào gắn ở cuối chunk. Một đối tượng WAVEFORMAT được định nghĩa như sau :

Typedef struct waveformar_tag{

WORD wFormatTag; WORD nChannels; DWORD nSamplesPerSec; DWORD nAvgBytesPerSec; WORD nBlockAlign; } WAVEFORMAT;

wFormatTag : Chứa hằng WAVE_FORMAT_PCM được định nghĩa trong MMSYSTEM.H như sau:

# define WAVE_FORMAT_PCM1

Giá trị WAVE_FORMAT_PCM báo cho phần mềm đọc file wave biết cách âm thanh trong nĩ được mã hố.

nChannels : Của đối tượng WAVEFORMAT cĩ 2 giá trị :

 1 đối với âm thanh mono.

 2 đối với âm thanh stereo.

nSamplePerSec : Cho biết tần số lấy mẫu của âm thanh để cĩ thể thu và phát cùng một tốc độ, giá trị thơng thường của field này nhận một những giá trị sau:

11025 - 11,025Khz 22055 - 22,050Khz 44100 - 44,1 Khz

nAvgBytesPerSec : Cho biết số bytes trung bình trong mỗi giây để thu và phát dữ liệu wave.

nBlockAlign : Xác định số bytes yêu cầu chứa trong một mẫu

 Những mẫu cĩ độ phân giải nhỏ hơn hoặc bằng 8 bits cĩ thể lưu vào 1 bytes.

 Những mẫu cĩ độ phân giải từ 9 đến 16 bits yêu cầu 2 bytes. Những mẫu stereo yêu cầu số bytes gấp đơi những mono.

Trong cấu trúc trên khơng định nghĩa số bits thật sự trong một mẫu dữ liệu âm thanh file wave, để định nghĩa số bits trong một mẫu ta dùng cấu trúc sau:

Typedef struct pvmwaveformat_tag{ WAVEFORMAT wf;

WORD wBitsPerSample;

} PCMWAVEFORMAT; Trong đĩ:

wf: Đối với dữ liệu subchunk fmt của một chunk WAVE chúng ta thật sự làm việc với đối tượng PCMWAVEFORMAT.

nBitsPerSample: Xác định số bits thật sự trong một mẫu .

Trong một mẫu mono 8 bits dữ liệu của chunk dữ liệu gồm một chuỗi dài cĩ giá trị 1 byte. Những mẫu stereo được chia ra với byte đầu dùng cho kênh bên trái và byte thứ hai dùng cho kênh bên phải, như vậy mỗi mẫu stereo 8 bits sẽ cần 2 bytes.[6]

Để làm việc với một file RIFF bao gồm các bước sau : Mở file.

Vào chunk cần thiết.

Chuyển con trỏ file vào vị trí bắt đầu dữ liệu của chunk. Hồn tất, ra khỏi chunk.

IV.1.1.2 Hàm Playsound

Chúng ta dùng hàm PlaySound để play dữ liệu dạng waveform hoặc chúng ta cĩ thể dùng hàm sndPlaySound. Tuy nhiên trong mơi trường Win32 thì nên dùng hàm PlaySound.

Hàm PlaySound cho phép chúng ta chỉ định các thơng số nguồn âm thanh theo các cách sau:

• Dùng tên alias khai báo trong file WIN.INI

• Dùng tên file.

• Dùng chỉ số nhận dạng tài nguyên

Waveform-Audio Files

Trong mơi trường Windows, phần lớn các file âm thanh dạng waveform đều cĩ phần mở rơng là .WAV

Ví dụ dưới đây minh họa cho việc phát file âm thanh “AmThanh.WAV” PlaySound("C:\\SOUNDS\\AmThanh.WAV", NULL, SND_SYNC);

Play sound theo các hiện tượng

Hàm PlaySound cịn cho phép chúng ta xuất âm thanh tùy theo một sự kiện nào đĩ xảy ra trong hệ thống như click mouse hay nhấn một phím nào đĩ. Hệ thống sẽ phát âm thanh tùy theo hiệc tượng xảy ra để cảnh báo người sử dụng. Am thanh dạng này được gọi là sound events.

PlaySound("MouseClick", NULL, SND_SYNC);

IV.1.2 GIAO TIẾP AUDIO VỚI BẰNG CÁC DỊCH VỤ CẤP THẤP

Trong phần này chúng ta sẽ khảo sát việc giao tiếp với thiết bị audio bằng các hàm cấp thấp, các hàm này phù hợp với các ứng dụng cần giao tiếp. Các hàm và cấu trúc cấp thấp này đều cĩ prefix là wave.[6]

Thiết bị và dữ liệu

Khi muốn giao tiếp với thiết bị, chúng ta phải mở thiết bị để sử dụng và sau khi sử dụng xong thì phải đĩng thiết bị lại. Trong khi sử dụng chúng ta sẽ truy xuất các tính năng của thiết bị và theo dõi thiết bị thực thi bằng các handles và Identifiers.

IV.1.3 SỬ DỤNG CÁC THIẾT BỊ XUẤT NHẬP, HỖ TRỢ WAVEFORM AUDIO

Chúng ta dùng hàm waveOutOpen để mở thiết bị đầu ra nhằm xuất dữ liệu dạng waveform. Hàm sẽ mở thiết bị waveOut và trả handle về cho ứng dụng. Hệ thống multimedia sẽ hỗ trợ nhiều dạng output dữ liệu khác nhau do đĩ khi mở thiết bị nếu cần chúng ta phải chỉ định rõ thơng số dữ liệu. Ví dụ chúng ta dùng cờ WAVE_MAPPER để xác định thiết bị output sẽ xuất âm thanh dạng waveform.

Dị tìm thiết bị

Windows cung cấp các hàm sau giúp chúng ta xác định các thiết bị trong hệ thống phù hợp cho yêu cầu của mình.

Hàm Chức năng

AuxGetNumDevs Truy xuất số lượng các thiết bị sẵn cĩ trong hệ thống

WaveInGetNumDevs Truy xuất số lượng các thiết bị nhập hỗ trợ waveform audio sẵn cĩ trong hệ thống WaveOutGetNumDev

s

Truy xuất số lượng các thiết bị xuất hỗ trợ waveform audio sẵn cĩ trong hệ thống

Các thiết bị khai báo trong hệ thống được đánh các chỉ số nhận dạng bắt đầu từ 0. Sau khi xác định số lượng các thiết bị sẵn cĩ trong hệ thống, chúng ta cĩ thể dị tìm khả năng của từng thiết bị bằng các hàm sau:

Hàm Chức năng

AuxGetDevCaps Truy xuất khả năng của thiết bị xuất

WaveInGetDevCaps Truy xuất khả năng của thiết bị nhập dạng waveform

WaveOutGetDevCaps Truy xuất khả năng của thiết bị xuất dạng waveform

Các hàm truy xuất này sẽ truy xuất này sẽ lấy các cấu trúc liên quan đến khả năng của thiết bị. Các cấu trúc dưới đây sẽ tương ứng với các hàm liệt kê ở trên:

WaveInGetDevCaps WAVEINCAPS

WaveOutGetDevCaps WAVEOUTCAPS

Thiết bị waveform cĩ khả năng hỗ trợ các dạng format khơng chuẩn. Dạng format khơng chuẩn này được dùng trong cấu trúc WAVEFORMATEX.

Handle và Identifier của thiết bị

Khi mở thiết bị, chúng ta sẽ nhận được handle hay thơng số Identify của thiết bị. Chúng ta sẽ điều khiển thiết bị qua các thơng số này.

Sự khác biệt giữa handle và identify là khĩ thấy nhưng rất quan trọng.

Identitier của thiết bị được chỉ định ngầm định từ số lượng các thiết bị sẵn cĩ trong hệ thống. Identifier sẽ được trả về khi chúng ta dùng các hàm auxGetNumDevs, waveInGetNumDevs, or waveOutGetNumDevs Hàm.

Handle của thiết bị là thơng số trả về của device driver khi chúng ta dùng các hàm waveInOpen hay waveOutOpen.

Waveform-Audio Output Data Types

Các thơng số dưới đây được dùng cho thiết bị waveform output

Cấu trúc Chức năng

WAVEFORMATE X

Cấu trúc dùng chỉ định dạng format thiết bị output/ input

WAVEHDR Cấu trúc dùng làm header cho khối dữ liệu waveform. Cấu trúc được dùng cho cả thiết bị output và input

WAVEOUTCAPS Cấu trúc dị hỏi khả năng của thiết bị output.

Chỉ định dạng format của dữ liệu waveform audio

Khi chúng ta mở thiết bị output bằng hàm waveOutOpen, thơng số pwfx sẽ chỉ định cấu trúc WAVEFORMATEX xác định dạng format của dữ liệu waveform. Đây là cấu trúc mở rơng của cấu trúc WAVEFORMAT.

Ghi dữ liệu waveform

Sau khi mở thiết bị xuất, chúng ta cĩ thể xuất dữ liệu bằng cách gọi hàm waveOutWrite. Hàm sẽ gửi khối dữ liệu âm thanh ra thiết bị xuất. Chúng ta dùng cấu trúc WAVEHDR để chỉ định header của khối dữ liệu được gửi ra. Header này gồm con trỏ tới khối dữ liệu đã lock, chiều dài khối dữ liệu và một số thơng số cờ. Khối dữ liệu phải được prepare trước khi đem ra sử dụng.

Sau khi gửi khối dữ liệu đến thiết bị output, chúng ta phải chờ driver hồn tất việc xử lý khối dữ liệu trước khi giải phĩng nĩ. Khi chúng ta cần gửi nhiều khối dữ liệu liên tục, chúng ta sẽ phải theo dõi việc xử lý hồn tất khối dữ liệu để cĩ thể gửi khối tiếp theo.

PCM Waveform-Audio Data Format

Thơng số lpData trong cấu trúc WAVEHDR sẽ trỏ đến dữ liệu đã được lấy mẫu. Đối với dữ liệu PCM 8-bit, mỗi giá trị lấy mẫu được biểu diễn bằng một số 8 bit khơng dấu. Đối với dữ liệu PCM 16-bit, mỗi giá trị lấy mẫu được biểu diễn bằng một số 16 bit khơng dấu. Bảng dưới đây cho chúng ta thấy các giá trị cao nhất, thấp nhất cũng như giá trị trung bình của dữ liệu PCM:

Data format Maximum value Minimum value Midpoint value

8-bit PCM 255(0xFF) 0 128 (0x80)

16-bit PCM 32,767 (0x7FFF) -32,768 (0x8000) 0

Các gĩi dữ liệu PCM

Thứ tự của dữ liệu thay đổi tùy theo dạng format 8-bit hay 16-bit, stereo hay mono. Bảng dưới đây trình bày các gĩi dữ liệu của các dạng PCM khác nhau:

PCM waveform

Chức năng

8-bit mono Mỗi giá trị lấy mẫu là 1 byte tương ứng một kênh. Các giá trị mẫu xếp theo thứ tự 1, 2, 3, 4 . . .

8-bit stereo Mỗi giá trị lấy mẫu là 2 byte. Các giá trị mẫu xếp theo thứ tự 1, 2, 3, 4 . . . Với mỗi giá trị mẫu byte đầu là kênh 0 (trái) cịn byte sau là kênh 1 (phải). 16-bit mono Mỗi giá trị lấy mẫu là 2 byte. Các giá trị mẫu xếp

đầu là byte thấp của kênh 0 cịn byte sau là byte cao của kênh 0.

16-bit stereo Mỗi giá trị lấy mẫu là 4 byte. Các giá trị mẫu xếp theo thứ tự 1, 2, 3, 4 . . . Với mỗi giá trị mẫu byte đầu là byte thấp của kênh 0 (trái), byte thứ 2 là byte cao của kênh 0, byte thứ 3 là byte thấp của kênh 1 (phải) cịn byte thứ 4 là byte cao của kênh 1.

Đĩng thiết bị waveform-Audio Output

Sau khi thực thi cơng việc xong, chúng ta sẽ gọi hàm waveOutClose để đĩng thiết bị. Khi thiết bị đang thực thi mà gọi hàm này thì lỗi sẽ xảy ra. Nếu chúng ta muốn đĩng thiết bị giữa chừng thì đầu tiên chúng ta nên gọi hàm waveOutReset trước khi đĩng thiết bị. Nhưng trước đĩ cũng cần gọi hàm waveOutUnprepareHeader để unprepare tất cả các khối dữ liệu.

Playing Waveform-Audio Files

Chúng ta cĩ thể dùng các hàm sau đây để xuất dữ liệu dạng âm thanh ra loa:

thống hay là nội dung của một file wave

PlaySound Giống như hàm trên và thêm cơ chế truy xuất trực tiếp tài nguyên.

Các hàm PlaySound và sndPlaySound sẽ nạp hồn tồn nội dung file wave vào bộ nhớ và xuất ra ngõ output. Khả năng bộ nhớ của chúng cĩ giới hạn nên chúng chỉ quản lý được các nội dung dưới 100KB. Khi làm việc với các file cĩ nội dung lớn hơn thì chúng ta cĩ thể sử dụng các dịch vụ do MCI cung cấp.

Sử dụng Windows message trong việc quản lý khi playback

Các Thơng báo dưới đây cĩ thể được sử dụng trong quá trình xuất dữ liệu:

Thơng báo Chức năng

MM_WOM_CLOS E

Được gửi đi khi đĩng thiết bị bằng hàm waveOutClose

MM_WOM_DONE Được gửi đi sau khi driver hồn tất việc xuất dữ liệu bằng hàm wafveOutWrite.

MM_WOM_OPEN Được gửi đi khi thiết bị được mở bằng hàm waveOutOpen.

Các thơng số wParam và lParam cũng rất cần thiết. Thơng số wParam luơn luơn xác định handle của thiết bị waveform-audio. Đối với thơng số lParam, Thơng báo MM_WOM_DONE dùng thơng số này trỏ tới cấu trúc WAVEHDR chỉ định sụ hồn tất của dữ liệu trong khi thơng số này khơng được

hai Thơng báo cịn lại dùng. Việc dùng này rất hữu hiệu, Thơng báo MM_WOM_DONE sẽ là tín hiệu được báo về sau khi việc playback khối dữ liệu hồn tất. Ta sẽ tiếp nhận Thơng báo này và giải phĩng các biến cĩ liên quan.

Thay đổi volume của quá trình playback dữ liệu waveform audio

Chúng ta sẽ dùngcác hàm sau đây để lấy thơng số volume cũng như thiết lập các thơng số này theo yêu cầu.

Hàm Chức năng

WaveOutGetVolume Truy xuất mức volume của thiết bị xuất WaveOutSetVolume Thiết lập mức volume cho thiết bị

Giá trị volume là một số doubleword. Khi audio format là stereo, 16 bit cao chỉ giá trị volume của channel phải và 16 bits thấp chỉ giá trị volume của channel trái. Cịn nếu ở các thiết bị khơng hỗ trợ 2 kênh thì 16 bit thấp sẽ được sử dụng chỉ giá trị volume cịn 16 bit cao sẽ khơng dùng đến.

Giá trị volume thay đổi từ giá trị 0x0 (silence) cho đến mức 0xFFFF (maximum)

Recording Waveform Audio

Chúng ta cĩ thể sử dụng dịch vụ thu âm thanh theo chuẩn MCI. Tuy nhiên nếu thấy cần thiết, chúng ta cĩ thể sử dụng các hàm thu âm thanh cấp thấp.

Các thơng số dữ liệu dưới đây sẽ đặc trưng cho dạng dữ liệu waveform audio input

Structure Chức năng

HWAVEIN Handle của thiết bị input

WAVEFORMATEX Cấu trúc của dạng dữ liệu được thiết bị input hỗ trợ

WAVEHDR Cấu trúc dùng làm header của khối dữ liệu input. Nĩ cũng được dùng khi xuất dữ liệu ra Output

WAVEINCAPS Cấu trúc dùng dị hỏi các khả năng của thiết bị input

Trước khi bắt đầu cơng việc thu dữ liệu, chúng ta phải dùng hàm waveInGetDevCaps để dị hỏi khả năng cũng như xác định các thuơc tính của thiết bị. Hàm sẽ trả về cấu trúc WAVEINCAPS xác định các thơng số mong muốn.

Opening Waveform-Audio Input Devices

Để thu dữ liệu, trước hết chúng ta dùng hàm waveInOpen để mở thiết bị waveform input. Nếu thực thi thành cơng, hàm sẽ trả về cho chúng ta handle của thiết bị.

Sau khi mở thiết bị, chúng ta cĩ thể tiến hành việc thu dữ liệu. Dạng dữ liệu waveform thu được sẽ được đưa vào buffer, buffer này được trỏ đến trong cấu trúc WAVEHDR. Trước khi được sử dụng, chúng ta phải prepare buffer này.

Windows cung cấp cho chúng ta các hàm sau đây dùng thu dữ liệu waveform:

Hàm Chức năng

WaveInAddBuffer Gửi một buffer cho device driver, thiết bị sẽ thu dữ liệu vào khối này

WaveInReset Ngừng thu dữ liệu và đánh dấu tất cả các buffer đã thu xong

WaveInStart Bắt đầu thu dữ liệu. WaveInStop Kết thúc việc thu dữ liệu

Chúng ta dùng hàm waveInAddBuffer để gửi các khối buffer tới device driver. Khi dữ liệu được điền đầy vào buffer, ứng dụng sẽ được thơng báo bằng window Thơng báo, callback Thơng báo, thread Thơng báo, hay event, tùy theo cờ thơng báo được chỉ định trong hàm open device.

Trước khi bắt đầu thu dữ liệu, chúng ta phải gửi ít nhất một buffer dữ liệu cho thiết bị input và khi đĩng thiết bị, chúng ta gọi hàm waveInReset để đánh dấu các buffer đã được thu xong.

Thơng báo Chức năng MM_WIM_CLOS

E

Được gửi đi khi thiết bị đĩng lại khi gọi hàm

Một phần của tài liệu Đồ án xây dựng thử nghiệm một hệ thống cho phép trao đổi thông tin bằng tiếng nói thoại, tương tác điểm – điểm trên mạng LAN (Trang 37 - 57)

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

(120 trang)
w