PDA

View Full Version : From Delphi 2 VB (Beep API in Win9x with Frequency)


pranab
08-16-2005, 10:23 AM
I made an alarm SW last month which could play alarm through PC speaker, show DayOfWeek and Date at system tray, etc. I don't like to keep my multimedia speaker turned on whole night and I don't like to hover mouse on the system clock everytime I want to see date/day. I didn't found any commercial alarm software with those functionality so I made it myself. But unfortunetly I lost all code due to hard drive crash :( .
I used the beep API. So it could not sound beep at specified frequencies in Win9x. Now I want to rewrite the code. But this time I want to make it Win9x compatible. So I Googled and found nothing except the Sound() function of Turbo C. Then I've found this Delphi code at
http://delphi.about.com/cs/adptips2003/a/bltip0303_3.htm

I've tried to convert it to VB (with a Delphi manual - I don't know Delphi at all) but failed. It would be great help if anyone can convert it to VB. Or atleast Win32 C++, so that it can be compiled in a Win32 dll and can be used as an API.

~~~~~~~~~~~~~~~~~~~~~~~~~
procedure SetPort(address, Value: Word) ;
var
bValue: Byte;
begin
bValue := trunc(Value and 255) ;
asm
mov dx, address
mov al, bValue
out dx, al
end;
end;

function GetPort(address: Word): Word;
var
bValue: Byte;
begin
asm
mov dx, address
in al, dx
mov bValue, al
end;
GetPort := bValue;
end;

procedure Sound(aFreq, aDelay: Integer) ;

procedure DoSound(Freq: Word) ;
var
B: Byte;
begin
if Freq > 18 then
begin
Freq := Word(1193181 div Longint(Freq)) ;
B := Byte(GetPort($61)) ;

if (B and 3) = 0 then
begin
SetPort($61, Word(B or 3)) ;
SetPort($43, $B6) ;
end;

SetPort($42, Freq) ;
SetPort($42, Freq shr 8) ;
end;
end;

procedure Delay(MSecs: Integer) ;
var
FirstTickCount: LongInt;
begin
FirstTickCount := GetTickCount;
repeat
Sleep(1) ;
//or use Application.ProcessMessages instead of Sleep
until ((GetTickCount - FirstTickCount) >= Longint(MSecs)) ;
end;

begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
Windows.Beep(aFreq, aDelay) ;
end
else
begin
DoSound(aFreq) ;
Delay(aDelay) ;
end;
end;

procedure NoSound;
var
Value: Word;
begin
if not (Win32Platform = VER_PLATFORM_WIN32_NT) then
begin
Value := GetPort($61) and $FC;
SetPort($61, Value) ;
end;
end;

{
// Example:

procedure TForm1.Button1Click(Sender: TObject) ;
begin
Sound(500, 1000) ;
Sound(700, 1000) ;
Sound(900, 1000) ;
NoSound;
end;
}
~~~~~~~~~~~~~~~~~~~~~~~~~

MiguelS
08-16-2005, 10:37 AM
Private Declare Function Beep Lib "kernel32" (ByVal dwFreq As Long, ByVal dwDuration As Long) As Long
Private Sub Form_Activate()
'KPD-Team 1999
'URL: http://www.allapi.net/
'E-Mail: KPDTeam@Allapi.net
Dim Cnt As Long
For Cnt = 0 To 5000 Step 10
'play a tone of 'Cnt' hertz, for 50 milliseconds
Beep Cnt, 50
Me.Caption = Cnt
DoEvents
Next Cnt
End Sub

pranab
08-16-2005, 10:46 AM
Thanks MiguelS for your response. But your code will not work in Windows95/98. The Beep API in Win9x doesn't support the arguments. The 'dwDuration' can be replaced with Sleep API I think. But I don't know how to beep at specified frequency.
That's why I want to convert this Delphi code.

Quote from API Guide:

· dwFreq
Windows NT:
Specifies the frequency, in hertz, of the sound. This parameter must be in the range 37 through 32,767 (0x25 through 0x7FFF).
Windows 95:
The parameter is ignored.

· dwDuration
Windows NT:
Specifies the duration, in milliseconds, of the sound.
Windows 95:
The parameter is ignored.

loquin
08-16-2005, 10:53 AM
Offhand, I believe you'll need to download & use PortIO.dll in order to read/write the ports in Windows 9x.

pranab
08-16-2005, 11:06 AM
OK. Downloaded it. Now ? how to do the conversion ? I've tried to convert it to VC++. (Again only following manual and knowledge of C). But the VC++ linker gives me a "Opcode Type Mismatch" (or similar - forgot actually) error near in al, dx

loquin
08-16-2005, 11:47 AM
OK. I haven't used PortIO.Dll in at least 5 years. But, you say you want to implement the Delphi code in VB. So, you need to use the PortIO.Dll calls INSTEAD OF the getport/setport delphi functions, which use inline assembly code.

You'll need to declare the PortIO.DLL functions in VB before you can use them, as you would with any of the Windows API calls.

The PortIO.Dll zip file should have documentation which describes its use.

pranab
08-16-2005, 11:53 AM
Sorry the zip file I've downloaded doesn't have any manual. Can you please send me the url ?

loquin
08-16-2005, 12:13 PM
OK.

Try this one instead.

InOut32.Dll - PORT I/O (http://www.logix4u.net/)

pranab
08-16-2005, 12:30 PM
Thanks ! This site has loads of info I need.

OnErr0r
08-16-2005, 01:11 PM
http://www.xtremevbtalk.com/showpost.php?p=182632&postcount=15

pranab
08-16-2005, 01:28 PM
Hey OnErr0r ! You just stopped me from being a Delphi Guru. ;)
Just kidding. You can't possibly imagine how happy I am ! :D VB crashed when I tried to run your dll and this is the FIRST time in my life I'm happy seeing an application crash. Now I know why that inline assembly didn't work. I'll now reboot to Win98 and try your code.
Many Many Thanks To You

Edit: Works smoothly in Win98 SE ! Thanks again. Thank you too loguin !

Sarackganda
08-31-2005, 02:28 PM
żIs late?... you can make a native Win32 DLL with your Delphi code...
library DelphiSound;

uses
SysUtils,
Windows;

procedure SetPort(address, Value: Word) ;
var
bValue: Byte;
begin
bValue := trunc(Value and 255) ;
asm
mov dx, address
mov al, bValue
out dx, al
end;
end;

function GetPort(address: Word): Word;
var
bValue: Byte;
begin
asm
mov dx, address
in al, dx
mov bValue, al
end;
GetPort := bValue;
end;

procedure Sound(aFreq, aDelay: Integer); stdcall; export;

procedure DoSound(Freq: Word) ;
var
B: Byte;
begin
if Freq > 18 then
begin
Freq := Word(1193181 div Longint(Freq)) ;
B := Byte(GetPort($61)) ;

if (B and 3) = 0 then
begin
SetPort($61, Word(B or 3)) ;
SetPort($43, $B6) ;
end;

SetPort($42, Freq) ;
SetPort($42, Freq shr 8) ;
end;
end;

procedure Delay(MSecs: Integer) ;
var
FirstTickCount: LongInt;
begin
FirstTickCount := GetTickCount;
repeat
Sleep(1) ;
//or use Application.ProcessMessages instead of Sleep
until ((GetTickCount - FirstTickCount) >= Longint(MSecs)) ;
end;

begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
Windows.Beep(aFreq, aDelay) ;
end
else
begin
DoSound(aFreq) ;
Delay(aDelay) ;
end;
end;

procedure NoSound; stdcall; export;
var
Value: Word;
begin
if not (Win32Platform = VER_PLATFORM_WIN32_NT) then
begin
Value := GetPort($61) and $FC;
SetPort($61, Value) ;
end;
end;


exports
Sound,
NoSound;

begin
end.


Using:

Private Declare Sub Sound Lib "DelphiSound.dll" (ByVal aFreq As Integer, ByVal aDelay As Integer)
Private Declare Sub NoSound Lib "DelphiSound.dll" ()


Bye

pranab
08-31-2005, 02:43 PM
Thanks Sarackganda for your response ! :)

Unfortunetly I don't have a Delphi compiler. And the only two languages I know is C and VB . So I tried to convert it into a C dll. But VC++ was giving me the error in the inline assembly. I use Win2K. I didn't know that it was WinNT specific error so I got stumped.
I'm grateful to OnErr0r for rescuing me.