如何让 Fmod 在课堂上工作

How do I get Fmod to work from a class?

本文关键字:课堂 工作 Fmod      更新时间:2023-10-16

在我用C++编写的项目中,我目前正在FMOD从我的main.cpp工作。为了帮助组织我的引擎,我想将我的声音代码移动到它自己的翻译单元。出于某种原因,当我尝试从类中运行声音代码时,它不会播放任何声音。我不确定是因为值分配不正确,还是有一个我不知道的更大问题。这是我的类实现:

//Sound.h
#ifndef SOUND_H
#define SOUND_H
#include <iostream>
#include "incfmod.hpp"
#include "incfmod_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();
}

目前它给了我 2 个错误:

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

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

知道为什么它不起作用吗?知道我如何解决这些问题吗?

从您的最后一条评论中查看您的代码,我看到了一个问题。您已经通过FMOD::System *sys;创建了一个指针,但此指针未初始化为任何FMOD::System实例,也就是说,代码中的某个位置应该有类似sys = new FMOD::Systemsys = new FMOD::System(/* whatever argument you must supply to it's constructor */);的东西,但就在您尝试访问与FMOD::System对象相关的任何内容之前。这很可能是程序崩溃的原因。此外,由于sys是指向FMOD::System的指针,因此包含result = FMOD::System_Create(&sys);通过引用传递指针的行存在另一个问题。我建议你阅读几篇关于 C 和 C++ 中的指针的文章,以及更多关于面向对象编程语言中的对象创建和销毁的文章。

我能够获得有关该问题的帮助。我错误地初始化了声音变量。

sound = &Sound();

实际上应该是:

sound = new Sound();