Beep & Time

F

Faraz A. Qureshi

A code like the following should play ten beeps shouldn't it?

Sub Bp()
For x = 1 To 10
Beep
Next
End Sub

How to have them played at specified intervals for example after 3/5 seconds
each?
 
M

Michelle

This does something like what you want...
Sub test()
Dim x As Byte
For x = 1 To 10
Beep
Application.Wait Now() + TimeSerial(0, 0, 0.6)
Next x
End Sub

however I think the wait method rounds the time values to the nearest full
second, so it treats the 0.6 as 1

is that any good for you?

M
 
M

Michelle

Another 'dodgy' option is to get it to run a loop with nothing in it lts of
times, so that it takes up the time you want.

Sub test()
Dim x As Byte, y As Long
For x = 1 To 10
Beep
For y = 1 To 50000000
Next y
Next x
End Sub


This will run at different speeds on different machines though.

It's a bodged workaround but it might do what you want

M
 
J

JoeU2004

Michelle said:
however I think the wait method rounds the time values to the
nearest full second, so it treats the 0.6 as 1

I don't know about the Wait method, but certainly the TimeSerial function
does, according to the help page.

Alternative:

Public Declare Sub Sleep Lib "kernel32" (ByVal msec As Long)

Sub doit()
Const delay as double = 3 / 5
Beep
For i = 2 To 10
Sleep 1000 * delay + 0.5
Beep
Next i
End Sub

Note: "+ 0.5" ensures "normal" rounding, if necessary. Otherwise, VB will
use "banker's" rounding.

Also note: This separates the beep sounds by 600 msec. That is probably
good enough. On my computer, the Beep statement sets up a sound, which runs
asynchronously. So the only overhead is the time to set up the sound, which
is only 3 to 9 msec on my computer.

But I don't know if that (asynchronous sound) is true for all computers. Do
you want to subtract the Beep statement overhead?

Finally, on my computer, the Beep statement will interrupt any sound in
progress. To understand the consequences, test your loop by setting the
Defaut Beep to a long sound. On my computer, Windows XP Startup,wav takes
about 2.75 sec.


----- original message -----

Michelle said:
This does something like what you want...
Sub test()
Dim x As Byte
For x = 1 To 10
Beep
Application.Wait Now() + TimeSerial(0, 0, 0.6)
Next x
End Sub

however I think the wait method rounds the time values to the nearest full
second, so it treats the 0.6 as 1

is that any good for you?

M
 
F

Faraz A. Qureshi

Thanx Michelle!

That was excellent! However, what's the logic of using BYTE???

--
Best Regards,

Faraz


Michelle said:
Another 'dodgy' option is to get it to run a loop with nothing in it lts of
times, so that it takes up the time you want.

Sub test()
Dim x As Byte, y As Long
For x = 1 To 10
Beep
For y = 1 To 50000000
Next y
Next x
End Sub


This will run at different speeds on different machines though.

It's a bodged workaround but it might do what you want

M
 
C

Chip Pearson

However, what's the logic of using BYTE???

A misguided effort to use the smallest possible data type.

Memory is so plentiful and cheap that it makes no sense to worry about
saving a byte here and there. (And if you were concerned to the point
where individual bytes really mattered, VBA is decidedly not the right
platform to begin with. Strict ANSI C, not even C++, for super tight
memory requirements.) All integral numerics should be Longs, as
software is optimized for 32 bits and short ints end up getting
converted to longs by the CPU. Floating points should always be
Doubles. Forget about Byte, Integer, and Single. On rare occasion you
may need an Byte array, but a single Byte variable is of no value.

And the code that Michelle posted, to which you are replying,

For y = 1 To 50000000
Next y

This is probably the absolutely worst way to cause some sort of pause
in code execution. A vastly better way is to use the SleepEx API:

Public Declare Function SleepEx Lib "kernel32" ( _
ByVal dwMilliseconds As Long, _
ByVal bAlertable As Long) As Long

Sub AAA()
Dim PauseSeconds As Long
PauseSeconds = 5
'
' your code here
'
' pause execution
SleepEx dwMilliseconds:=PauseSeconds * 1000&, bAlertable:=0
'
' the rest of your code here
'
End Sub

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)
 
J

JoeU2004

Chip Pearson said:
And the code that Michelle posted, to which you are replying,
For y = 1 To 50000000
Next y
This is probably the absolutely worst way to cause some sort
of pause in code execution.

My reaction as well. But I figured "you can lead a horse to water, but you
cannot make him drink".

A vastly better way is to use the SleepEx API:

Public Declare Function SleepEx Lib "kernel32" ( _
ByVal dwMilliseconds As Long, _
ByVal bAlertable As Long) As Long

Since you are setting bAlertable to zero (uninterruptible), why not use the
even simpler Sleep API, as I did?

Dim PauseSeconds As Long
PauseSeconds = 5
[....]
SleepEx dwMilliseconds:=PauseSeconds * 1000&, bAlertable:=0

Since the OP wants a delay 3/5 sec, why are you using 5 seconds in your
example?

I believe the correct implementation is, minimally:

Dim PauseSeconds as Double
PauseSeconds = 3 / 5
.....
SleepEx dwMilliseconds:=PauseSeconds * 1000, bAlertable:=0

I believe VB will convert the Double PauseSeconds*1000 to Long by applying
"banker's rounding". To ensure "normal" rounding, I would do:

SleepEx dwMilliseconds:=PauseSeconds * 1000 + 0.5, bAlertable:=0

Alternatively, you could do:

Dim PauseMsec as Long
PauseMsec = 600
.....
SleepEx dwMilliseconds:=PauseMsec, bAlertable:=0


----- original message -----
 
C

Chip Pearson

Since you are setting bAlertable to zero (uninterruptible), why not use the
even simpler Sleep API, as I did?

Habit, mostly. Also, I believe that MSDN recommends using SleepEx
rather than Sleep. I forget why, and I don't feel like looking it up.
Since the OP wants a delay 3/5 sec, why are you using 5 seconds in your
example?

For illustration only, and I had lost track of the original question.
The point I was trying to make was that the For N = 1 To 5 Billion
loop was a terrible way to code. In real world code, I would get rid
of the intermediate variable entirely and just use the correct value
in the call to SleepEx and be done with it.

SleepEx dwMilliseconds:=600, bAlertable:=0

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)

Chip Pearson said:
And the code that Michelle posted, to which you are replying,
For y = 1 To 50000000
Next y
This is probably the absolutely worst way to cause some sort
of pause in code execution.

My reaction as well. But I figured "you can lead a horse to water, but you
cannot make him drink".

A vastly better way is to use the SleepEx API:

Public Declare Function SleepEx Lib "kernel32" ( _
ByVal dwMilliseconds As Long, _
ByVal bAlertable As Long) As Long

Since you are setting bAlertable to zero (uninterruptible), why not use the
even simpler Sleep API, as I did?

Dim PauseSeconds As Long
PauseSeconds = 5
[....]
SleepEx dwMilliseconds:=PauseSeconds * 1000&, bAlertable:=0

Since the OP wants a delay 3/5 sec, why are you using 5 seconds in your
example?

I believe the correct implementation is, minimally:

Dim PauseSeconds as Double
PauseSeconds = 3 / 5
....
SleepEx dwMilliseconds:=PauseSeconds * 1000, bAlertable:=0

I believe VB will convert the Double PauseSeconds*1000 to Long by applying
"banker's rounding". To ensure "normal" rounding, I would do:

SleepEx dwMilliseconds:=PauseSeconds * 1000 + 0.5, bAlertable:=0

Alternatively, you could do:

Dim PauseMsec as Long
PauseMsec = 600
....
SleepEx dwMilliseconds:=PauseMsec, bAlertable:=0


----- original message -----

Chip Pearson said:
A misguided effort to use the smallest possible data type.

Memory is so plentiful and cheap that it makes no sense to worry about
saving a byte here and there. (And if you were concerned to the point
where individual bytes really mattered, VBA is decidedly not the right
platform to begin with. Strict ANSI C, not even C++, for super tight
memory requirements.) All integral numerics should be Longs, as
software is optimized for 32 bits and short ints end up getting
converted to longs by the CPU. Floating points should always be
Doubles. Forget about Byte, Integer, and Single. On rare occasion you
may need an Byte array, but a single Byte variable is of no value.

And the code that Michelle posted, to which you are replying,

For y = 1 To 50000000
Next y

This is probably the absolutely worst way to cause some sort of pause
in code execution. A vastly better way is to use the SleepEx API:

Public Declare Function SleepEx Lib "kernel32" ( _
ByVal dwMilliseconds As Long, _
ByVal bAlertable As Long) As Long

Sub AAA()
Dim PauseSeconds As Long
PauseSeconds = 5
'
' your code here
'
' pause execution
SleepEx dwMilliseconds:=PauseSeconds * 1000&, bAlertable:=0
'
' the rest of your code here
'
End Sub

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)
 
J

JoeU2004

Chip Pearson said:
The point I was trying to make was that the
For N = 1 To 5 Billion loop was a terrible
way to code.

Oh, y'get no argument from me on that point. I had to duct tape my hands to
the desk in order to keep me from reacting to Michelle's suggestion and
later to Faraz's response.

(Although it did bring back some fond memories of the days -- more than 35
years ago! -- when I had to meticulously design such timing loops in order
to transmit bits at a precise baud rate. This is before USARTs. But I
digress....)


----- original message -----

Chip Pearson said:
Since you are setting bAlertable to zero (uninterruptible), why not use
the
even simpler Sleep API, as I did?

Habit, mostly. Also, I believe that MSDN recommends using SleepEx
rather than Sleep. I forget why, and I don't feel like looking it up.
Since the OP wants a delay 3/5 sec, why are you using 5 seconds in your
example?

For illustration only, and I had lost track of the original question.
The point I was trying to make was that the For N = 1 To 5 Billion
loop was a terrible way to code. In real world code, I would get rid
of the intermediate variable entirely and just use the correct value
in the call to SleepEx and be done with it.

SleepEx dwMilliseconds:=600, bAlertable:=0

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)

Chip Pearson said:
And the code that Michelle posted, to which you are replying,
For y = 1 To 50000000
Next y
This is probably the absolutely worst way to cause some sort
of pause in code execution.

My reaction as well. But I figured "you can lead a horse to water, but
you
cannot make him drink".

A vastly better way is to use the SleepEx API:

Public Declare Function SleepEx Lib "kernel32" ( _
ByVal dwMilliseconds As Long, _
ByVal bAlertable As Long) As Long

Since you are setting bAlertable to zero (uninterruptible), why not use
the
even simpler Sleep API, as I did?

Dim PauseSeconds As Long
PauseSeconds = 5
[....]
SleepEx dwMilliseconds:=PauseSeconds * 1000&, bAlertable:=0

Since the OP wants a delay 3/5 sec, why are you using 5 seconds in your
example?

I believe the correct implementation is, minimally:

Dim PauseSeconds as Double
PauseSeconds = 3 / 5
....
SleepEx dwMilliseconds:=PauseSeconds * 1000, bAlertable:=0

I believe VB will convert the Double PauseSeconds*1000 to Long by applying
"banker's rounding". To ensure "normal" rounding, I would do:

SleepEx dwMilliseconds:=PauseSeconds * 1000 + 0.5, bAlertable:=0

Alternatively, you could do:

Dim PauseMsec as Long
PauseMsec = 600
....
SleepEx dwMilliseconds:=PauseMsec, bAlertable:=0


----- original message -----

Chip Pearson said:
However, what's the logic of using BYTE???

A misguided effort to use the smallest possible data type.

Memory is so plentiful and cheap that it makes no sense to worry about
saving a byte here and there. (And if you were concerned to the point
where individual bytes really mattered, VBA is decidedly not the right
platform to begin with. Strict ANSI C, not even C++, for super tight
memory requirements.) All integral numerics should be Longs, as
software is optimized for 32 bits and short ints end up getting
converted to longs by the CPU. Floating points should always be
Doubles. Forget about Byte, Integer, and Single. On rare occasion you
may need an Byte array, but a single Byte variable is of no value.

And the code that Michelle posted, to which you are replying,

For y = 1 To 50000000
Next y

This is probably the absolutely worst way to cause some sort of pause
in code execution. A vastly better way is to use the SleepEx API:

Public Declare Function SleepEx Lib "kernel32" ( _
ByVal dwMilliseconds As Long, _
ByVal bAlertable As Long) As Long

Sub AAA()
Dim PauseSeconds As Long
PauseSeconds = 5
'
' your code here
'
' pause execution
SleepEx dwMilliseconds:=PauseSeconds * 1000&, bAlertable:=0
'
' the rest of your code here
'
End Sub

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)


On Sun, 13 Sep 2009 02:25:01 -0700, Faraz A. Qureshi

Thanx Michelle!

That was excellent! However, what's the logic of using BYTE???
 
F

Faraz A. Qureshi

I am really sorry Joe!
The mistake was that I had inserted "/" instead of an "OR"!
--
Best Regards,

Faraz


JoeU2004 said:
Chip Pearson said:
And the code that Michelle posted, to which you are replying,
For y = 1 To 50000000
Next y
This is probably the absolutely worst way to cause some sort
of pause in code execution.

My reaction as well. But I figured "you can lead a horse to water, but you
cannot make him drink".

A vastly better way is to use the SleepEx API:

Public Declare Function SleepEx Lib "kernel32" ( _
ByVal dwMilliseconds As Long, _
ByVal bAlertable As Long) As Long

Since you are setting bAlertable to zero (uninterruptible), why not use the
even simpler Sleep API, as I did?

Dim PauseSeconds As Long
PauseSeconds = 5
[....]
SleepEx dwMilliseconds:=PauseSeconds * 1000&, bAlertable:=0

Since the OP wants a delay 3/5 sec, why are you using 5 seconds in your
example?

I believe the correct implementation is, minimally:

Dim PauseSeconds as Double
PauseSeconds = 3 / 5
.....
SleepEx dwMilliseconds:=PauseSeconds * 1000, bAlertable:=0

I believe VB will convert the Double PauseSeconds*1000 to Long by applying
"banker's rounding". To ensure "normal" rounding, I would do:

SleepEx dwMilliseconds:=PauseSeconds * 1000 + 0.5, bAlertable:=0

Alternatively, you could do:

Dim PauseMsec as Long
PauseMsec = 600
.....
SleepEx dwMilliseconds:=PauseMsec, bAlertable:=0


----- original message -----

Chip Pearson said:
A misguided effort to use the smallest possible data type.

Memory is so plentiful and cheap that it makes no sense to worry about
saving a byte here and there. (And if you were concerned to the point
where individual bytes really mattered, VBA is decidedly not the right
platform to begin with. Strict ANSI C, not even C++, for super tight
memory requirements.) All integral numerics should be Longs, as
software is optimized for 32 bits and short ints end up getting
converted to longs by the CPU. Floating points should always be
Doubles. Forget about Byte, Integer, and Single. On rare occasion you
may need an Byte array, but a single Byte variable is of no value.

And the code that Michelle posted, to which you are replying,

For y = 1 To 50000000
Next y

This is probably the absolutely worst way to cause some sort of pause
in code execution. A vastly better way is to use the SleepEx API:

Public Declare Function SleepEx Lib "kernel32" ( _
ByVal dwMilliseconds As Long, _
ByVal bAlertable As Long) As Long

Sub AAA()
Dim PauseSeconds As Long
PauseSeconds = 5
'
' your code here
'
' pause execution
SleepEx dwMilliseconds:=PauseSeconds * 1000&, bAlertable:=0
'
' the rest of your code here
'
End Sub

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)
 
J

JoeU2004

Faraz A. Qureshi said:
The mistake was that I had inserted "/" instead of an "OR"!

Ironically, I began to suspect as much when I read Chip's posting, and I to
think about the potential ambiguity of "3 / 5". I had ass-u-me-d that "no
one" would want to beep for 30 to 50 seconds (!).

Anyway, in that case, Michelle's first solution might be the best one
insofar as it is the most straight-forward. Namely:

Application.Wait Now() + TimeSerial(0,0,5)

The point is, as Chip stated so "diplomatically": do not use a timing loop,
at least not when some better method works.

One caveat: VB Now() truncates time to the second, in contrast to Excel
Now(), which has a resolution of ten millisecond, as I recall. So the Wait
method above might be off by as much as nearly one second.

If that concerns you, the Sleep solution that I presented might be
preferrable. Or use Chip's SleepEx solution if you like adding complexity
that you might not understand ;-).

On the other hand, one advantage of the Wait method is that it is portable
among platforms (i.e. Mac and Windows). I don't know if the same can be
said for any kernel32 lib functions.


----- original message -----

Faraz A. Qureshi said:
I am really sorry Joe!
The mistake was that I had inserted "/" instead of an "OR"!
--
Best Regards,

Faraz


JoeU2004 said:
Chip Pearson said:
And the code that Michelle posted, to which you are replying,
For y = 1 To 50000000
Next y
This is probably the absolutely worst way to cause some sort
of pause in code execution.

My reaction as well. But I figured "you can lead a horse to water, but
you
cannot make him drink".

A vastly better way is to use the SleepEx API:

Public Declare Function SleepEx Lib "kernel32" ( _
ByVal dwMilliseconds As Long, _
ByVal bAlertable As Long) As Long

Since you are setting bAlertable to zero (uninterruptible), why not use
the
even simpler Sleep API, as I did?

Dim PauseSeconds As Long
PauseSeconds = 5
[....]
SleepEx dwMilliseconds:=PauseSeconds * 1000&, bAlertable:=0

Since the OP wants a delay 3/5 sec, why are you using 5 seconds in your
example?

I believe the correct implementation is, minimally:

Dim PauseSeconds as Double
PauseSeconds = 3 / 5
.....
SleepEx dwMilliseconds:=PauseSeconds * 1000, bAlertable:=0

I believe VB will convert the Double PauseSeconds*1000 to Long by
applying
"banker's rounding". To ensure "normal" rounding, I would do:

SleepEx dwMilliseconds:=PauseSeconds * 1000 + 0.5, bAlertable:=0

Alternatively, you could do:

Dim PauseMsec as Long
PauseMsec = 600
.....
SleepEx dwMilliseconds:=PauseMsec, bAlertable:=0


----- original message -----

Chip Pearson said:
However, what's the logic of using BYTE???

A misguided effort to use the smallest possible data type.

Memory is so plentiful and cheap that it makes no sense to worry about
saving a byte here and there. (And if you were concerned to the point
where individual bytes really mattered, VBA is decidedly not the right
platform to begin with. Strict ANSI C, not even C++, for super tight
memory requirements.) All integral numerics should be Longs, as
software is optimized for 32 bits and short ints end up getting
converted to longs by the CPU. Floating points should always be
Doubles. Forget about Byte, Integer, and Single. On rare occasion you
may need an Byte array, but a single Byte variable is of no value.

And the code that Michelle posted, to which you are replying,

For y = 1 To 50000000
Next y

This is probably the absolutely worst way to cause some sort of pause
in code execution. A vastly better way is to use the SleepEx API:

Public Declare Function SleepEx Lib "kernel32" ( _
ByVal dwMilliseconds As Long, _
ByVal bAlertable As Long) As Long

Sub AAA()
Dim PauseSeconds As Long
PauseSeconds = 5
'
' your code here
'
' pause execution
SleepEx dwMilliseconds:=PauseSeconds * 1000&, bAlertable:=0
'
' the rest of your code here
'
End Sub

Cordially,
Chip Pearson
Microsoft Most Valuable Professional
Excel Product Group, 1998 - 2009
Pearson Software Consulting, LLC
www.cpearson.com
(email on web site)


On Sun, 13 Sep 2009 02:25:01 -0700, Faraz A. Qureshi

Thanx Michelle!

That was excellent! However, what's the logic of using BYTE???
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top