Board index » delphi » Produce simple sound using internal speaker

Produce simple sound using internal speaker

I need to be able to produce a (any) simple sound using the systems internal
speaker - regardless of the fact that there might be a soundcard installed.

I can't use the Beep or MessageBeep functions since the sound seems to be
routed to the soundcard (if installed).

I don't need to be able to play complex wave sound; a simple sequence of
single frequencies is all that is needed - but it HAS to come from the
standard internal speaker.

Any suggestions ?

Regards
Johnny Nielsen

 

Re:Produce simple sound using internal speaker


The Help says
"The Beep procedure calls the Windows API MessageBeep with a parameter
of zero."

So essentially they are the same. I'm not sure what Windows.Beep will
give you. You can also try the folowing (found it in a D3 project.

{***********************************************************************
********
  Sounds
************************************************************************
*******}

{ This procedure turns on the PC speaker
  Assembler copied from BP7 crt.pas unit source
  Directly programs the timer chip to produce the tone
  This access is blocked under Windows NT, so do not call on that
platform
  Called by BeepOn

  freq - frequency to use 16..16000Hz }
procedure Sound( freq: Word ); assembler;
asm
  { The first three parameters are passed in EAX, EDX and ECX
    Remaining parameters are pushed on the stack from left to right
    Must preserve EBX EDI ESI and EBP
    Function results returned in EAX

    On entry
      EAX <- freq }

  { ebx is changed below so preserve it first }
  push ebx

  { The cycle time to produce the desired frequency tone is
    $001234DD / hz }

  { Move freq to bx }
  mov  bx, freq

  { Set dx:ax to $001234DD }
  mov  ax, $34DD
  mov  dx, $0012

  { If bx < $12 (18Hz) then skip }
  cmp  dx, bx
  jnb  @002

  { Perform division
    result stored in ax
    remainder stored in dx }
  div  bx

  { Need result in bx as ax is about to be clobbered by in command }
  mov  bx, ax

  { Read value of 8255 PPI port B }
  in   al, $61

  { Test if bits 1 and 0 are both set
    bit 1 = 8253 PIT1 counter 2 out to amplifier switch
    bit 0 = 8253 PIT1 counter 2 gate input }
  test al, 3

  { If both bits set then skip the next bit }
  jne  @001

  { Enable bits 0 and 1 }
  or   al, 3

  { Store new value in 8255 PPI port B }
  out  $61, al

  { Set 8253 PIT1 control word to counter 2, mode 3, binary counting,
    low and high counter bytes following
    $B6  = 10 11 011  0
           SC RW Mode BCD

    SC   = select counter
           10 = counter 2
    RW   = read/write
           11 = low counter followed by high counter
    Mode = PIT counting mode
           011=mode 3 square wave generator
    BCD  = counting format
           0 = binary counting with 16 bits }
  mov  al, $B6
  out  $43, al

  @001:

  { Copy low byte of counter period to 8253 PIT1 counter 2 }
  mov  al, bl
  out  $42, al

  { Copy high byte of counter period to 8253 PIT1 counter 2 }
  mov  al, bh
  out  $42, al

  @002:

  { Restore previously saved ebx value }
  pop ebx
end; {Sound}

{ This procedure turns off the PC speaker
  Assembler copied from BP7 crt.pas unit source
  Directly programs the timer chip to stop producing any tone
  This access is blocked under Windows NT, so do not call on that
platform
  Called by BeepOn and BeepOff }
procedure NoSound; assembler;
asm
  { The first three parameters are passed in EAX, EDX and ECX
    Remaining parameters are pushed on the stack from left to right
    Must preserve EBX EDI ESI and EBP
    Function results returned in EAX }

  { Read value of 8255 PPI port B }
  in   al, $61

  { Turn off bits 1 and 0
    bit 1 = 8253 PIT1 counter 2 out to amplifier switch
    bit 0 = 8253 PIT1 counter 2 gate input }
  and  al, $FC

  { Store new value in 8255 PPI port B }
  out  $61, al
end; {NoSound}

{ This procedure turns the PC speaker on at a particular frequency and
  waits for the duration.  If duration is 0 then this call leaves the
  speaker on and returns immediately
  On NT, this just calls Windows.Beep
  On 95, this programs the timer chip and sleeps

  freq - frequency of beep
  duration - length of beep in ms }
procedure BeepOn( freq, duration: Integer );
begin
  { -1 is documented as meaning continuous asynchronous tone, but
    instead produces a click }

  if duration <= 0 then duration := -1;

  if Win32Platform = VER_PLATFORM_WIN32_NT then
    Windows.Beep( freq, duration )
  else
  begin
    Sound( freq );
    if duration > 0 then
    begin
      Sleep( duration );
      NoSound;
    end; {if}
  end; {else}
end; {BeepOn}

{ This procedure turns the PC speaker off
  On NT, this just calls Windows.Beep
  On 95, this programs the timer chip }
procedure BeepOff;
begin
  if Win32Platform = VER_PLATFORM_WIN32_NT then
    Windows.Beep( 37, 0 )
  else
    NoSound;
end; {BeepOff}

In article <OtNX4.1579$Nv3.24...@news000.worldonline.dk>,
  "Johnny Nielsen" <DONT.WRITE.THISjohn...@image.dk> wrote:

Quote
> I need to be able to produce a (any) simple sound using the systems
internal
> speaker - regardless of the fact that there might be a soundcard
installed.

> I can't use the Beep or MessageBeep functions since the sound seems
to be
> routed to the soundcard (if installed).

> I don't need to be able to play complex wave sound; a simple sequence
of
> single frequencies is all that is needed - but it HAS to come from the
> standard internal speaker.

> Any suggestions ?

> Regards
> Johnny Nielsen

--
DIGITAL PROSPERITY PTY LTD  phone: +61 3 9761-3885
P.O. Box 557                fax:   +61 3 9761-3811
Boronia, Victoria 3155
http://www.luck-e-lotto.com.au

Sent via Deja.com http://www.deja.com/
Before you buy.

Re:Produce simple sound using internal speaker


In article <OtNX4.1579$Nv3.24...@news000.worldonline.dk>, "Johnny Nielsen"

Quote
<DONT.WRITE.THISjohn...@image.dk> writes:
>I need to be able to produce a (any) simple sound using the systems internal
>speaker - regardless of the fact that there might be a soundcard installed.

>I can't use the Beep or MessageBeep functions since the sound seems to be
>routed to the soundcard (if installed).

>I don't need to be able to play complex wave sound; a simple sequence of
>single frequencies is all that is needed - but it HAS to come from the
>standard internal speaker.

>Any suggestions ?

This will work on a non-NT type OS - ie Win95 at least :-

function PortGet(Addr : word) : byte;
{equivalent of D1's Port[Addr]}
begin
  {$IFDEF VER80}  // Delphi 1
  Result := Port[Addr];
  {$ELSE}
  asm
    mov dx, Addr;     in  al, dx;     mov Result, al
  end;
  {$ENDIF}
end;

procedure PortSet(Addr : word; Data : byte);
{equivalent of D1's Port[Addr] := Data}
begin
  {$IFDEF VER80}  // Delphi 1
  Port[Addr] := Data;
  {$ELSE}
  asm
    mov dx, Addr;     mov al, Data;     out dx, al
  end;
  {$ENDIF}
end;

procedure NoSound;
{stops sound from PC}
begin
  PortSet($61, PortGet($61) and $FC);
end;

procedure Sound(NoteFreq : integer);
{sound at NoteFreq frequency from PC's internal speaker}
var
  PortFreq : integer;
  Port61 : byte;
begin
  if NoteFreq = 0 then
    NoSound
  else begin
    PortFreq := 1193181 div NoteFreq;
    Port61 := PortGet($61);  {get current Port 61 setting}
    {stop any current sound}
    NoSound;
    {Enable Speaker Data | Timer 2 gate to Speaker}
    PortSet($61, Port61 or 3);
    {Counter 2 | R/W 0-7 then 8-15 | Square Wave | Bin 16 bit}
    PortSet($43, $b6);
    {start note}
    PortSet($42, byte(PortFreq));
    PortSet($42, byte(PortFreq shr 8));
  end;
end;

Alan Lloyd
alangll...@aol.com

Other Threads