如何从OpenAL缓冲区获取波形?

时间:2015-06-22 23:48:53

标签: openal

我正在使用OpenAL和ALUT处理我正在进行的项目。我需要从缓冲区中获取波形。我正在使用alutLoadWAVFile将数据加载到缓冲区中。当我输出缓冲区中的每个项目时,我得到这样的结果:

enter image description here

这不是波形,因为Audacity中的波形如下所示:

enter image description here

我的代码(无论如何相关部分):

unsigned char* alBuffer;
...
alutLoadWAVFile((ALbyte*)("test2.wav"), &alFormatBuffer,
    (void **)&alBuffer, (ALsizei*)&alBufferLen, &alFreqBuffer, &alLoop);
...
for (int i = 0; i < (alBufferLen>5000?5000:alBufferLen); i++) {
    log << (int)data[i] << "\n";
}

1 个答案:

答案 0 :(得分:1)

我在想你所期待的是缓冲区数据正是你在Audacity中看到的。如果wav不是8Bit Mono(我认为无论如何,它已经有一段时间了),情况就不是这样了。

此外,您似乎将数据[i]从unsigned char转换为int,这可能是另一个问题。

此外,您可能希望尝试手动读取wav文件而不是使用ALUT。 ALUT是一个让你变弱的拐杖。 :)

这是一个在没有ALUT的情况下读取和播放wav的程序。有了它,你将能够找出wav文件的mono / stereoness和freq。希望你可以从那里开始直接搞乱缓冲区并准确输出你想要的东西。

#include <stdio.h>
#include <AL\al.h>
#include <AL\alc.h>

struct RIFF_Header {
    char chunkID[4];
    long chunkSize;
    char format[4];
};

struct WAVE_Format {
    char subChunkID[4];
    long subChunkSize;
    short audioFormat;
    short numChannels;
    long sampleRate;
    long byteRate;
    short blockAlign;
    short bitsPerSample;
};

struct WAVE_Data {
    char subChunkID[4];
    long subChunk2Size;
};

bool loadWavFile(const char* filename, ALuint* buffer,
                 ALsizei* size, ALsizei* frequency,
                 ALenum* format) {
  FILE* soundFile = NULL;
  WAVE_Format wave_format;
  RIFF_Header riff_header;
  WAVE_Data wave_data;
  unsigned char* data;

  try {
    soundFile = fopen(filename, "rb");
    if (!soundFile)
      throw (filename);

    fread(&riff_header, sizeof(RIFF_Header), 1, soundFile);

    if ((riff_header.chunkID[0] != 'R' ||
         riff_header.chunkID[1] != 'I' ||
         riff_header.chunkID[2] != 'F' ||
         riff_header.chunkID[3] != 'F') &&
        (riff_header.format[0] != 'W' ||
         riff_header.format[1] != 'A' ||
         riff_header.format[2] != 'V' ||
         riff_header.format[3] != 'E'))
             throw ("Invalid RIFF or WAVE Header");

    fread(&wave_format, sizeof(WAVE_Format), 1, soundFile);

    if (wave_format.subChunkID[0] != 'f' ||
        wave_format.subChunkID[1] != 'm' ||
        wave_format.subChunkID[2] != 't' ||
        wave_format.subChunkID[3] != ' ')
             throw ("Invalid Wave Format");

    if (wave_format.subChunkSize > 16)
        fseek(soundFile, sizeof(short), SEEK_CUR);

    fread(&wave_data, sizeof(WAVE_Data), 1, soundFile);

    if (wave_data.subChunkID[0] != 'd' ||
        wave_data.subChunkID[1] != 'a' ||
        wave_data.subChunkID[2] != 't' ||
        wave_data.subChunkID[3] != 'a')
             throw ("Invalid data header");

    data = new unsigned char[wave_data.subChunk2Size];

    if (!fread(data, wave_data.subChunk2Size, 1, soundFile))
        throw ("error loading WAVE data into struct!");

    *size = wave_data.subChunk2Size;
    *frequency = wave_format.sampleRate;

    if (wave_format.numChannels == 1) {
        if (wave_format.bitsPerSample == 8 )
            *format = AL_FORMAT_MONO8;
        else if (wave_format.bitsPerSample == 16)
            *format = AL_FORMAT_MONO16;
    } else if (wave_format.numChannels == 2) {
        if (wave_format.bitsPerSample == 8 )
            *format = AL_FORMAT_STEREO8;
        else if (wave_format.bitsPerSample == 16)
            *format = AL_FORMAT_STEREO16;
    }

    alGenBuffers(1, buffer);
    alBufferData(*buffer, *format, (void*)data,
                 *size, *frequency);
    fclose(soundFile);
    return true;
  } catch(char* error) {
    if (soundFile != NULL)
        fclose(soundFile);
    return false;
  }
}

int main(){

    //Sound play data
    ALint state;                            // The state of the sound source
    ALuint bufferID;                        // The OpenAL sound buffer ID
    ALuint sourceID;                        // The OpenAL sound source
    ALenum format;                          // The sound data format
    ALsizei freq;                           // The frequency of the sound data
    ALsizei size;                           // Data size

    ALCdevice* device = alcOpenDevice(NULL);
    ALCcontext* context = alcCreateContext(device, NULL);
    alcMakeContextCurrent(context);

    // Create sound buffer and source
    alGenBuffers(1, &bufferID);
    alGenSources(1, &sourceID);

    // Set the source and listener to the same location
    alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
    alSource3f(sourceID, AL_POSITION, 0.0f, 0.0f, 0.0f);

    loadWavFile("..\\wavdata\\YOURWAVHERE.wav", &bufferID, &size, &freq, &format);

    alSourcei(sourceID, AL_BUFFER, bufferID);

    alSourcePlay(sourceID);

    do{
        alGetSourcei(sourceID, AL_SOURCE_STATE, &state);
    } while (state != AL_STOPPED);


    alDeleteBuffers(1, &bufferID);
    alDeleteSources(1, &sourceID);
    alcDestroyContext(context);
    alcCloseDevice(device);

    return 0;
}
相关问题