Sound and Music in games

Heya everyone,

For the first time ever im going to take a stab at making music and sound
effects in my code.

What i have right now is a 2d side scroller made in opengl (getting to
opengl via sdl) that takes up very little cpu/gpu so lots of resources are
still left available.

What im looking for is just something simple like being able to play .wav
files as sound effects and .mid for background music.

I’ve heard from some people SDL_Mixer is the way to go, and then also heard
from other people that SDL_Mixer is unwieldy and doesnt work so great.

What do you guys say, what’s the best way to go on this? OpenAL? fmodlib?
something else?

Thanks for the help!
Atrix

SDL_Mixer works fine for me.

Here is my C code for music and sounds. It should be pretty easy to
bolt on, and straightforward to use. I have an overall header file,
and then 3 C files, one for general audio device control, one for
music, and one for sound. It do not use all features of SDL_Mixer,
but it is certianly enough to get you started if you have not done it
before.

ChrisOn 6/10/05, Alan Wolfe wrote:

Heya everyone,

For the first time ever im going to take a stab at making music and sound
effects in my code.

What i have right now is a 2d side scroller made in opengl (getting to
opengl via sdl) that takes up very little cpu/gpu so lots of resources are
still left available.

What im looking for is just something simple like being able to play .wav
files as sound effects and .mid for background music.

I’ve heard from some people SDL_Mixer is the way to go, and then also heard
from other people that SDL_Mixer is unwieldy and doesnt work so great.


/******************************************************************************
*

  • audio_lib.h
  • Copyright © 2002, 2005 Chris Nystrom
  • This program is free software; you can redistribute it and/or modify
  • it under the terms of the GNU Lessor General Public License as published
  • by the Free Software Foundation; either version 2.1 of the License, or
  • (at your option) any later version.
  • This program is distributed in the hope that it will be useful,
  • but without any warranty whatsoever.
  • For more license information see:
  •  http://www.gnu.org/copyleft/lessor.html
    
  • Contact Author at:
  • Chris Nystrom
  • 11013 Prairie Dove Circle
  • Austin, Texas 78758
  • E-Mail: cnystrom at gmail.com
  • Blog: http://conversazione.blogspot.com
  • AIM: nystromchris
  • Soli Deo Gloria

*/

#ifndef _AUDIO_LIB_H
#define _AUDIO_LIB_H

#ifndef _SDL_H
#include “SDL.h”
#endif

#ifndef _MIXER_H
#include “SDL_mixer.h”
#endif

#ifndef PRIVATE
#define PRIVATE static
#endif

#ifndef PUBLIC
#define PUBLIC
#endif

#ifndef _BOOL_H
#define _BOOL_H

typedef unsigned char bool;

#ifndef FALSE
#define FALSE (0)
#endif

#ifndef TRUE
#define TRUE !FALSE
#endif

#endif // _BOOL_H

#ifndef OFF
#define OFF (0)
#endif

#ifndef ON
#define ON (!OFF)
#endif

#define MAX_NUM_CHANNELS (25)
#define MAX_NUM_SOUNDS (25)

PUBLIC int init_audio(void);
PUBLIC void close_audio(void);

PUBLIC bool audio_avail(void);

PUBLIC int load_sound(const char *filename);
PUBLIC void delete_sound(int i);

PUBLIC int sound_channel_done(int channel);
PUBLIC int play_sound(int i, int loops);

PUBLIC int load_music(const char *filename);
PUBLIC void play_music(int loops);
PUBLIC void stop_music(void);
PUBLIC bool music_playing(void);

PUBLIC void set_sound_volume(int v);
PUBLIC int get_sound_volume(void);

PUBLIC void set_music_volume(int v);
PUBLIC int get_music_volume(void);

#endif // _AUDIO_LIB_H

/******************************************************************************
*

  • audio.c
  • Copyright © 2002, 2005 Chris Nystrom
  • This program is free software; you can redistribute it and/or modify
  • it under the terms of the GNU Lessor General Public License as published
  • by the Free Software Foundation; either version 2.1 of the License, or
  • (at your option) any later version.
  • This program is distributed in the hope that it will be useful,
  • but without any warranty whatsoever.
  • For more license information see:
  •  http://www.gnu.org/copyleft/lessor.html
    
  • Contact Author at:
  • Chris Nystrom
  • 11013 Prairie Dove Circle
  • Austin, Texas 78758
  • E-Mail: cnystrom at gmail.com
  • Blog: http://conversazione.blogspot.com
  • AIM: nystromchris
  • Soli Deo Gloria

*/

#include <stdio.h>
#include “SDL.h”
#include “SDL_mixer.h”
#include “audio_lib.h”

PRIVATE bool audio_init = FALSE;

PUBLIC int init_audio(void)
{
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 512) < 0) {
fprintf(stderr, “init_audio(): %s\n”, Mix_GetError());
return (-1);
}

    audio_init = TRUE;

    return (0);

}

PUBLIC void close_audio(void)
{
if (audio_init) {
Mix_CloseAudio();
}
audio_init = FALSE;
}

PUBLIC bool audio_avail(void)
{
return (audio_init);
}

/******************************************************************************
*

  • music.c
  • Copyright © 2002, 2005 Chris Nystrom
  • This program is free software; you can redistribute it and/or modify
  • it under the terms of the GNU Lessor General Public License as published
  • by the Free Software Foundation; either version 2.1 of the License, or
  • (at your option) any later version.
  • This program is distributed in the hope that it will be useful,
  • but without any warranty whatsoever.
  • For more license information see:
  •  http://www.gnu.org/copyleft/lessor.html
    
  • Contact Author at:
  • Chris Nystrom
  • 11013 Prairie Dove Circle
  • Austin, Texas 78758
  • E-Mail: cnystrom at gmail.com
  • Blog: http://conversazione.blogspot.com
  • AIM: nystromchris
  • Soli Deo Gloria

*/

#include <stdlib.h>
#include “SDL.h”
#include “SDL_mixer.h”
#include “audio_lib.h”

extern bool file_exists(const char *s);

PRIVATE Mix_Music *song;
PRIVATE int music_volume;

PUBLIC int load_music(const char *filename)
{
if (!audio_avail()) {
fprintf(stderr, “load_music(): audio not initialized.\n”);
return (-1);
}

    if (!file_exists(filename)) {
            fprintf(stderr, "load_music(): file not available.\n");
            return (-2);
    }

    song = Mix_LoadMUS(filename);

    if (NULL == song) {
            fprintf(stderr, "load_song(): %s\n", Mix_GetError());
            return (-1);
    }

    return (0);

}

// Notes: loops == -1 is infinite loops.
// loops == 1 plays the sample twice (1 loop).
PUBLIC void play_music(int loops)
{
if (!audio_avail()) {
fprintf(stderr, “play_music(): audio not initialized.\n”);
return;
}

    if (-1 == Mix_PlayMusic(song, loops)) {
            fprintf(stderr, "play_music(): %s\n", Mix_GetError());
            fflush(stderr);
    }

}

PUBLIC void stop_music(void)
{
if (!audio_avail()) {
fprintf(stderr, “stop_music(): audio not initialized.\n”);
return;
}

    Mix_HaltMusic();

}

PUBLIC bool music_playing(void)
{
if (!audio_avail()) {
fprintf(stderr,
“music_playing(): audio not initialized.\n”);
return (FALSE);
}

    return (Mix_PlayingMusic());

}

PUBLIC void set_music_volume(int v)
{
if (!audio_avail()) {
fprintf(stderr,
“set_music_volume(): audio not initialized.\n”);
return;
}

    if (v < 0)
            v = 0;

    // Note MIX_MAX_VOLUME defined in SDL_mixer.h
    if (v > MIX_MAX_VOLUME)
            v = MIX_MAX_VOLUME;

    music_volume = v;

    Mix_VolumeMusic(music_volume);

}

PUBLIC int get_music_volume(void)
{
return (music_volume);
}

/******************************************************************************
*

  • sound.c
  • Copyright © 2002, 2005 Chris Nystrom
  • This program is free software; you can redistribute it and/or modify
  • it under the terms of the GNU Lessor General Public License as published
  • by the Free Software Foundation; either version 2.1 of the License, or
  • (at your option) any later version.
  • This program is distributed in the hope that it will be useful,
  • but without any warranty whatsoever.
  • For more license information see:
  •  http://www.gnu.org/copyleft/lessor.html
    
  • Contact Author at:
  • Chris Nystrom
  • 11013 Prairie Dove Circle
  • Austin, Texas 78758
  • E-Mail: cnystrom at gmail.com
  • Blog: http://conversazione.blogspot.com
  • AIM: nystromchris
  • Soli Deo Gloria

*/

#include <stdio.h>
#include “SDL.h”
#include “SDL_mixer.h”
#include “audio_lib.h”

extern bool file_exists(const char *s);

PRIVATE Mix_Chunk *sound[MAX_NUM_SOUNDS];
PRIVATE bool s_flag[MAX_NUM_SOUNDS] = { FALSE }; // Sound loaded for use

PRIVATE int done[MAX_NUM_CHANNELS] = { TRUE }; // Channel completed

PRIVATE int sound_volume;

PUBLIC int next_free_sound_num(void)
{
int i_num;

    for (i_num = 0; i_num < MAX_NUM_SOUNDS; i_num++) {
            if (FALSE == s_flag[i_num]) {
                    s_flag[i_num] = TRUE;
                    return (i_num);
            }
    }

    fprintf(stderr,
            "next_free_sound_num(): No more sounds available.\n");
    return (-1);

}

PUBLIC int load_sound(const char *filename)
{
int i;

    if (!audio_avail()) {
            fprintf(stderr, "load_sound(): audio not initialized.\n");
            return (-1);
    }

    if (!file_exists(filename)) {
            fprintf(stderr, "load_sound(): file not available.\n");
            return (-2);
    }

    i = next_free_sound_num();

// printf(“load_sound(): i = %d\n”, i);

    if (i < 0)
            return (i);

    sound[i] = Mix_LoadWAV(filename);

    if (NULL == sound[i]) {
            fprintf(stderr, "load_sound(): %s\n", Mix_GetError());
            fflush(stderr);
            return (-1);
    }

    return (i);

}

PUBLIC int sound_channel_done(int channel)
{
return (done[channel]);
}

PUBLIC void sound_channel_callback(int channel)
{
// printf(“sound_channel_callback(): sound on channel %d should be
done now.\n”, channel);

    done[channel] = TRUE;

}

// Notes: loops == -1 is infinite loops.
// loops == 1 plays the sample twice (1 loop).
PUBLIC int play_sound(int i, int loops)
{
int channel = -1;

    if (!audio_avail()) {
            fprintf(stderr, "play_sound(): audio not initialized.\n");
            return (-1);
    }

    Mix_ChannelFinished(sound_channel_callback);

// printf(“play_sound(): i = %d\n”, i);
// printf(“play_sound(): loops = %d\n”, loops);

    channel = Mix_PlayChannel(-1, sound[i], loops);

// printf(“play_sound(): channel = %d\n”, channel);

    if (-1 == channel) {
            fprintf(stderr, "play_sound(): %s\n", Mix_GetError());
            fflush(stderr);
    } else {
            done[channel] = FALSE;
    }

    return (channel);

}

PUBLIC void delete_sound(int i)
{
if (i < 0 || i >= MAX_NUM_SOUNDS) {
fprintf(stderr, “delete_sound(): bad sound number: %d.\n”,
i);
return;
}

    s_flag[i] = FALSE;

}

PUBLIC void set_sound_volume(int v)
{
int i;

    if (!audio_avail()) {
            fprintf(stderr,
                    "set_sound_volume(): audio not initialized.\n");
            return;
    }

    if (v < 0)
            v = 0;

    // Note MIX_MAX_VOLUME defined in SDL_mixer.h
    if (v > MIX_MAX_VOLUME)
            v = MIX_MAX_VOLUME;

    sound_volume = v;

    for (i = 0; i < MAX_NUM_SOUNDS; i++) {
            if (NULL != sound[i]) {
                    Mix_VolumeChunk(sound[i], sound_volume);
            }
    }

}

PUBLIC int get_sound_volume(void)
{
return (sound_volume);
}


E-Mail: Chris Nystrom
Business: http://www.shaklee.net/austin
Blog: http://conversazione.blogspot.com/
AIM: nystromchris