• Thứ Năm, 08/01/2004 10:23 (GMT+7)

    Ứng dụng lập trình Soundblaster

    Từ khi đọc tạp chí PC World VN cho đến nay, tôi nhận thấy có rất nhiều bạn hỏi về làm thế nào để tạo ra đuợc âm thanh qua sound card bằng lập trình Turbo Pascal hay C. Chính vì vậy tôi muốn trao đổi kinh nghiệm nhỏ mà tôi có được cho các bạn yêu thích lập trình.
    Lập trình thông qua sound card có rất nhiều lợi ích: ví dụ bạn muốn đo điện dung, xem dạng sóng tín hiệu điện (chỉ áp dụng cho tín hiệu nhỏ) giống như dao động kế, hoặc tự mình lập trình cho kêu ra loa với dạng sóng có tần số và biên độ mong muốn, hoặc cao hơn có thể lập trình để xử lý nhận dạng tiếng nói...
    Trước khi lập trình, tôi xin nêu một vấn đề cơ sở về biến đổi DA và AD.

    Biến đổi AD (Analog to Digital)

    Thực chất là biến đổi từ tín hiệu tương tự sang tín hiệu số, muốn làm được thì phải tiến hành theo 3 bước được mô hình hoá qua hình vẽ sau:
    Tín hiệu ban đầu là liên tục theo thời gian sẽ được rời rạc hoá tại các thời điểm lấy mẫu khác nhau, sau đó tín hiệu sẽ được làm tròn thành 1 trong 5 mức thông qua bộ lượng tử hoá, và cuối cùng tín hiệu được mã hoá thành các bit nhị phân mà máy tính có thể xử lý được.

    Biến đổi DA (Digital to Analog) 
    Là quá trình biến đổi từ tín hiệu số sang tín hiệu tương tự, các bước được mô hình như sau:
    Như vậy đối với người lập trình công việc cần phải làm là:
    - Biến đổi AD: đọc từ cổng giá trị các bít nhị phân, và giá trị này tỉ lệ thuận với biên độ tín hiệu.
    - Biến đổi DA: chỉ cần ghi ra cổng giá trị nhị phân.
    Lập trình với sound card thông qua 4 cổng địa chỉ cơ sở:
    - Reset 2x6h
    - Đọc dữ liệu 2xah
    - Viết lệnh/dữ liệu thông qua 2xch- Đọc vào bộ đệm trạng thái thông qua cổng 2xch
    - Dữ liệu sẵn sàng 2xeh

    (x=1-> 6 )

    Việc đi sâu vào chi tiết lập trình với soundblaster, nghĩ là không cần thiết nên tôi chỉ đưa ra một thư viện có sẵn, lập trình bằng Pascal mà người viết thư viện này là Mark Feldma.

    {sounds.pas }

    unit sounds ;

    Interface

    function ResetDSP(base : word) : boolean;

    { viết ra speaker mức tương ứng là level}

    procedure WriteDAC(level : byte);

    { đọc từ microphone  }

    function ReadDAC : byte;

    { Bật speaker }

    function SpeakerOn: byte;

    {Tắt speaker }

    function SpeakerOff: byte;

    Implementation

    Uses Crt;

    var DSP_RESET : word;

    DSP_READ_DATA : word;

    DSP_WRITE_DATA : word;

    DSP_WRITE_STATUS : word;

    DSP_DATA_AVAIL : word;

    function ResetDSP(base : word) : boolean;

    begin

    base := base * $10;

    {tính toán địa chỉ cổng }

    DSP_RESET := base + $206;

    DSP_READ_DATA := base + $20A;

    DSP_WRITE_DATA := base + $20C;

    DSP_WRITE_STATUS := base + $20C;

    DSP_DATA_AVAIL := base + $20E;

    {thiểt lập  DSP, và đưa ra khoảng thời gian trễ}

    Port[DSP_RESET] := 1;

    Delay(10);

    Port[DSP_RESET] := 0;

    Delay(10);

    if (Port[DSP_DATA_AVAIL] And $80 = $80) And

    (Port[DSP_READ_DATA] = $AA) then

    ResetDSP := true

    else

    ResetDSP := false;

    end;

    procedure WriteDSP(value : byte);

    begin

    while Port[DSP_WRITE_STATUS] And $80 <> 0 do;

    Port[DSP_WRITE_DATA] := value;

    end;

    function ReadDSP : byte;

    begin

    while Port[DSP_DATA_AVAIL] and $80 = 0 do;

    ReadDSP := Port[DSP_READ_DATA];

    end;

    procedure WriteDAC(level : byte);

    begin

    WriteDSP($10);

    WriteDSP(level);

    end;

    function ReadDAC : byte;

    begin

    WriteDSP($20);

    ReadDAC := ReadDSP;

    end;

    function SpeakerOn: byte;

    begin

    WriteDSP($D1);

    end;

    function SpeakerOff: byte;

    begin

    WriteDSP($D3);

    end;

    end.

    Sau đây là một số chương trình ứng dụng:

    { chương trình đọc một file *.wav và phát ra speaker }

    uses crt,sounds,dos;

    var

       f:file of byte;

       k:byte;

       tenfile:string;

    begin

      {chỉ đọc được file wav không nén }

      writeln(‘Chuong trinh doc mot file *.wav ‘);

      write(‘Ten file *.wav :’ );readln(tenfile);

      assign(f,tenfile);{ mo file}

      reset(f);

      seek(f,54);

    { nhảy con trỏ file đến vị trí 54, tại vị trí này trở đI  se

      có các giá trị được lấy mẫu liên tiếp nhau}

      resetdsp(2);{ x=2, khởi tạo soundblaster }

      speakeron; { bật speaker }

    repeat

       read(f,k);{ đọc từng byte }

       writedac(k);{ viết ra soundblaster từng byte }

       delay(0);{cho thời gian phát ra speaker nhanh chậm tuỳ ý, nếu muốn phát ra speaker thòi gian chuẩn thì phải lập trình IC 8253 để được thời gian trễ cần thiềt, nếu bạn không biết lập trình IC này thì hãy gửi thư hoặc email cho tôi}

    until (port[$60]=1)or(eof(f));

    {kết thúc khi có một phím được ấn hoặc hết file }

    close(f);

    end.

    Một chương trình khác để phát ra một tín hiệu có dạng xung tam giác:

     

    {tamgiac.pas}

    uses crt,sounds,dos;

    var

       f:file of byte;

       k:byte;

     begin

      resetdsp(2);{ x=2, khởi tạo soundblaster}

      speakeron;  {bật speaker }

      k:=0;

    repeat

       k:=k+1;

       writedac(k); {viet tung byte }

       delay(0);

       if k>255 then k:=0;{ lên đến đỉnh cho về 0}

    until (port[$60]=1);

    { kết thúc khi có một phím được ấn  }

    end.

    Dương thanh Hải
    ĐT: (4) 873 0764
    Email: dth04@yahoo.com

    ID: A0203_64