Search code examples
c++fmod

How do I get Fmod to work from a class?


In my project written in C++, I have FMOD currently working from my main.cpp. To help organize my engine I want to move my sound code to it's own translation unit. For some reason when I try to run my sound code from within my class, it doesn't play any sound. I'm not sure if it is because of incorrect assignment of the value or if there is a bigger issue that I don't know about. This is my class implementation:

//Sound.h
#ifndef SOUND_H
#define SOUND_H

#include <iostream>

#include "inc\fmod.hpp"
#include "inc\fmod_errors.h"

class Sound
{
public:
    Sound(void);
    ~Sound(void);

    void Init();
    void FMODErrorCheck(FMOD_RESULT res);

    void PlaySound();
    void ResumeSound();
    void PauseSound();

    void Update();

private:
    //sound
    FMOD::System    *sys;
    FMOD_RESULT result;
    size_t  version; //this is just an unsigned int
    FMOD_SPEAKERMODE speakerMode;
    int numDrivers;
    FMOD_CAPS caps;
    char    name[256];
    FMOD::Sound *sound;
    FMOD::Channel *channel;
    bool    quitFlag;
};

#endif


//Sound.cpp
#include "Sound.h"

Sound::Sound(void)
{
    Init();
}

Sound::~Sound(void)
{
    FMODErrorCheck(sound->release());
    FMODErrorCheck(sys->release());
}

void Sound::Init()
{
    // Create FMOD interface object
    result = FMOD::System_Create(&sys);
    FMODErrorCheck(result);

    // Check version
    result = sys->getVersion(&version);
    FMODErrorCheck(result);

    if(version < FMOD_VERSION)
    {
        std::cout << "Error! You are using an old version of FMOD " << version << ". This program requires " << FMOD_VERSION << std::endl;
        exit(0);
    }

    // Get number of sound cards
    result = sys->getNumDrivers(&numDrivers);
    FMODErrorCheck(result);

    // No sound cards (disable sound)
    if(numDrivers == 0)
    {
        result = sys->setOutput(FMOD_OUTPUTTYPE_NOSOUND);
        FMODErrorCheck(result);
    }

    // At least one sound card
    else
    {
        // Get the capabilities of the default (0) sound card
        result = sys->getDriverCaps(0, &caps, 0, &speakerMode);
        FMODErrorCheck(result);

        // Set the speaker mode to match that in Control Panel
        result = sys->setSpeakerMode(speakerMode);
        FMODErrorCheck(result);

        // Increase buffer size if user has Acceleration slider set to off
        if(caps & FMOD_CAPS_HARDWARE_EMULATED)
        {
            result = sys->setDSPBufferSize(1024, 10);
            FMODErrorCheck(result);
        }

        // Get name of driver
        result = sys->getDriverInfo(0, name, 256, 0);
        FMODErrorCheck(result);

        // SigmaTel sound devices crackle for some reason if the format is PCM 16-bit.
        // PCM floating point output seems to solve it.
        if(strstr(name, "SigmaTel"))
        {
            result = sys->setSoftwareFormat(48000, FMOD_SOUND_FORMAT_PCMFLOAT, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
            FMODErrorCheck(result);
        }
    }

    // Initialise FMOD
    result = sys->init(100, FMOD_INIT_NORMAL, 0);

    // If the selected speaker mode isn't supported by this sound card, switch it back to stereo
    if(result == FMOD_ERR_OUTPUT_CREATEBUFFER)
    {
        result = sys->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
        FMODErrorCheck(result);

        result = sys->init(100, FMOD_INIT_NORMAL, 0);
    }
    FMODErrorCheck(result);

    // Open music as a stream
    //FMOD::Sound *song1, *song2, *effect;
    //result = sys->createStream("Effect.mp3", FMOD_DEFAULT, 0, &sound);
    //FMODErrorCheck(result);

    result = sys->createSound("Effect.mp3", FMOD_DEFAULT, 0, &sound);
    FMODErrorCheck(result);

    // Assign each song to a channel and start them paused
    //result = sys->playSound(FMOD_CHANNEL_FREE, sound, true, &channel);
    //FMODErrorCheck(result);

    // Songs should repeat forever
    channel->setLoopCount(-1);
}

void Sound::FMODErrorCheck(FMOD_RESULT res)
{
    if(res != FMOD_OK)
    {
        std::cout << "FMOD ERROR: (" << res << ") - " << FMOD_ErrorString(res) << std::endl;
        //quitFlag = true;
    }
}

void Sound::PlaySound()
{
    sys->playSound(FMOD_CHANNEL_FREE, sound, false, 0);
}

void Sound::ResumeSound()
{
    channel->setPaused(false);
}

void Sound::PauseSound()
{
    channel->setPaused(true);
}

void Sound::Update()
{
    sys->update();
}


//Main.cpp
Sound sound;

// Initialization routine.
void setup(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0);

    sound = &Sound();
}

//------------------------------------------------------------ OnInit()
//
void OnIdle()
{
    if(IsKeyPressed(KEY_ESCAPE))
    {
        exit(EXIT_SUCCESS);
    }

    if(IsKeyPressed('1'))
    {
        sound->PlaySound();
    }

    sound->Update();

    // redraw the screen
    glutPostRedisplay();
}

Currently it is giving me 2 errors:

Unhandled exception at 0x0F74465A (fmodex.dll) in TestOpenGL.exe: 0xC0000005: Access violation reading location 0x062C5040

and

FMOD error! (36) An invalid object handle was used

Any idea why it isn't working? Any idea how I solve these issues?


Solution

  • I was able to get help with the issue. I was initializing my sound variable incorrectly.

    sound = &Sound();

    Should actually be:

    sound = new Sound();