尝试使用 SDL 为音频分配回调变量
trying to assign callback variable with SDL for audio
当我尝试在 AudioSpec 结构中分配回调变量时,当我尝试将类型 "void function" 分配给类型 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 文件中分配了音频所需的变量,因此 class.
中的所有函数都可以访问它
SDL 回调签名是 void (*)(void* userdata, Uint8* stream, int len)
类型的独立函数。
您的回调签名接近但不完全匹配:void (mainEngineCW4::*)(void* userdata, Uint8* stream, int len)
。
主要区别在于它是一个成员函数,是其类型的一部分。简而言之,该类型——成员函数——意味着你必须用一个 class 的实例来调用它,它成为 this
指针,例如 myEngine->myAudioCallback( ... )
。独立函数没有 this
指针,因此会被称为 standAloneAudioCallback( ... )
.
解决此问题的一种方法是使 myAudioCallback
成为 static 成员函数。另一种方法是 make 是一个非成员(aka,独立)函数。
在任何一种情况下,如果您需要访问 mainEngineCW4
class 当前所属的(非静态)成员数据,您将需要访问它,通常通过静态或全局变量或使用 userdata
参数来存储 class 实例。我需要多看一点你的程序才能准确地演示它。
更新回复您的评论:
有几种方法可以做到这一点。可能您想要的是将音频规范中的 userdata
设置为您的引擎实例 class 并传入使用该指针调用成员函数的静态(或独立)回调:
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);
// ...
}
};
为了简洁起见,我将其全部写在 class 定义中,但如果需要,您可以将其拆分为 .h
/.cpp
。我还添加了一些 const
,这是很好的做法,我遵循了“Almost Always Auto”风格。
正如 metal 之前回复的那样,错误是我试图在我的 mainEngineCW4 中定义 myAudioCallback class。
class mainEngineCW4
{
public:
void myAudioCallback();
}
相反,在 class 之外声明它。
我一开始 运行 遇到的错误是无法访问结构 AudioData,但这也在 class 中定义。只需在 class.
之外定义两者
class mainEngineCW4
{}
struct AudioData {
Uint8* position;
Uint32 length;};
void myAudioCallback(void* userdata, Uint8* stream, int len);
当我尝试在 AudioSpec 结构中分配回调变量时,当我尝试将类型 "void function" 分配给类型 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 文件中分配了音频所需的变量,因此 class.
中的所有函数都可以访问它SDL 回调签名是 void (*)(void* userdata, Uint8* stream, int len)
类型的独立函数。
您的回调签名接近但不完全匹配:void (mainEngineCW4::*)(void* userdata, Uint8* stream, int len)
。
主要区别在于它是一个成员函数,是其类型的一部分。简而言之,该类型——成员函数——意味着你必须用一个 class 的实例来调用它,它成为 this
指针,例如 myEngine->myAudioCallback( ... )
。独立函数没有 this
指针,因此会被称为 standAloneAudioCallback( ... )
.
解决此问题的一种方法是使 myAudioCallback
成为 static 成员函数。另一种方法是 make 是一个非成员(aka,独立)函数。
在任何一种情况下,如果您需要访问 mainEngineCW4
class 当前所属的(非静态)成员数据,您将需要访问它,通常通过静态或全局变量或使用 userdata
参数来存储 class 实例。我需要多看一点你的程序才能准确地演示它。
更新回复您的评论:
有几种方法可以做到这一点。可能您想要的是将音频规范中的 userdata
设置为您的引擎实例 class 并传入使用该指针调用成员函数的静态(或独立)回调:
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);
// ...
}
};
为了简洁起见,我将其全部写在 class 定义中,但如果需要,您可以将其拆分为 .h
/.cpp
。我还添加了一些 const
,这是很好的做法,我遵循了“Almost Always Auto”风格。
正如 metal 之前回复的那样,错误是我试图在我的 mainEngineCW4 中定义 myAudioCallback class。
class mainEngineCW4
{
public:
void myAudioCallback();
}
相反,在 class 之外声明它。
我一开始 运行 遇到的错误是无法访问结构 AudioData,但这也在 class 中定义。只需在 class.
之外定义两者class mainEngineCW4
{}
struct AudioData {
Uint8* position;
Uint32 length;};
void myAudioCallback(void* userdata, Uint8* stream, int len);