Background info: I was working on my C project these days. And due to the reason that this project is a piecs of homework of a course, we are told that using other libraries is not allowed. Our teacher provied us with a simple graphic lib and I planned to write a simple 2DGameEngine.
However when I tried to use mciSendString() to realize the audio system, I found that this function work out with GREAT DELAY (about 0.5s or a little bit more than that), It's not bareable for Game sound effect.
At first I thought it was because my function play
need first open a audio and then play it (I thought open a file from disk would spend a lot of time),However when I move open operation out of play, the delay still exist. I found many blogs or answers told me to use PlaySound()
or use XAudio2. But the former cannot play audio parally and the latter seems doesn't work well C. So I am expecting some solutions that DO NOT depends on any other libraries except Windows API and are able to immediately play the sound without any delay.
Here are some pieces of my code:
//Using OOP style in C and Audio is a Component.
Audio* newAudio(char* filePath, bool loop) {
Audio* audio = (Audio*)malloc(sizeof(Audio));
initAudio(audio, filePath, loop);
return audio;
}
static void initAudio(struct Audio *audio, char* filePath, bool loop){
Component* super = newComponent(renderAudio, updateAudio);
memcpy(&(audio->super), super, sizeof(Component));
audio->super.vptr = NULL;
audio->super.vptr = (componentvTable*)calloc(1, sizeof(componentvTable));
if (audio->super.vptr == NULL) {
printf("Cannot allocate memory for vptr of audio component\n");
return;
}
memcpy(audio->super.vptr, super->vptr, sizeof(componentvTable));
audio->super.vptr->getComponentType = returnAudioType;
destoryComponent(super);
audio->super.vptr->getComponentType = returnAudioType;
audio->super.meta = NULL;
audio->super.next = NULL;
audio->super.prev = NULL;
audio->filePath = filePath;
audio->playing = FALSE;
audio->loop = loop;
audio->volume = 100;
audio->play = Audio_play;
audio->pause = Audio_pause;
audio->stop = Audio_stop;
audio->setVolume = Audio_setVolume;
audio->getFilePath = Audio_getFilePath;
audio->getMeta = audio->super.getMeta;
audio->setMeta = audio->super.setMeta;
char command[256];
sprintf(command, "open \"%s\" type mpegvideo alias audio%d", audio->filePath, (int)audio);
mciSendString(command, NULL, 0, NULL);
}
static void renderAudio(Component* c){
return;
}
static void updateAudio(Component* c, ...){
return;
}
static const int returnAudioType(ComponentNode c){
return AUDIO;
}
static void Audio_play(struct Audio* audio) {
char command[256];
if (!audio->loop) {
sprintf(command, "play audio%d", (int)audio);
mciSendString(command, NULL, 0, NULL);
} else {
sprintf(command, "play audio%d repeat", (int)audio);
mciSendString(command, NULL, 0, NULL);
}
audio->playing = TRUE;
}
static void Audio_pause(struct Audio* audio) {
char command[256];
sprintf(command, "pause audio%d", (int)audio);
mciSendString(command, NULL, 0, NULL);
audio->playing = FALSE;
}
static void Audio_stop(struct Audio* audio) {
char command[256];
sprintf(command, "stop audio%d", (int)audio);
mciSendString(command, NULL, 0, NULL);
sprintf(command, "seek audio%d to %ld", (int)audio, 0L);
mciSendString(command, NULL, 0, NULL);
audio->playing = FALSE;
}
static void Audio_setVolume(struct Audio* audio, int volume) {
char command[256];
sprintf(command, "setaudio audio%d volume to %d", (int)audio, volume);
mciSendString(command, NULL, 0, NULL);
audio->volume = volume;
}
static char* Audio_getFilePath(struct Audio* audio) {
return audio->filePath;
}
static void destoryAudio(struct Audio* audio) {
char command[256];
sprintf(command, "close audio%d", (int)audio);
mciSendString(command, NULL, 0, NULL);
free(audio->super.vptr);
free(audio);
}
And below is how I use it.
static void playerUpdate(ActorNode player, double delta)
{
//other code
//R键技能
Vector *dashDirection = newVector(inmng.mouseX - player->pos.x, inmng.mouseY - player->pos.y);
if (dashDirection->length(dashDirection) > 5)
{
dashDirection->normalize(dashDirection);
dashDirection->mult(dashDirection, 5);
}
if (inmng.keyStates['R'])
{
//Start to play skill sound effect here.
if (!bulletTimeSound->playing)
bulletTimeSound->play(bulletTimeSound);
GAME_TIME_TICK = 1.0 / 500.0;
rPressed = TRUE;
playerDashTargetCircle->pos.x = player->pos.x + dashDirection->x;
playerDashTargetCircle->pos.y = player->pos.y + dashDirection->y;
playerDashTargetCircle->visible = TRUE;
playerDashTargetCircle->super.vptr->update((ComponentNode)playerDashTargetCircle, &(playerDashTargetCircle->pos));
}
else
{
GAME_TIME_TICK = 1.0 / 60.0;
if (rPressed && inmng.keyBoardEventType == KEY_UP)
{
rPressed = FALSE;
playerDashTargetCircle->visible = FALSE;
if (dashPower >= 10){
dashPower = dashPower - 40 > 0 ? dashPower - 40 : 0;
player->vel.x = dashDirection->x; player->vel.y = dashDirection->y;
Vector vel;
memcpy(&(vel), &(player->vel), sizeof(Vector));
vel.mult(&(vel), delta * VEL_CONST * 25);
player->pos.add(&(player->pos), &(vel));
//Stop skill sound effect play here
bulletTimeSound->stop(bulletTimeSound);
}
}
}
// other code
}