Hi, can anyone help me to add an audio or video file to a form and play it from there??
For both video and audio you can use MCI (Windows'
Multimedia
Control
Interface).
However, if you are going to only need audio, I highly recommend using
FMOD (you can do so much more - set the volume, frequency, panning, view waveform and spectrum data, etc, even though you probably won't need all that. XD)
FMOD is used by means of a DLL, meaning that you just call functions like normal in VB.
MCI is very different - you simply send a commands as a string and get a return value.
For both, there are no 'events' for when a sound reaches the end of playback, for example, you have to keep bugging them asking for the current position and seeing if that's how long the sound
is (it must've reached the end). Also both can cope with many files open at once, although FMOD seems to be able to cope with more, because it's very often used for a sound effects engine in games, therefore it
needs to be able to deal with many many sounds.
Anyway... a quick tutorial of how to use MCI! ^-^
Firstly, to be able to send commands to MCI in VB6, you need to put this module in your VB project:
-
Declare Function mciSendString Lib "winmm.dll" Alias _
-
"mciSendStringA" (ByVal lpstrCommand As String, ByVal _
-
lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal _
-
hwndCallback As Long) As Long
-
-
'Also, I (Robbi-985) found this list of error codes (and
-
'their explanations, is the point...)
-
-
'MCI Errors Defined MCI Error Number
-
'----------------------------------------------------------
-
'#define MCIERR_BASE 256
-
'
-
'#define MCIERR_INVALID_DEVICE_ID 257
-
'#define MCIERR_UNRECOGNIZED_KEYWORD 259
-
'#define MCIERR_UNRECOGNIZED_COMMAND 261
-
'#define MCIERR_HARDWARE 262
-
'#define MCIERR_INVALID_DEVICE_NAME 263
-
'#define MCIERR_OUT_OF_MEMORY 264
-
'#define MCIERR_DEVICE_OPEN 265
-
'#define MCIERR_CANNOT_LOAD_DRIVER 266
-
'#define MCIERR_MISSING_COMMAND_STRING 267
-
'#define MCIERR_PARAM_OVERFLOW 268
-
'#define MCIERR_MISSING_STRING_ARGUMENT 269
-
'#define MCIERR_BAD_INTEGER 270
-
'#define MCIERR_PARSER_INTERNAL 271
-
'#define MCIERR_DRIVER_INTERNAL 272
-
'#define MCIERR_MISSING_PARAMETER 273
-
'#define MCIERR_UNSUPPORTED_FUNCTION 274
-
'#define MCIERR_FILE_NOT_FOUND 275
-
'#define MCIERR_DEVICE_NOT_READY 276
-
'#define MCIERR_INTERNAL 277
-
'#define MCIERR_DRIVER 278
-
'#define MCIERR_CANNOT_USE_ALL 279
-
'#define MCIERR_MULTIPLE 280
-
'#define MCIERR_EXTENSION_NOT_FOUND 281
-
'#define MCIERR_OUTOFRANGE 282
-
'#define MCIERR_FLAGS_NOT_COMPATIBLE 283
-
'#define MCIERR_FILE_NOT_SAVED 286
-
'#define MCIERR_DEVICE_TYPE_REQUIRED 287
-
'#define MCIERR_DEVICE_LOCKED 288
-
'#define MCIERR_DUPLICATE_ALIAS 289
-
'#define MCIERR_BAD_CONSTANT 290
-
'#define MCIERR_MUST_USE_SHAREABLE 291
-
'#define MCIERR_MISSING_DEVICE_NAME 292
-
'#define MCIERR_BAD_TIME_FORMAT 293
-
'#define MCIERR_NO_CLOSING_QUOTE 294
-
'#define MCIERR_DUPLICATE_FLAGS 295
-
'#define MCIERR_INVALID_FILE 296
-
'#define MCIERR_NULL_PARAMETER_BLOCK 297
-
'#define MCIERR_UNNAMED_RESOURCE 298
-
'#define MCIERR_NEW_REQUIRES_ALIAS 299
-
'#define MCIERR_NOTIFY_ON_AUTO_OPEN 300
-
'#define MCIERR_NO_ELEMENT_ALLOWED 301
-
'#define MCIERR_NONAPPLICABLE_FUNCTION 302
-
'#define MCIERR_ILLEGAL_FOR_AUTO_OPEN 303
-
'#define MCIERR_FILENAME_REQUIRED 304
-
'#define MCIERR_EXTRA_CHARACTERS 305
-
'#define MCIERR_DEVICE_NOT_INSTALLED 306
-
'#define MCIERR_GET_CD 307
-
'#define MCIERR_SET_CD 308
-
'#define MCIERR_SET_DRIVE 309
-
'#define MCIERR_DEVICE_LENGTH 310
-
'#define MCIERR_DEVICE_ORD_LENGTH 311
-
'#define MCIERR_NO_INTEGER 312
-
'
-
'#define MCIERR_WAVE_OUTPUTSINUSE 320
-
'#define MCIERR_WAVE_SETOUTPUTINUSE 321
-
'#define MCIERR_WAVE_INPUTSINUSE 322
-
'#define MCIERR_WAVE_SETINPUTINUSE 323
-
'#define MCIERR_WAVE_OUTPUTUNSPECIFIED 324
-
'#define MCIERR_WAVE_INPUTUNSPECIFIED 325
-
'#define MCIERR_WAVE_OUTPUTSUNSUITABLE 326
-
'#define MCIERR_WAVE_SETOUTPUTUNSUITABLE 327
-
'#define MCIERR_WAVE_INPUTSUNSUITABLE 328
-
'#define MCIERR_WAVE_SETINPUTUNSUITABLE 329
-
'
-
'#define MCIERR_SEQ_DIV_INCOMPATIBLE 336
-
'#define MCIERR_SEQ_PORT_INUSE 337
-
'#define MCIERR_SEQ_PORT_NONEXISTENT 338
-
'#define MCIERR_SEQ_PORT_MAPNODEVICE 339
-
'#define MCIERR_SEQ_PORT_MISCERROR 340
-
'#define MCIERR_SEQ_TIMER 341
-
'#define MCIERR_SEQ_PORTUNSPECIFIED 342
-
'#define MCIERR_SEQ_NOMIDIPRESENT 343
-
'
-
'#define MCIERR_NO_WINDOW 346
-
'#define MCIERR_CREATEWINDOW 347
-
'#define MCIERR_FILE_READ 348
-
'#define MCIERR_FILE_WRITE 349
-
'
-
'#define MCIERR_CUSTOM_DRIVER_BASE 512
-
Now...
It seems there are basically 2 types of commands you can send - ones which require a return value (a response, in English...), and ones which don't. For both, you get back an error code.
When you send a command which doesn't require a response, use code like this:
TempError = mciSendString("open that file", 0&, 0, 0)
TempError will be given the error code which that MCI command made. If it's 0, there was no error. Otherwise, look at that massive piece of code above to find a number which matches, and that'll tell you what that error code means.
When you send a command which DOES require a response, use code like this:
TempError = mciSendString("how long is that file?", ReturnString, 255, 0)
Again, TempError is the error code (this is always the case), hopefully 0.
We've told MCI to put the answer to the question we asked, into ReturnString.
And we told it not to make the answer more than 255 characters long.
How to use MCI to actually do something (a.k.a. Examples)
You know in VB6, everything's based on objects, and every obejct has a name?
Well in MCI it's kinda the same, except it's called an
alias. The alias basically
is the sound, to MCI - every time you give it the alias, it refers to that sound.
When you open a new file (video or audio), you need to give it an alias.
To open a file, send the command
open followed by the name of the file, in speech-marks.
- You also need to tell it what
type of file you're telling it to open.
- Lastly, you need to give it an
alias - a name which you can refer to this loaded file as later, when you need to stop it or play it again for example.
The full command could look like this:
open "c:\An Audio File.wav" type waveaudio alias MyFirstSound
- The
type will usually be one of 2:
- -
waveaudio
- -
mpegvideo
Yes, it sounds weird telling it that a sound is in fact an '
mpegvideo', but there is no such type as 'mpegaudio'.
mpegvideo seems to look for any codec you have on your system which can play this file (for example, it can also play OGG files if you have the Ogg Vorbis codecs installed!)
- The
alias can be anything alphabetical, and it is
case sensitive (i.e.
MyFirstSound isn't the same thing as
myfirstsound). Possibly it can also have numbers in it, but I'm not sure about that, and I've never
had to use numbers, so I haven't.
To put speech-marks into a string in VB6 is not quite as straight-forward as we'd like it to be.
e.g.
String = "My name is "Robbi-985""
That makes no sense if you follow the speech-marks.
It can be done though by telling VB to insert the character with the ASCII code 34 (this the code for a speech-mark).
e.g.
String = "My name is"+chr(34)+"Robbi-985"+chr(34)
That's what I mean - it's a mess, but it works.
So, to send the string which I gave as an example above, you'd type in VB:
TempError = mciSendString("open "+chr(34)+"c:\An Audio File.wav"+chr(34)+" type waveaudio alias MyFirstSound)
Nasty. But anyway, that's really the only time you'll need to give it a speech-mark, thankfully.
The next thing that you should know is how to
REMOVE an alias (i.e. sound/video) when you don't need it any more! If you
don't remove it, then the next time your program runs, it will cause an error when trying to open a sound with that alias
again, because that alias will already be being used (left over from before)!
This is probably the simplest command of them all -
close:
close MyAudioFile
That's it.
Also, in case your program crashes or is not exitted properly (like using the Stop button on VB6 when not made into an EXE yet), you should tell MCI to make sure that your alias is not already being used
before trying to open a sound and use that alias. In other words, tell it to close it before opening it. Again, it sounds weird, but it will prevent an error when you try to use the aliss which is already used, and if it
isn't already being used, it
will not cause an error, so it's a win-win situation.
To play a loaded sound, send ... surprisingly... the
play command:
play lynxaudiofile
...and to
stop a playing sound, if it is playing (again, an error won't be caused it it
isn't playing - MCI is generally pretty error-resiliant):
stop lynxaudiofile
So far, these have all been commands where you're not asking MCI to tell you something - to give back a return value.
What if you want to skip 5 seconds ahead in a playing sound?
You need MCI to tell you how long the sound is, then add 5 seconds to that, then tell it to skip to there.
So...
First, you must tell it what unit of length to operate in - MCI can tell you how long a sound is in samples or miliseconds, but miliseconds is the one we want here. So we tell it this:
set MyAudioFile time format ms
Again, we're not asking for anything back yet, so we use code like this:
TempError = mciSendString("set MyAudioFile time format ms", 0&, 0, 0)
Next, we ask it, how long is the sound?
Whenever you ask MCI to tell you anything, you will always begin the command with
status. For example, to get the length of a sound we use:
TempError = mciSendString("status MyAudioFile position", ReturnString, 255, 0)
So it gives back an error code as usual in TempError, but stores how long the sound is, in milliseconds in ReturnString.
IMPORTANT - MCI
always gives back responses as strings!
(Not the error codes - they're not exactly a response, more a result.)
So, if you want to store the position of the sound as a Long variable type, you'll want to do:
Dim MyAudioFileLength as Long
MyAudioFileLength = Val(ReturnString)
Here, we need the
position though:
TempError = mciSendString("status MyAudioFile position", ReturnString, 255, 0)
We'll store it in a variable called SoundPosition:
SoundPosition = Val(ReturnString)
So, we wanted it to skip 5 seconds ahead. Since we've been told the length in milliseconds, we'll need to add 5000 onto its current position and tell it to skip to there.
SoundPosition = SoundPosition + 5000
Next step is telling it to skip ('
seek') to this new position!
TempError = mciSendString("seek MyAudioFile to " + Str(SoundPosition), 0&, 0, 0)
Note, we're not asking for MCI to give something back here.
Note also that after seeking, the sound playback stops, so you must tell it to carry on playing!
TempReturn = mciSendString("play MyAudioFile", 0&, 0, 0)
My God, I went on a bit. But I hope that is useful info. Even if you are using VB.NET, the command strings of MCI are always the same.