Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi







Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (1)


Playing sounds thru the built-in PC speakerComponent available for this articleFormat this article printer-friendly!Bookmark function is only available for registered users!
Using inline assembler to play sounds with the built-in PC speaker
Product:
Delphi 3.x (or higher)
Category:
Multimedia
Skill Level:
Scoring:
Last Update:
09/12/2003
Search Keys:
delphi delphi3000 article borland vcl code-snippet inline assembler basm asm built-in PC speaker sound sounds tone tones tune music musical note play frequency duration Beep hertz hz speakersound in out PPI 8255 Programmable Peripheral Interface 8253 8254 Counter Timer chip chips
Times Scored:
9
Visits:
12820
Uploader: Ernesto De Spirito
Company: Latium Software
Reference: Pascal Newsletter #48
Component Download: http://www.latiumsoftware.com/download/p0048.zip
 
Question/Problem/Abstract:
The Windows API Beep can be used to play sounds thru the PC speaker. It takes two parameters: frecuency of the sound in hertz and duration of the sound in miliseconds. The problem with this function is that the parameters are ignored under Windows 95/98/98SE/Me if there is a sound card present, and in this case Beep simply plays the default system sound thru the sound card. So, what if we want to play an arbitrary sound thru the PC speaker under these operating systems?
Answer:



Playing sounds thru the built-in PC speaker


By Ernesto De Spirito


The Windows API Beep can be used to play sounds thru the PC speaker. It takes two parameters: frecuency of the sound in hertz and duration of the sound in miliseconds. The problem with this function is that the parameters are ignored under Windows 95/98/98SE/Me if there is a sound card present, and in this case Beep simply plays the default system sound thru the sound card. So, what if we want to play an arbitrary sound thru the PC speaker under these operating systems if the machine is equipped with a sound card?

We can do it by interfacing with the 8253/8254 Counter/Timer and the
8255 Programmable Peripheral Interface (PPI) chips on the motherboard, by reading and writing thru their ports. We'll make use of some inline assembler for that purpose. For some information about inline assembler, see:


The IN and OUT assembler instructions allow us to read from and write to an I/O port respectively.

To read from a port:

  in accumulator, port

IN reads a byte, word or doubleword from the specified port into the accumulator register, i.e. AL, AX, or EAX for a byte, word or doubleword port respectively. The port number can be a byte constant (0..255) or the DX register (to have access to all I/O ports).

To write to a port:

  out port, accumulator

OUT writes the byte, word or doubleword in the accumulator register to the specified port. Again, the port number can be a byte constant or the DX register.

Here we'll see an example of the use of assembler for reading and writing to I/O ports to program the 8253/8254 Counter/Timer and the 8255 Programmable Peripheral Interface (PPI) chips on the motherboard in order to make the built-in PC speaker play a tone.

The steps to play a tone using those chips are the following:

  1. Prepare the 8253/8254 to receive the frequency. This is done by writing the value $B6 to the Timer Control Register (port $43).

  2. Write the frequency of the sound to the 8253/8254's Frequency Register (port $42). Actually, it's not the frequency in Hertz that we should write to the register, but the result of 1331000 divided into that frequency. First we should write the low order byte of the result, and then the high order byte.

  3. Turn the speaker on and make it use the 8253/8254 Counter/Timer. This is done by turning on the first two bits of Port B of the 8255 PPI (port $61).

  4. Turn the speaker off when the sound should stop. This is done by turning off the second bit of Port B of the 8255 PPI (port $61).


The following inline assembler function implements the steps listed above:

  procedure SpeakerSound(Frequency: word; Duration: longint);
  // Copyright (c) 2003 Ernesto De Spirito
  // Visit: http://www.latiumsoftware.com
  // Plays a tone thru the PC speaker using the 8253/8254
  // Counter/Timer chip and the 8255 Programmable Peripheral
  // Interface (PPI) chip on the motherboard.
  // NOTE: This code won't work under Windows NT/2000/XP. Use Beep.
  asm
    push edx          // Push Duration on the stack (for Sleep)
    mov cx, ax        // CX := Frequency;
    // Prepare the 8253/8254 to receive the frequency data
    mov al, $B6       // Function: Expect frequency data
    out $43, al       // Write to Timer Control Register
    // Compute the frequency data
    mov dx, $14       // DX:AX = $144F38
    mov ax, $4F38     //       = 1331000
    div cx            // AX := 1331000 / Frequency;
    // Send the frequency data to the 8253/8254 Counter/Timer chip
    out $42, al       // Write low byte to the Frequency Address
    mov al, ah        // AL := High byte of AX
    out $42, al       // Write high byte to the Frequency Address
    // Tell the 8255 PPI to start the sound
    in al, $61        // Read Port B of the 8255 PPI
    or al, $03        // Set bits 0 and 1:
                      // bit 0 --> use the 8253/8254
                      // bit 1 --> turn speaker on
    out $61, al       // Write to Port B of the 8255 PPI
    // Wait
    call Sleep        // Sleep(Duration); // requires Windows unit
    // Tell the 8255 PPI to stop the sound
    in al, $61        // Read Port B of the 8255 PPI
    and al, NOT 2     // Clear bit 1 (turn speaker off)
    out $61, al       // Write to Port B of the 8255 PPI
  end;

Sample call:

  procedure TForm1.Button1Click(Sender: TObject);
  var
    i: integer;
  begin
    Randomize;
    for i := 1 to 3 do
      SpeakerSound(Random(900)+100, 200);
  end;

In conclusion, under Windows NT/2000/XP use the API Beep, and under Windows 95/98/98SE/Me use SpeakerSound instead.

In the following article you'll find a class to mimic the PLAY command of GWBASIC to produce music thru the PC speaker:


You can modify the source code to check for the operating system version and to call SpeakerSound instead of Windows.Beep to make the code also work under 95/98/98SE/Me, regardless of whether there is a sound card present or not.


NOTE: Using the PC speaker to make sounds is OBSELETE. Applications should use MIDI or WAVE sounds instead.





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
Useful...
    Alexia Death (Feb 5 2008 3:01PM)

Useful for making audio notices for applications where the user does not always keep eyes on screen.
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
C.A. Longen
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)