Play different sounds as Quick as DoCmd.Beep (1 Viewer)

killerflappy

Registered User.
Local time
Today, 15:21
Joined
Aug 23, 2017
Messages
50
We use a barcode scan-application witch is made in Access with a lot of VBA.

When there is an error with a scanned barcode the DoCmd.Beep will run.
This works excellent whitout any delay.

But nog I want to add an second sound.
This can be done with http://www.cpearson.com/excel/PlaySound.aspx

So I put at the top of the module for barcode scanning:

Code:
Private Declare Function sndPlaySound32 _
    Lib "winmm.dll" _
    Alias "sndPlaySoundA" ( _
        ByVal lpszSoundName As String, _
        ByVal uFlags As Long) As Long

And then at the place in the code where the sound should play:

Code:
sndPlaySound32 "C:\Windows\Media\Chord.wav", 0&

This works very slow. The barcodes are scanned in a fast way.
The records are shown very slowely. At the end of scanning the records are half way.
With the DoCmd.Beep the records are shown directly.

I played around with SND_SYN, SND_ASYNC and SND_MEMORY.
But the loading of the wav-files takes to much time.

Is there an other way to play more than one sound (DoCmd.Beep) in a fast way?
 
Last edited:

isladogs

MVP / VIP
Local time
Today, 14:21
Joined
Jan 14, 2017
Messages
18,186
This is the code I use in my Countdown Timer example app

If you are using a small wave file there shouldn't be a noticeable delay

Code:
Option Compare Database
Option Explicit

Public Const SND_ALIAS& = &H10000
Public Const SND_ASYNC& = &H1
Public Const SND_FILENAME& = &H20000
Public Const SND_NODEFAULT& = &H2
Public Const SND_NOWAIT& = &H2000
Public Const SND_RESOURCE& = &H40004
Public Const SND_SYNC& = &H0
Public Const SND_LOOP = &H8
Public Const SND_PURGE = &H40
Private Declare Function PlaySound& Lib "winmm.dll" Alias _
        "PlaySoundA" (ByVal lpszName As String, _
         ByVal hModule As Long, _
         ByVal dwFlags As Long)
         
Sub PlayWaveFile()
   PlaySound strSound, 0, SND_LOOP + SND_ASYNC
End Sub

Sub StopWaveFile()
   PlaySound vbNullString, 0, SND_PURGE
End Sub

Then just add PlayWaveFile to the scan event
 

killerflappy

Registered User.
Local time
Today, 15:21
Joined
Aug 23, 2017
Messages
50
This is the code I use in my Countdown Timer example app

If you are using a small wave file there shouldn't be a noticeable delay

Code:
Option Compare Database
Option Explicit

Public Const SND_ALIAS& = &H10000
Public Const SND_ASYNC& = &H1
Public Const SND_FILENAME& = &H20000
Public Const SND_NODEFAULT& = &H2
Public Const SND_NOWAIT& = &H2000
Public Const SND_RESOURCE& = &H40004
Public Const SND_SYNC& = &H0
Public Const SND_LOOP = &H8
Public Const SND_PURGE = &H40
Private Declare Function PlaySound& Lib "winmm.dll" Alias _
        "PlaySoundA" (ByVal lpszName As String, _
         ByVal hModule As Long, _
         ByVal dwFlags As Long)
         
End Sub

Then just add PlayWaveFile to the scan event

Where can I find the meaning of the "Public Const" options?

I also see the Const SND_MEMORY = &H4
lpszSoundName is a memory file of the sound. Not used in VBA/VB6.
But i'm not sure what this does.

There are 10.000 barcode scanned every day.
 

isladogs

MVP / VIP
Local time
Today, 14:21
Joined
Jan 14, 2017
Messages
18,186
Where can I find the meaning of the "Public Const" options?

I also see the Const SND_MEMORY = &H4
lpszSoundName is a memory file of the sound. Not used in VBA/VB6.
But i'm not sure what this does.

There are 10.000 barcode scanned every day.

This may help:

Code:
Declare PtrSafe Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long

'  flag values for uFlags parameter
Const SND_SYNC = &H0         '  play synchronously (default)
Const SND_ASYNC = &H1         '  play asynchronously

Const SND_NODEFAULT = &H2         '  silence not default, if sound not found

Const SND_MEMORY = &H4         '  lpszSoundName points to a memory file
Const SND_ALIAS = &H10000     '  name is a WIN.INI [sounds] entry
Const SND_FILENAME = &H20000     '  name is a file name
Const SND_RESOURCE = &H40004     '  name is a resource name or atom
Const SND_ALIAS_ID = &H110000    '  name is a WIN.INI [sounds] entry identifier

Const SND_ALIAS_START = 0  '  must be > 4096 to keep strings in same section of resource file

Const SND_LOOP = &H8         '  loop the sound until next sndPlaySound
Const SND_NOSTOP = &H10        '  don't stop any currently playing sound
Const SND_VALID = &H1F        '  valid flags          / ;Internal /

Const SND_NOWAIT = &H2000      '  don't wait if the driver is busy

Const SND_VALIDFLAGS = &H17201F    '  Set of valid flag bits.  Anything outside
                                    '  this range will raise an error
Const SND_RESERVED = &HFF000000  '  In particular these flags are reserved

Const SND_TYPE_MASK = &H170007

Taken from the attached text file - not sure where that came from originally
If you want more info I would do a search on the MS developers site

lpszSoundName points to a memory file
I'm guessing that the code allows looping by storing the specified file into memory

The number of scanned items shouldn't be relevant if the file loads quickly & asynchronously
 

Attachments

  • Win32API_PtrSafe.zip
    141 KB · Views: 515

IMyself

Registered User.
Local time
Today, 18:51
Joined
Oct 15, 2019
Messages
30
This is the code I use in my Countdown Timer example app

If you are using a small wave file there shouldn't be a noticeable delay

Code:
Option Compare Database
Option Explicit

Public Const SND_ALIAS& = &H10000
Public Const SND_ASYNC& = &H1
Public Const SND_FILENAME& = &H20000
Public Const SND_NODEFAULT& = &H2
Public Const SND_NOWAIT& = &H2000
Public Const SND_RESOURCE& = &H40004
Public Const SND_SYNC& = &H0
Public Const SND_LOOP = &H8
Public Const SND_PURGE = &H40
Private Declare Function PlaySound& Lib "winmm.dll" Alias _
        "PlaySoundA" (ByVal lpszName As String, _
         ByVal hModule As Long, _
         ByVal dwFlags As Long)
         
Sub PlayWaveFile()
   PlaySound strSound, 0, SND_LOOP + SND_ASYNC
End Sub

Sub StopWaveFile()
   PlaySound vbNullString, 0, SND_PURGE
End Sub

Then just add PlayWaveFile to the scan event

It sounds pretty cool!
but I guess it is for 32bit version, because I used it in my 64bit version and it didnt work and the below part of code got red:

Code:
Private Declare Function PlaySound& Lib "winmm.dll" Alias _
        "PlaySoundA" (ByVal lpszName As String, _
         ByVal hModule As Long, _
         ByVal dwFlags As Long)

is there any trick to modify it for 64bit version ?
 

theDBguy

I’m here to help
Staff member
Local time
Today, 07:21
Joined
Oct 29, 2018
Messages
21,357
It sounds pretty cool!
but I guess it is for 32bit version, because I used it in my 64bit version and it didnt work and the below part of code got red:

Code:
Private Declare Function PlaySound& Lib "winmm.dll" Alias _
        "PlaySoundA" (ByVal lpszName As String, _
         ByVal hModule As Long, _
         ByVal dwFlags As Long)

is there any trick to modify it for 64bit version ?

Hi. The trick is to try and add the PtrSafe keyword in your API declaration.
 

isladogs

MVP / VIP
Local time
Today, 14:21
Joined
Jan 14, 2017
Messages
18,186
Hi

You need to do more than just add PtrSafe for your code to work correctly. See below in red

For info, I've updated the API declarations using conditional compilation to work in both 32-bit & 64-bit in the latest version (1903) of my Countdown Timer app (attached)

The change required to the code posted earlier is:

Code:
'###############################################
'API Checked/Updated by Colin Riddington 05/03/2019
#If VBA7 Then
  [B]  Private Declare PtrSafe Function PlaySound& Lib "winmm.dll" Alias "PlaySoundA" _
        (ByVal lpszName As String, ByVal [COLOR="DarkRed"]hModule As LongPtr[/COLOR], ByVal dwFlags As Long)[/B]
#Else '32-bit Office
    Private Declare Function PlaySound& Lib "winmm.dll" Alias "PlaySoundA" _
        (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long)
#End If
'###############################################

If all your users are running A2010 or later, you only need the part in bold type

NOTE:
The latest version of the Countdown Timer app can also be found on my website: http://www.mendipdatasystems.co.uk/countdown-timer/4594365457 and in sample databases https://www.access-programmers.co.uk/forums/showthread.php?p=1644831#post1644831
 

Attachments

  • CountdownTimer1903.zip
    757.7 KB · Views: 468
Last edited:

IMyself

Registered User.
Local time
Today, 18:51
Joined
Oct 15, 2019
Messages
30
Hi

You need to do more than just add PtrSafe for your code to work correctly. See below in red

For info, I've updated the API declarations using conditional compilation to work in both 32-bit & 64-bit in the latest version (1903) of my Countdown Timer app (attached)

The change required to the code posted earlier is:

Code:
'###############################################
'API Checked/Updated by Colin Riddington 05/03/2019
#If VBA7 Then
  [B]  Private Declare PtrSafe Function PlaySound& Lib "winmm.dll" Alias "PlaySoundA" _
        (ByVal lpszName As String, ByVal [COLOR="DarkRed"]hModule As LongPtr[/COLOR], ByVal dwFlags As Long)[/B]
#Else '32-bit Office
    Private Declare Function PlaySound& Lib "winmm.dll" Alias "PlaySoundA" _
        (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long)
#End If
'###############################################

If all your users are running A2010 or later, you only need the part in bold type

NOTE:
The latest version of the Countdown Timer app can also be found on my website: http://www.mendipdatasystems.co.uk/countdown-timer/4594365457 and in sample databases https://www.access-programmers.co.uk/forums/showthread.php?p=1644831#post1644831

Yesssss! Muchas Gracias Amigo !
but actually I combined your code with killerflappy's to work. it modified to this:
Code:
Private Declare PtrSafe Function sndPlaySound32 _
    Lib "winmm.dll" _
    Alias "sndPlaySoundA" ( _
        ByVal lpszSoundName As String, _
        ByVal uFlags As LongPtr) As Long

and then this:
Code:
sndPlaySound32 "C:\Windows\Media\Chord.wav", 0&
and it worked with no delay as killerflappy said.
 

isladogs

MVP / VIP
Local time
Today, 14:21
Joined
Jan 14, 2017
Messages
18,186
You're welcome.
Whilst add PtrSafe is needed so the project compiles, you always need to use LongPtr for handles such as hWnd or, in this case, hModule.
I've not seen the uFlags variation before so I'm not clear what that is/does.
 

IMyself

Registered User.
Local time
Today, 18:51
Joined
Oct 15, 2019
Messages
30
You know, when using your code, this part:
Code:
Public Const SND_ALIAS& = &H10000
Public Const SND_ASYNC& = &H1
Public Const SND_FILENAME& = &H20000
Public Const SND_NODEFAULT& = &H2
Public Const SND_NOWAIT& = &H2000
Public Const SND_RESOURCE& = &H40004
Public Const SND_SYNC& = &H0
Public Const SND_LOOP = &H8
Public Const SND_PURGE = &H40
gets red! and shows the error of "arrays, Declare statements and.... not allowed as Public members of object modules".
 

IMyself

Registered User.
Local time
Today, 18:51
Joined
Oct 15, 2019
Messages
30
So, After hanging around I did some changes:
deleting the "Public" statement, and modify the PlayWaveFile , the strSound to music path, because it didnt play! and change SND_LOOP to 0 to prevent non-stop sound playing!! :
Code:
Sub PlayWaveFile()
   PlaySound "C:\Windows\Media\Chimes.wav", 0, 0 + SND_ASYNC
End Sub
And it has Absolutely 0 time wait comparing to the previews code !!
in the previews one, the form stops working till the musics plays completely :/
 

IMyself

Registered User.
Local time
Today, 18:51
Joined
Oct 15, 2019
Messages
30
We use a barcode scan-application witch is made in Access with a lot of VBA.

When there is an error with a scanned barcode the DoCmd.Beep will run.
This works excellent whitout any delay.

But nog I want to add an second sound.
This can be done with http://www.cpearson.com/excel/PlaySound.aspx

So I put at the top of the module for barcode scanning:

Code:
Private Declare Function sndPlaySound32 _
    Lib "winmm.dll" _
    Alias "sndPlaySoundA" ( _
        ByVal lpszSoundName As String, _
        ByVal uFlags As Long) As Long

And then at the place in the code where the sound should play:

Code:
sndPlaySound32 "C:\Windows\Media\Chord.wav", 0&

This works very slow. The barcodes are scanned in a fast way.
The records are shown very slowely. At the end of scanning the records are half way.
With the DoCmd.Beep the records are shown directly.

I played around with SND_SYN, SND_ASYNC and SND_MEMORY.
But the loading of the wav-files takes to much time.

Is there an other way to play more than one sound (DoCmd.Beep) in a fast way?

this is what I came along:
You just need to declare this at first:
Const SND_ASYNC& = &H1
or
Public Const SND_ASYNC& = &H1

and then modify your code to this:
Code:
sndPlaySound32 "C:\Windows\Media\Chord.wav", 0 + SND_ASYNC

actually found that the SND_ASYNC job is to prevent to form to wait till the music ends!
 

theDBguy

I’m here to help
Staff member
Local time
Today, 07:21
Joined
Oct 29, 2018
Messages
21,357
So, After hanging around I did some changes:
deleting the "Public" statement, and modify the PlayWaveFile , the strSound to music path, because it didnt play! and change SND_LOOP to 0 to prevent non-stop sound playing!! :
Code:
Sub PlayWaveFile()
   PlaySound "C:\Windows\Media\Chimes.wav", 0, 0 + SND_ASYNC
End Sub
And it has Absolutely 0 time wait comparing to the previews code !!
in the previews one, the form stops working till the musics plays completely :/

Hi. Congratulations! Thanks for the update. You might consider posting a demo file with your changes. Just a thought...
 

isladogs

MVP / VIP
Local time
Today, 14:21
Joined
Jan 14, 2017
Messages
18,186
You know, when using your code, this part:
Code:
Public Const SND_ALIAS& = &H10000
Public Const SND_ASYNC& = &H1
Public Const SND_FILENAME& = &H20000
Public Const SND_NODEFAULT& = &H2
Public Const SND_NOWAIT& = &H2000
Public Const SND_RESOURCE& = &H40004
Public Const SND_SYNC& = &H0
Public Const SND_LOOP = &H8
Public Const SND_PURGE = &H40
gets red! and shows the error of "arrays, Declare statements and.... not allowed as Public members of object modules".

Hmm....
I've rechecked this in Access 2019/365 64-bit and it works absolutely fine. The code should be in a standard module ...NOT a form/class module
The only parts in red are those in the #Else (legacy) part of each API declaration and that is normal behaviour!
I did find an unrelated 64-bit error in a different module which I've fixed in the attached updated version of my countdown utility

IMyself said:
deleting the "Public" statement, and modify the PlayWaveFile , the strSound to music path, because it didnt play! and change SND_LOOP to 0 to prevent non-stop sound playing!! :

Once again I've rechecked this and it works for me and other numerous clients.
Did you define strSound as String as in my example?

In my example I want the sound to loop. If you don't, you would indeed need to modify the code.
That was why I include all those Public Const values (the purpose of which were all explained on post #6) as different users have different needs
 

Attachments

  • CountdownTimer1910.zip
    758 KB · Views: 294
Last edited:

Users who are viewing this thread

Top Bottom