How do I get waveform from OpenAL buffer?

1.7k views Asked by At

I am using OpenAL and ALUT on a project I am working on. I need to get the waveform from the buffer. I am using alutLoadWAVFile to load the data into the buffer. When I output each item in the buffer, I get something like this:

enter image description here

This is not the waveform, because the waveform looks like this in Audacity:

enter image description here

My code (the relevant parts anyway):

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

There are 1 answers

0
AudioBubble On

I'm thinking that what you're expecting is that the buffer data to be exactly what you see in Audacity. This won't really be the case if the wav is anything other than 8Bit Mono (I think anyway, it's been a while).

Also, you seem to be casting data[i] from an unsigned char to an int, which may be another problem.

Also, you might want to attempt manually reading the wav file instead of using ALUT. ALUT is a crutch that makes you weak. :)

Here's a program that reads and plays a wav without ALUT. With it you'll be able to figure out the mono/stereoness and freq of the wav file. Hopefully from there you can start messing with the buffer directly and output exactly what you want.

#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;
}