SDL仅发出蜂鸣声,而不是实际的音频文件

问题描述 投票:0回答:1

我最近设法克服了使用SDL进行声音的错误。

现在,它正在运行,而且我没有遇到错误,我的程序只播放蜂鸣声,而不是我提供的文件。

我希望程序播放我传递给SDL_LoadWAV的.wav文件。

[我尝试了两个不同长度和大小的不同.wav文件,并检查了头文件以找到注释和提示,以了解SDL播放.wav文件所需的格式,但两者均未解决任何问题它。

myAudioCallback函数负责处理SDL回调。

void myAudioCallback(void* userdata, Uint8* stream, int len) 
{
    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

std::cout << "Audio Length " << audio->length << std::endl;
std::cout << "Audio Position " << audio->position << std::endl;

SDL_memcpy(stream, audio->position, length); // audio callback is called by SDL, this ensures that the stream and data that is sent, is copied over to our struct, so we can use it and manipulate it

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

我的loadAudio函数负责加载音频文件并将有关音频文件的信息保存到我在.h中声明的各个变量中(有关我的.h的更多信息,请参见下一节)

void mainEngineCW4::loadAudio() // this function is for the sole purpose of loading the .wav file 
{
    SDL_Init(SDL_INIT_AUDIO); // loads the SDL to initialise audio

char* audioFile = "backgroundmusic.wav"; // a char pointer for the file path

// LoadWAV loads the wav file, and by putting it in an if statement like this, we can simutaneously check if the result is null, meaning an error occured while loading it.
if (SDL_LoadWAV(audioFile, &wavSpec, &wavStart, &wavLength) == NULL)
    std::cerr << "Error: file could not be loaded as an audio file." << std::endl;
else
    std::cout << audioFile << " loaded" << std::endl; 
}

playAudio函数负责加载音频设备并通过音频设备播放音频

void mainEngineCW4::playAudio() // this function is for loading an audio device, and playing the audio through that device 
{
audio.position = wavStart; // define where we start in the audio file
audio.length = wavLength; // define the length of the audio file

wavSpec.callback = myAudioCallback; // the callback variable needs a function that its going to run to be able to call back the audio that is played. assigning the function name to the variable allows it to call that function when needed
wavSpec.userdata = &audio; // the userdata is the audio itself

audioDevice = SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, SDL_AUDIO_ALLOW_ANY_CHANGE); // opens the audio device, also having it play the audio information found at memory address for wavspec
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. 
}

这是我的.h。我已经在类外部定义了myAudioCallback,因为SDL不喜欢成员函数的其他隐藏参数

struct AudioData
{
    Uint8* position;
    Uint32 length;
};

void myAudioCallback(void* userdata, Uint8* stream, int len);

class mainEngineCW4 :
    public BaseEngine
{

public:

    void loadAudio();
    void playAudio();
    void endAudio();

private:
    // variables and pointers for audio information
    AudioData audio;
    SDL_AudioSpec wavSpec;
    SDL_AudioDeviceID audioDevice;
    Uint8* wavStart;
    Uint32 wavLength;
};

我已经删除了与我遇到的问题无关的其他函数和变量

我的问题是,我希望我的程序播放传入的音频文件,而不仅仅是发出噪音。任何帮助都将不胜感激

编辑:我意识到我不愿意提供信息和对事物的解释,所以我编辑了更多信息,解释和头文件。如果还有其他可以提供的信息,请告诉我

c++ sdl wav
1个回答
0
投票

[在朋友的帮助下,我设法解决了这个问题。我通过时似乎SDL不喜欢它

SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, SDL_AUDIO_ALLOW_ANY_CHANGE);

所以我通过了

SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, 0);

相反。这样可以很好地播放文件,并为音频文件的长度和位置提供其他变量。

即使在播放文件后,我仍然遇到另一个问题,就是蜂鸣器仍在播放音频文件。我无法直接自己解决此问题,相反,当我第二天清洗解决方案时,哔哔声消失了,唯一播放的是音频文件。

我已经附上了下面的代码。

除了我在.h中创建的结构之外>

struct AudioData
{
    Uint8* position;
    Uint32 length;
};

将audio_position和audio_length定义为全局变量也有助于复制音频回调函数中的信息。

static Uint8* audio_position;
static Uint32 audio_length;
void myAudioCallback(void* userdata, Uint8* stream, int len)
{
    if (audio_length == 0)
        return;

    len = (len > audio_length ? audio_length : len); // 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, len); // audio callback is called by SDL, this ensures that the stream and data that is sent, is copied over to our struct, so we can use it and manipulate it

    audio_position += len;
    audio_length -= len;
}

对于加载音频,我确保实际上已经加载了所有将被视为“正在加载”的信息,包括存储AudioSpec回调函数以及设置音频文件的长度和位置。

void mainEngineCW4::loadAudio() // this function is for the sole purpose of loading the .wav file
{
    if (SDL_Init(SDL_INIT_AUDIO) < 0 || audioPlaying == true) // loads the SDL to initialise audio
        return;

    char* filePath = "backgroundmusic.wav"; // a char pointer for the file path

    // LoadWAV loads the wav file, and by putting it in an if statement like this, we can simutaneously check if the result is null, meaning an error occured while loading it.
    if (SDL_LoadWAV(filePath, &desiredSpec, &wavStart, &wavLength) == NULL)
        std::cerr << "Error: file could not be loaded as an audio file." << std::endl;
    else
        std::cout << filePath << " loaded" << std::endl;

    desiredSpec.callback = myAudioCallback; // the callback variable needs a function that its going to run to be able to call back the audio that is played. assigning the function name to the variable allows it to call that function when needed
    desiredSpec.userdata = &audioInfo; // the userdata is the audio itself

    audio_position = wavStart; // define where we start in the audio file
    audio_length = wavLength; // define the length of the audio file
}

我还向该类添加了一个布尔值,因此当返回true时,这意味着音频已经在播放或已经加载,以确保SDL不会同时播放相同的东西。

void mainEngineCW4::playAudio() // this function is for loading an audio device, and playing the audio through that device
{
    if (audioPlaying == true)
        return;

    audioDevice = SDL_OpenAudioDevice(NULL, 0, &desiredSpec, NULL, 0); // opens the audio device, also having it play the audio information found at memory address for wavspec

    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.
    audioPlaying = true;
}

void mainEngineCW4::endAudio()
{
    SDL_CloseAudioDevice(audioDevice);
    SDL_FreeWAV(wavStart);
    audioPlaying = false;
    }
© www.soinside.com 2019 - 2024. All rights reserved.