c++ - 尝试使用SDL为音频分配回调变量

标签 c++ audio sdl

当我尝试在AudioSpec结构中分配回调变量时,当我尝试为类型SDL_AudioCallback分配类型“无效函数”时,编译器不喜欢它。

void mainEngineCW4::myAudioCallback(void* userdata, Uint8* stream, int Glen) {

AudioData* audio = (AudioData*)userdata;

if (audio->length == 0)
    return;

Uint32 length = (Uint32)len;
length = (length > audio->length ? audio->length : length); // if length is more than the audio length, then set length to be the audio.length, if not, set it to be the length passed to the function

SDL_memcpy(stream, audio->position, length);

audio->position += length;
audio->length -= length; }

void mainEngineCW4::playAudio() // this function is for loading an audio device, and playing the audio through that device {

AudioData audio;
audio.position = wavStart;
audio.length = wavLength;

wavSpec.callback = mainEngineCW4::myAudioCallback;
wavSpec.userdata = &audio;

audioDevice = SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, SDL_AUDIO_ALLOW_ANY_CHANGE);
if (audioDevice == 0)
{
    std::cerr << SDL_GetError() << std::endl;
    return;
}

SDL_PauseAudioDevice(audioDevice, 0); // mildly confused by why they decided to call the function for starting to play audio for "PauseAudioDevice" but yeah. this plays audio. }

我将控制音频的职责分为三个功能,loadAudio,startAudio和endAudio。我已经在.h文件中分配了音频所需的变量,因此该类中的所有函数都可以访问它。

this is the error

最佳答案

SDL回调签名是void (*)(void* userdata, Uint8* stream, int len)类型的独立函数。

您的回调签名很接近,但并不完全匹配:void (mainEngineCW4::*)(void* userdata, Uint8* stream, int len)

主要区别在于它是成员函数,是其类型的一部分。简而言之,该类型(成员函数)表示您必须使用一个类的实例来调用它,该实例将成为this指针,例如myEngine->myAudioCallback( ... )。独立函数没有this指针,因此将被称为standAloneAudioCallback( ... )

解决此问题的一种方法是使myAudioCallback成为静态成员函数。另一种制作方法是非成员(也称为独立)函数。

在任何一种情况下,如果您需要访问当前属于它的mainEngineCW4类的(非静态)成员数据,则通常需要使用静态或全局变量或使用userdata参数来访问它。存储类实例。我需要多看一些您的程序以进行精确演示。

更新回应您的评论:

您可以通过几种方法来执行此操作。可能需要的是将音频规范中的userdata设置为引擎类的实例,并传递一个使用该指针调用成员函数的静态(或独立)回调:

class mainEngineCW4 
{
    struct AudioData { /* ... */ };

    // Private static member function, but could be a stand-alone function
    static void myStaticAudioCallback( void* const userData, Uint8* const stream, const int len )
    {
        const auto myEngine = reinterpret_cast<mainEngineCW4*>( userData );
        myEngine->myAudioCallback( stream, len );
    }

    void myAudioCallback( const Uint8* const stream, const int len )
    {
        // ... Process stream using AudioData struct or whatever
    }

public:
    void playAudio()
    {
        auto audioSpec = SDL_AudioSpec{};
        // ... set the freq and format and what not in the audio spec
        audioSpec.callback = &myStaticAudioCallback;
        audioSpec.userdata = this;

        const auto audioDevice = SDL_OpenAudioDevice( NULL, 0, &audioSpec, NULL, SDL_AUDIO_ALLOW_ANY_CHANGE);
        // ...
    }
};

为了简洁起见,我已经在类定义中全部编写了此代码,但是您可以根据需要将其拆分为.h / .cpp。我还添加了一些const,这是很好的做法,并且遵循“Almost Always Auto”样式。

关于c++ - 尝试使用SDL为音频分配回调变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61842282/

相关文章:

c++ - 将两个整数相除以产生浮点结果

html - 如何将我的个人保管箱文件嵌入到我的网站上以便公开显示?

c++ - Xcode 在 C++ 中访问资源

iphone - 通过iPhone上的http套接字播放mp3音频

Java Clip.play 在第三次调用时挂起

c++ - C++中的屏幕分辨率

c++ - 无法在 SDL2 (MAC M1) 中正确渲染三角形

c++ - 无法将 "member pointer to derived class"转换为 "member pointer to base class"

C++ 从 .CPP 文件访问变量

c++ - 在类构造函数中初始化常量 vector (C++)