473,387 Members | 1,542 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Generating a tone in VB6

Hi,

Can anyone tell me how I can generate a tone in VB6 I need to be able to set the frequency and duration in ms it also needs to go to the line out or speaker out of the sound card.

I have limited programming experience, so a detailed explanation is appreciated

Thanks..
Aug 28 '07 #1
11 7858
Robbie
180 100+
Hi. I know how to do exactly what you want pretty easily, apart from the fact that it comes out of the internal PC speaker / 'bleeper' rather than the soundcard.
Unfortunately though, for what you want, I only know how to do it a rather long-winded way - but hey, at least it gets the job done ;) (...eventually <_<)

For this I recommend using the FMOD sound engine.
You can download it there (it's free), and it comes with quite a lot of examples for VB6 (I presume you're not using .NET...?).

This tutorial should get you a program which can produce (and change frequency of) a tone in realtime (don't need to make any WAV file). Since you say you're new to VB, I'll try to go in a pretty step-by-step fashion.

- Download and install the FMOD Programmers' API.
- Start VB and choose to create a Standard EXE.
The next thing you need to do is to save the project (yes, it's just a blank form so far). To keep everything neat and easy to keep track of, I suggest you put it in its own new folder.
- Wherever you save it, the next thing to do is copy fmodex.dll (you'll find it where you installed FMOD, in the api folder) and paste it into the folder which you saved the VB project in.
- Then, back in the FMOD program folder, in api/vb copy those 4 VB Modules and paste them into the folder which your project's saved in (gotta keep everything together, makes it so much easier to maintain).
- On your project on VB, in the Project Explorer area (usually top-right - it's the bit where you'll see the forms, modules and other things used in your project), right-click, choose Add, click Module.
- On the Add Module window, choose the Existing tab and open one of the 4 Modules.
- Do the same to add the other 3 Modules so you end up with all 4 added to your project.

Now for the main coding part! >=D

- Double-click on your form so that you get to editing the Form_Load() sub's code.
- Type this (or better still, copy-and-paste) :

OUTSIDE of the Form_Load() sub (at the top of the code window, the General Declarations area) :
Expand|Select|Wrap|Line Numbers
  1. Dim MainSystem As Long
  2. Dim ToneChannel As Long
  3. Dim DSPID as Long
  4.  
INSIDE the Form_Load() sub:
Expand|Select|Wrap|Line Numbers
  1. Dim Result As FMOD_RESULT
  2. Dim Version As Long
  3.  
  4. ' Create our main system object and initialize. Its ID will be stored in the variable 'MainSystem', so we can refer to it later.
  5.             Result = FMOD_System_Create(MainSystem)
  6.             ERRCHECK (Result)
  7. 'Note that after every FMOD function, we'll tell VB to make sure that FMOD gave back no error (hence the ERRCHECK(Result))
  8.  
  9. 'Find out what version of FMOD the DLL (fmodex.dll) is, store it in 'Version' variable
  10.             Result = FMOD_System_GetVersion(MainSystem, Version)
  11.             ERRCHECK (Result)
  12.  
  13. 'FMOD_VERSION is a variable held in one of the 4 modules we added. Those modules were made for that specific version of FMOD.
  14. 'Therefore we have to make sure the DLL is of the same version, otherwise there could be incompatibilities (this is mainly for if you're gonna give the program to other people, because we need to make sure they have the same version of FMOD's DLL as the program needs)
  15.             If Version <> FMOD_VERSION Then
  16. 'If it's not the right version, show an error
  17.                 MsgBox "Error!  You are using an old Version of FMOD " & Hex$(Version) & ". " & _
  18.                     "This program requires " & Hex$(FMOD_VERSION)
  19.             End If
  20.  
  21. 'Initialize our system (MainSystem)!
  22.                 Result = FMOD_System_Init(MainSystem, 2, FMOD_INIT_NORMAL, 0)
  23. 'MainSystem means that's the system we want to initialize, which we created earlier (yes, you can even use multiple 'systems' at once...)
  24. '2 = the maximum number of channels which will be able to play on this system - i.e. we're telling it that only as many as 2 sounds need to be able to play at any one time here. I know you actually only need 1, but I like to use slightly more than necessary e.g. so I can tell if I accidentally tell a sound to play twice.
  25.                 ERRCHECK (Result)
  26.  
  27. 'Create a DSP which will make the tone which you want.
  28. 'A DSP is a 'unit' in FMOD which can either create sound from scratch (what we're using it for here - meaning that it's called a DSP oscillator), or to filter sound, e.g. bass boost or add a reverb)
  29. 'We're storing the ID of this DSP unit in the variable DSPID, which we can then use later to refer to this specific DSP unit, as we did with MainSystem.
  30.                 Result = FMOD_System_CreateDSPByType(MainSystem, FMOD_DSP_TYPE_OSCILLATOR, DSPID)
  31.                 ERRCHECK (Result)
  32.  
  33. 'Set the frequency of our DSP oscillator
  34.                 Result = FMOD_DSP_SetParameter(DSPID, FMOD_DSP_OSCILLATOR_RATE, 4000)
  35. 'That means 4,000 Hz
  36.                 ERRCHECK (Result)
  37.  
  38. 'Set the type of the to Square
  39.                 Result = FMOD_DSP_SetParameter(DSPID, FMOD_DSP_OSCILLATOR_TYPE, 1)
  40.                 ERRCHECK (Result)
  41. '1 means Square waveform (sounds like the internal PC speaker). Also available are Sine wave (pure 'hum'), sawtooth, triangle, white noise (not in that order, and I can't remember what number means which. I thing 0 for Sine and 4 for WhiteNoise, but I can't remember off the top of my head. You can change it and see for yourself anyway if you need to.
  42.  
  43.  
  44. 'You play a sound on a channel - whether from a sound file or being made in realtime, like with this DSP unit.
  45. 'It is simpler to have the DSP permanently making a tone, and just pause/unpause the channel which it's playing on, than to actually keep stopping and starting the DSP itself.
  46. '(Just trust me ;) )
  47. 'Start playing it on a channel. We've told FMOD that there should only be 2 channels available. FMOD will play the DSP on the first available channel, or if there is no channel available, the one which had something starting playing on it the longest time ago (therefore probably least important).
  48.                 Result = FMOD_System_PlayDSP(System, FMOD_CHANNEL_REUSE, DSPID, 1, ToneChannel)
  49.                 ERRCHECK (Result)
  50. 'The ID of the channel which it uses is stored in our variable ToneChannel.
  51. '1 means that it WILL start paused. A 0 here would mean no, it will start producing sound straight away, not wait for us to unpause it.
  52.  
  53. 'One more thing needs to be done to protect your precious speakers and ears - turn down the volume of that channel which will play the DSP! (Well, it already will be playing, just paused)
  54.                 Result = FMOD_Channel_SetVolume(ToneChannel, 0.125)
  55.                 ERRCHECK (Result)
  56. 'Volumes range from 0 to 1. So 0.125 may seem like a very low volume. However, the volumes are logarithmic, meaning that it makes more of a difference lower down, e.g. the difference between 0.1 and 0.2 is more obvious than 0.6 and 1.
  57.  
You should see a sub called ERRCHECK being called many times to check for and display any errors FMOD gave back for the last thing we told it to do. But that ERRCHECK function doesn't exist, so we need to make it.
Put this at the absolute bottom of the code window (outside any subs)
Expand|Select|Wrap|Line Numbers
  1. Private Sub ERRCHECK(Result As FMOD_RESULT)
  2.  
  3.     If Result <> FMOD_OK Then
  4.         MsgBox "FMOD error! (" & Result & ") " & FMOD_ErrorString(Result)
  5.     End If
  6.  
  7. End Sub
  8.  
The next thing you must do, before we even try to hear the sound, is SAVE THE FORM before we crash VB and lose it!
It's very easy for VB to crash while we play around with FMOD.
If you forget to shut down the system (MainSystem) before exitting the program,VB will crash, simple as that.

- So next, on the code window, in the top-left pulldown menu choose Form, and in the top-right menu choose Unload.
We're gonna tell VB to shut down our MainSystem on FMOD whenever the form is about to close, to avoid VB crashing!
- In the Form_Unload() sub, copy/paste this:
Expand|Select|Wrap|Line Numbers
  1. If MainSystem Then
  2.         Result = FMOD_System_Close(System)
  3.         Result = FMOD_System_Release(System)
  4. End If
  5.  
Now you have to remember to never use the Stop button on VB (next to the Play button you click to run your program), unless you have saved, because it will crash because of us not shutting down MainSystem! However, if you exit the form as you'd have to when your program's made, it won't crash now.

Right, we're ready to try to hear the sound now!
- Create a CheckBox on the form and call it ToneCheck.
- Double-click it to get typing code in the ToneCheck_Click() sub.
- Copy/paste this into that sub:
[code=vb]
If ToneCheck.Value = 1 Then
'The checkbox is ticked! We need to set ToneChannel's paused state to 0 (not paused!)
'(In English: we need to unpause the channel so we can hear the tone!)

Result = FMOD_Channel_SetPaused(ToneChannel, 0)
ERRCHECK (Result)
'0 = unpaused
Else
'Checkbox is unchecked - we don't want to hear the tone, pause ToneChannel!
Result = FMOD_Channel_SetPaused(ToneChannel, 1)
ERRCHECK (Result)
'1 = paused
End If

Save now and run it, and check/uncheck the box. Hopefully this is what you need.
You can change the frequency of the DSP unit by using this code:
Expand|Select|Wrap|Line Numbers
  1.        Result = FMOD_DSP_SetParameter(DSPID, FMOD_DSP_OSCILLATOR_RATE, YourNewFrequency)
  2.                 ERRCHECK (Result)
  3.  
I know that you wanted it to be so that you gave it the frequency and duration. Well here's a little sub which does that:
Expand|Select|Wrap|Line Numbers
  1. Public Sub FMODBeep(Frequency, Duration as Long)
  2.     Result = FMOD_DSP_SetParameter(DSPID, FMOD_DSP_OSCILLATOR_RATE, Frequency)
  3. ERRCHECK(Result)
  4. 'That set the frequency to Frequency (Hz)
  5.         Result = FMOD_Channel_SetPaused(Channel, 0)
  6.         ERRCHECK (Result)
  7. 'That 'turned the tone on'
  8. MsgWaitObj Duration
  9. 'That's making it wait for the Duration you gave (milliseconds)
  10.  
  11.         Result = FMOD_Channel_SetPaused(Channel, 1)
  12.         ERRCHECK (Result)
  13. 'That's pausing the channel again after we've heard the tone for as long as we want to.
  14.  
  15. End Sub
  16.  
There's a call to a sub there called MsgWaitObj.
That makes VB wait there until a certain amount of time has passed, without maxing out the processor and without stopping the program from responding.
To be able to use it, add another Module (this time, New), and paste this into it:
Expand|Select|Wrap|Line Numbers
  1. '-----
  2. 'INSANE COMPLEXNESS FOR NON-LOCKING SLEEP:
  3. 'START
  4. '-----
  5. '********************************************
  6. '*    (c) 1999-2000 Sergey Merzlikin        *
  7. '********************************************
  8.  
  9. Private Const STATUS_TIMEOUT = &H102&
  10. Private Const INFINITE = -1& ' Infinite interval
  11. Private Const QS_KEY = &H1&
  12. Private Const QS_MOUSEMOVE = &H2&
  13. Private Const QS_MOUSEBUTTON = &H4&
  14. Private Const QS_POSTMESSAGE = &H8&
  15. Private Const QS_TIMER = &H10&
  16. Private Const QS_PAINT = &H20&
  17. Private Const QS_SENDMESSAGE = &H40&
  18. Private Const QS_HOTKEY = &H80&
  19. Private Const QS_ALLINPUT = (QS_SENDMESSAGE Or QS_PAINT _
  20.         Or QS_TIMER Or QS_POSTMESSAGE Or QS_MOUSEBUTTON _
  21.         Or QS_MOUSEMOVE Or QS_HOTKEY Or QS_KEY)
  22. Private Declare Function MsgWaitForMultipleObjects Lib "user32" _
  23.         (ByVal nCount As Long, pHandles As Long, _
  24.         ByVal fWaitAll As Long, ByVal dwMilliseconds _
  25.         As Long, ByVal dwWakeMask As Long) As Long
  26. Private Declare Function GetTickCount Lib "kernel32" () As Long
  27. '-----
  28. 'INSANE COMPLEXNESS FOR NON-LOCKING SLEEP:
  29. 'END
  30. '-----
  31.  
  32.  
  33.  
  34.  
  35.  
  36. ' The MsgWaitObj function replaces Sleep,
  37. ' WaitForSingleObject, WaitForMultipleObjects functions.
  38. ' Unlike these functions, it
  39. ' doesn't block thread messages processing.
  40. ' Using instead Sleep:
  41. '     MsgWaitObj dwMilliseconds
  42. ' Using instead WaitForSingleObject:
  43. '     retval = MsgWaitObj(dwMilliseconds, hObj, 1&)
  44. ' Using instead WaitForMultipleObjects:
  45. '     retval = MsgWaitObj(dwMilliseconds, hObj(0&), n),
  46. '     where n - wait objects quantity,
  47. '     hObj() - their handles array.
  48.  
  49. Public Function MsgWaitObj(Interval As Long, _
  50.             Optional hObj As Long = 0&, _
  51.             Optional nObj As Long = 0&) As Long
  52. Dim T As Long, T1 As Long
  53. If Interval <> INFINITE Then
  54.     T = GetTickCount()
  55.     On Error Resume Next
  56.     T = T + Interval
  57.     ' Overflow prevention
  58.     If Err <> 0& Then
  59.         If T > 0& Then
  60.             T = ((T + &H80000000) _
  61.             + Interval) + &H80000000
  62.         Else
  63.             T = ((T - &H80000000) _
  64.             + Interval) - &H80000000
  65.         End If
  66.     End If
  67.     On Error GoTo 0
  68.     ' T contains now absolute time of the end of interval
  69. Else
  70.     T1 = INFINITE
  71. End If
  72. Do
  73.     If Interval <> INFINITE Then
  74.         T1 = GetTickCount()
  75.         On Error Resume Next
  76.      T1 = T - T1
  77.         ' Overflow prevention
  78.         If Err <> 0& Then
  79.             If T > 0& Then
  80.                 T1 = ((T + &H80000000) _
  81.                 - (T1 - &H80000000))
  82.             Else
  83.                 T1 = ((T - &H80000000) _
  84.                 - (T1 + &H80000000))
  85.             End If
  86.         End If
  87.         On Error GoTo 0
  88.         ' T1 contains now the remaining interval part
  89.         If IIf((T1 Xor Interval) > 0&, _
  90.             T1 > Interval, T1 < 0&) Then
  91.             ' Interval expired
  92.             ' during DoEvents
  93.             MsgWaitObj = STATUS_TIMEOUT
  94.             Exit Function
  95.         End If
  96.     End If
  97.     ' Wait for event, interval expiration
  98.     ' or message appearance in thread queue
  99.     MsgWaitObj = MsgWaitForMultipleObjects(nObj, _
  100.             hObj, 0&, T1, QS_ALLINPUT)
  101.     ' Let's message be processed
  102.     DoEvents
  103.     If MsgWaitObj <> nObj Then Exit Function
  104.     ' It was message - continue to wait
  105. Loop
  106. End Function
  107.  
Sorry for the absolutely ridiculous length of this post!
Good luck~!
If you have any more questions, please ask! ^^
Aug 30 '07 #2
Robbie
180 100+
Woah~... I noticed missed-out words, wrong words ('thing' instead of 'think'), no close brackets...
I blame it on the fact that it's 6:07 AM and I haven't been to sleep yet. -"-;

EDIT: Sorry for double-post, I can't read my entire tutorial in just 5 minutes to edit it within 5 minutes >_<
Aug 30 '07 #3
Hi Robbie,

Thanks for writing this answer to my question, this is very helpfull .
I will go and try this out.
Thanks again for taking the time to do this.
Aug 30 '07 #4
Hi Robbie,

I have done everything your said in your posting but run into a couple of problems.
While trying to add the last module (fmodexp) it came up with the following 2 error messages

"Name conflicts with existing module, project or object library"

Then it comes up with the following

"An error occurred while background loading module"module 1".
Background load will now abort and the code for some modules may
not be loaded. saving these modules to there current file name will
result in code loss. Please load a new project."

I tried this several times but every time it is the same and I don't see duplicate names so I don't know where the problem is.

It will create a "module 1 (fmodexp.bas)" but this is empty.

I guess that this is the reason I get other error messages when running the program.

If it is more helpfull I can email you the folder with what I have done so far.

Thanks
Aug 30 '07 #5
Killer42
8,435 Expert 8TB
... I can't read my entire tutorial in just 5 minutes to edit it within 5 minutes >_<
Someone told me recently that the five-minute limit on editing had been increased to one hour. Is this not the case?
Aug 31 '07 #6
Robbie
180 100+
While trying to add the last module (fmodexp) it came up with the following 2 error messages
I downloaded the latest version from their web site and it doesn't work for me either, but because of other errors.
I'm sorry, you only should have tried to load modules:
fmod_errors
fmod_dsp
fmodex

It seems they're just rushing and not paying attention to the VB stuff because they think that C++ or other languages there are more important, or something. <_<

I'm uploading a ZIP file which contains the version of FMOD I'm using.
The ZIP contains the 3 VB modules, and the fmodex.dll.
Hope this works! (It should, since they're the exact files I'm using)
FMOD_v4_6_21_for_VB.zip
Sep 3 '07 #7
jnherm
2
Hi Robbie,
I use this code you suggested and all corrections you"ve made and yet i have problems running my prog...Whenever a function with ToneChannel parameter is called error will result..It says invalid parameter was passed to this function!err#37..
What happen?
Functions with errors are:

FMOD_System_PlayDSP(...)
FMOD_Channel_SetVolume(...) and
FMDO_Channel_SetPaused(...)
Sep 8 '07 #8
Robbie
180 100+
*Sigh*
I knew I should've tested this before I told you to do make it.

Just to let you know, I'm working on an example project on VB, I'll give you a link to it when I'm done. ;)
Sep 8 '07 #9
Robbie
180 100+
Here you go! =D
I found several errors in my code, the worst one being I typed System instead of MainSystem (because that was code which I'd copied from another of my programs and forgotten to change >_<)

Enjoy! ^^
Please let me know how it goes
Generate_Tone_example.zip
Sep 8 '07 #10
jnherm
2
Thanks so much Robbie for sample program!!!
Sep 9 '07 #11
Option Explicit
Private Declare Function GetMem8 Lib "msvbvm60" (ByRef src As Any, ByRef Dst As Any) As Long
Private Declare Function GetMem4 Lib "msvbvm60" (ByRef src As Any, ByRef Dst As Any) As Long
Private Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundW" (ByRef pData As Any, ByVal hModule As Long, ByVal dwFlags As Long) As Long
Private Declare Function Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) As Long
Private Const SND_MEMORY = &H4
Dim x As Integer

Private Function PlayTone(ByVal fFrequency As Single, ByVal fDurationMS As Single) As Boolean
Dim bData() As Byte
Dim lSize As Long
Dim lSamples As Long
Dim lIndex As Long
Dim fPhase As Single
Dim fDelta As Single
lSamples = 44.1 * fDurationMS
lSize = lSamples + 44
fDelta = fFrequency / 44100 * 6.28318530717959
ReDim bData(lSize - 1)
GetMem4 &H46464952, bData(0): GetMem4 CLng(lSize - 8), bData(4)
GetMem8 233861439252950.2551@, bData(8)
GetMem8 28147927167.7968@, bData(16)
GetMem8 18940805779.77@, bData(24)
GetMem8 702234480110259.4049@, bData(32)
GetMem4 lSamples, bData(40)
For lIndex = 0 To lSamples - 1
bData(lIndex + 44) = Sin(fPhase) * 127 + 128
fPhase = fPhase + fDelta
If fPhase > 6.28318530717959 Then fPhase = fPhase - 6.28318530717959
Next
PlaySound bData(0), 0, SND_MEMORY
End Function



Private Sub Form_Load()
For x = 300 To 1100 Step 9
PlayTone x, 8
Next
For x = 900 To 300 Step -9
PlayTone x, 7
Next
' the x is frequency and the number is duration
End
End Sub
Jul 14 '18 #12

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: jinoy | last post by:
how can i detect the dtmf tone using the mscomm control. pls send me the code of it.
0
by: Jan Kowalski | last post by:
Hi! Does someon know how to generate a sinusoidal tone? Thanks in advance!
4
by: seo gang ho | last post by:
how to make tone generator.. set frequency and amplitude.. show me the example.. thank you for read..
2
by: John S. Ford, MD | last post by:
I'm familiar with the beep function but is there any function that enables you to determine the pitch and duration of a tone produced by the computer's speaker? John
2
by: gichu | last post by:
what is single tone class in C++,
2
by: jjjonesman | last post by:
Hey, can anyone recommend a site that supports 3410 Nokia ring tone. Nokia forums weren't much help unfortunately. I'm an IT guy but apparently I suck at cell phone tech. Heheh :)
1
by: LA1 | last post by:
I have telecomuter that logs into a mainframe to use a DB2 database. The client uses SPUFI to edit the database and make changes. The client has received from us a new notebook. Both his old and...
1
by: =?Utf-8?B?Q29ubnk=?= | last post by:
I need to create tones simulating the keys of a piano. 1. Please how does the sourcecode look like for a tone generator using single sine wave? 2. How does the sourcecode look like for a tone...
0
by: =?windows-1256?B?5e3L4w==?= | last post by:
Download FREE from here http://ringtonesmp03.blogspot.com/2008/11/tone-channel-bbc-world.html http://ringtonesmp03.blogspot.com
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.