First of all, write the following code:
#include <Mmsystem.h>
#include <mciapi.h>
//these two headers are already included in the <Windows.h> header
#pragma comment(lib, "Winmm.lib")
To open *.mp3:
mciSendString("open \"*.mp3\" type mpegvideo alias mp3", NULL, 0, NULL);
To play *.mp3:
mciSendString("play mp3", NULL, 0, NULL);
To play and wait until the *.mp3 has finished playing:
mciSendString("play mp3 wait", NULL, 0, NULL);
To replay (play again from start) the *.mp3:
mciSendString("play mp3 from 0", NULL, 0, NULL);
To replay and wait until the *.mp3 has finished playing:
mciSendString("play mp3 from 0 wait", NULL, 0, NULL);
To play the *.mp3 and replay it every time it ends like a loop:
mciSendString("play mp3 repeat", NULL, 0, NULL);
If you want to do something when the *.mp3 has finished playing, then you need to RegisterClassEx
by the WNDCLASSEX
structure, CreateWindowEx
and process it's messages with the GetMessage, TranslateMessage and DispatchMessage functions in a while
loop and call:
mciSendString("play mp3 notify", NULL, 0, hwnd); //hwnd is an handle to the window returned from CreateWindowEx. If this doesn't work, then replace the hwnd with MAKELONG(hwnd, 0).
In the window procedure, add the case MM_MCINOTIFY:
The code in there will be executed when the mp3 has finished playing.
But if you program a Console Application and you don't deal with windows, then you can CreateThread
in suspend state by specifying the CREATE_SUSPENDED
flag in the dwCreationFlags
parameter and keep the return value in a static
variable and call it whatever you want. For instance, I call it mp3. The type of this static
variable is HANDLE
of course.
Here is the ThreadProc
for the lpStartAddress
of this thread:
DWORD WINAPI MP3Proc(_In_ LPVOID lpParameter) //lpParameter can be a pointer to a structure that store data that you cannot access outside of this function. You can prepare this structure before `CreateThread` and give it's address in the `lpParameter`
{
Data *data = (Data*)lpParameter; //If you call this structure Data, but you can call it whatever you want.
while (true)
{
mciSendString("play mp3 from 0 wait", NULL, 0, NULL);
//Do here what you want to do when the mp3 playback is over
SuspendThread(GetCurrentThread()); //or the handle of this thread that you keep in a static variable instead
}
}
All what you have to do now is to ResumeThread(mp3);
every time you want to replay your mp3 and something will happen every time it finishes.
You can #define play_my_mp3 ResumeThread(mp3);
to make your code more readable.
Of course you can remove the while (true)
, SuspendThread
and the from 0 codes, if you want to play your mp3 file only once and do whatever you want when it is over.
If you only remove the SuspendThread
call, then the sound will play over and over again and do something whenever it is over. This is equivalent to:
mciSendString("play mp3 repeat notify", NULL, 0, hwnd); //or MAKELONG(hwnd, 0) instead
in windows.
To pause the *.mp3 in middle:
mciSendString("pause mp3", NULL, 0, NULL);
and to resume it:
mciSendString("resume mp3", NULL, 0, NULL);
To stop it in middle:
mciSendString("stop mp3", NULL, 0, NULL);
Note that you cannot resume a sound that has been stopped, but only paused, but you can replay it by carrying out the play command. When you're done playing this *.mp3, don't forget to:
mciSendString("close mp3", NULL, 0, NULL);
All these actions also apply to (work with) wave files too, but with wave files, you can use "waveaudio" instead of "mpegvideo". Also you can just play them directly without opening them:
PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME);
If you don't want to specify an handle to a module:
sndPlaySound("*.wav", SND_FILENAME);
If you don't want to wait until the playback is over:
PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME | SND_ASYNC);
//or
sndPlaySound("*.wav", SND_FILENAME | SND_ASYNC);
To play the wave file over and over again:
PlaySound("*.wav", GetModuleHandle(NULL), SND_FILENAME | SND_ASYNC | SND_LOOP);
//or
sndPlaySound("*.wav", SND_FILENAME | SND_ASYNC | SND_LOOP);
Note that you must specify both the SND_ASYNC
and SND_LOOP
flags, because you never going to wait until a sound, that repeats itself countless times, is over!
Also you can fopen
the wave file and copy all it's bytes to a buffer (an enormous/huge (very big) array of bytes) with the fread
function and then:
PlaySound(buffer, GetModuleHandle(NULL), SND_MEMORY);
//or
PlaySound(buffer, GetModuleHandle(NULL), SND_MEMORY | SND_ASYNC);
//or
PlaySound(buffer, GetModuleHandle(NULL), SND_MEMORY | SND_ASYNC | SND_LOOP);
//or
sndPlaySound(buffer, SND_MEMORY);
//or
sndPlaySound(buffer, SND_MEMORY | SND_ASYNC);
//or
sndPlaySound(buffer, SND_MEMORY | SND_ASYNC | SND_LOOP);
Either OpenFile
or CreateFile
or CreateFile2
and either ReadFile
or ReadFileEx
functions can be used instead of fopen
and fread
functions.
Hope this fully answers perfectly your question.