[Openal] Loading .wav using OpenAL SDK 1.1 for Windows

Casey Borders thebeast.13 at gmail.com
Sat Nov 10 08:04:00 PST 2007


I have put together some code that works from looking at alut and some
various bits of code around the internet.  I use it in my OgreAL project (
http://www.ogre3d.org/phpBB2addons/viewforum.php?f=10), which integrates
OpenAL seamlessly into the Ogre Rendering Engine(www.ogre3d.org).  Anyway,
here's that bit of code.

try
{
     mLoop = loop?AL_TRUE:AL_FALSE;

    // buffers
    char magic[5];
    magic[4] = '\0';
    unsigned char buffer32[4];
    unsigned char buffer16[2];

    // check magic
    CheckCondition(mSoundStream->read(magic, 4) == 4, 13, "Cannot read wav
file " + mFileName);
    CheckCondition(std::string(magic) == "RIFF", 13, "Wrong wav file format.
This file is not a .wav file (no RIFF magic): " + mFileName);

    // The next 4 bytes are the file size, we can skip this since we get the
size from the DataStream
    mSoundStream->skip(4);
    mSize = static_cast<Size>(mSoundStream->size());

    // check file format
    CheckCondition(mSoundStream->read(magic, 4) == 4, 13, "Cannot read wav
file " + mFileName);
    CheckCondition(std::string(magic) == "WAVE", 13, "Wrong wav file format.
This file is not a .wav file (no WAVE format): " + mFileName);

    // check 'fmt ' sub chunk (1)
    CheckCondition(mSoundStream->read(magic, 4) == 4, 13, "Cannot read wav
file " + mFileName);
    CheckCondition(std::string(magic) == "fmt ", 13, "Wrong wav file format.
This file is not a .wav file (no 'fmt ' subchunk): " + mFileName);

    // read (1)'s size
    CheckCondition(mSoundStream->read(buffer32, 4) == 4, 13, "Cannot read
wav file " + mFileName);
    unsigned long subChunk1Size = readByte32(buffer32);
    CheckCondition(subChunk1Size >= 16, 13, "Wrong wav file format. This
file is not a .wav file ('fmt ' chunk too small, truncated file?): " +
mFileName);

    // check PCM audio format
    CheckCondition(mSoundStream->read(buffer16, 2) == 2, 13, "Cannot read
wav file " + mFileName);
    unsigned short audioFormat = readByte16(buffer16);
    CheckCondition(audioFormat == 1, 13, "Wrong wav file format. This file
is not a .wav file (audio format is not PCM): " + mFileName);

    // read number of channels
    CheckCondition(mSoundStream->read(buffer16, 2) == 2, 13, "Cannot read
wav file " + mFileName);
    unsigned short channels = readByte16(buffer16);

    // read frequency (sample rate)
    CheckCondition(mSoundStream->read(buffer32, 4) == 4, 13, "Cannot read
wav file " + mFileName);
    mFreq = readByte32(buffer32);

    // skip 6 bytes (Byte rate (4), Block align (2))
    mSoundStream->skip(6);

    // read bits per sample
    CheckCondition(mSoundStream->read(buffer16, 2) == 2, 13, "Cannot read
wav file " + mFileName);
    unsigned short bps = readByte16(buffer16);

    if (channels == 1)
    {
        if(bps == 8)
        {
            mFormat = AL_FORMAT_MONO8;
            // Set BufferSize to 250ms (Frequency divided by 4 (quarter of a
second))
            mBufferSize = mFreq / 4;
        }
        else
        {
            mFormat = AL_FORMAT_MONO16;
            // Set BufferSize to 250ms (Frequency * 2 (16bit) divided by 4
(quarter of a second))
            mBufferSize = mFreq >> 1;
            // IMPORTANT : The Buffer Size must be an exact multiple of the
BlockAlignment ...
            mBufferSize -= (mBufferSize % 2);
        }
    }
    else
    {
        if(bps == 8)
        {
            mFormat = AL_FORMAT_STEREO16;
            // Set BufferSize to 250ms (Frequency * 2 (8bit stereo) divided
by 4 (quarter of a second))
            mBufferSize = mFreq >> 1;
            // IMPORTANT : The Buffer Size must be an exact multiple of the
BlockAlignment ...
            mBufferSize -= (mBufferSize % 2);
        }
        else
        {
            mFormat = AL_FORMAT_STEREO16;
            // Set BufferSize to 250ms (Frequency * 4 (16bit stereo) divided
by 4 (quarter of a second))
            mBufferSize = mFreq;
            // IMPORTANT : The Buffer Size must be an exact multiple of the
BlockAlignment ...
            mBufferSize -= (mBufferSize % 4);
        }
    }

    // check 'data' sub chunk (2)
    CheckCondition(mSoundStream->read(magic, 4) == 4, 13, "Cannot read wav
file " + mFileName);
    CheckCondition(std::string(magic) == "data" || std::string(magic) ==
"fact", 13, "Wrong wav file format. This file is not a .wav file (no data
subchunk): " + mFileName);

    // fact is an option section we don't need to worry about
    if(std::string(magic) == "fact")
    {
        mSoundStream->skip(8);

        // Now we shoudl hit the data chunk
        CheckCondition(mSoundStream->read(magic, 4) == 4, 13, "Cannot read
wav file " + mFileName);
        CheckCondition(std::string(magic) == "data", 13, "Wrong wav file
format. This file is not a .wav file (no data subchunk): " + mFileName);
    }

    // The next four bytes are the size remaing of the file
    CheckCondition(mSoundStream->read(buffer32, 4) == 4, 13, "Cannot read
wav file " + mFileName);
    unsigned long remainingSize = readByte32(buffer32);
    mDataStart = mSoundStream->tell();

    mBuffers = new BufferRef[mNumBuffers];
    alGenBuffers(mNumBuffers, mBuffers);
    CheckError(alGetError(), "Could not generate buffer");

    for(int i = 0; i < mNumBuffers; i++)
    {
        CheckCondition(AL_NONE != mBuffers[i], 13, "Could not generate
buffer");
        Buffer buffer = bufferData(mSoundStream,
mStream?mBufferSize:remainingSize);
        alBufferData(mBuffers[i], mFormat, &buffer[0], static_cast<Size>(
buffer.size()), mFreq);
        CheckError(alGetError(), "Could not load buffer data");
    }
}
catch(Ogre::Exception e)
{
    for(int i = 0; i < mNumBuffers; i++)
    {
        if (mBuffers[i] && alIsBuffer(mBuffers[i]) == AL_TRUE)
        {
            alDeleteBuffers(1, &mBuffers[i]);
            CheckError(alGetError(), "Failed to delete Buffer");
        }
    }

    throw (e);
}

In the code mSoundStream is an Ogre::DataStream, which is specific to Ogre,
but you could replace it with an std::istream, or you could use a FILE* and
replace the stream access with fread, etc.

On Nov 10, 2007 10:37 AM, Nana Yaw <supremestar at hotmail.com> wrote:

>  Hello,
> I'm new to OpenAL.  I'm want to load a simple .wav file and have it played
> but I'm having defficulties.
> alut is deprecated in SDK 1.1 and so visul studio .Net 2005 prevents me
> from using it.
>
> Is there any way around it?  Please help.
>
> regards
>
> ------------------------------
> Invite your mail contacts to join your friends list with Windows Live
> Spaces. It's easy! Try it!<http://spaces.live.com/spacesapi.aspx?wx_action=create&wx_url=/friends.aspx&mkt=en-us>
>
> _______________________________________________
> Openal mailing list
> Openal at opensource.creative.com
> http://opensource.creative.com/mailman/listinfo/openal
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://opensource.creative.com/pipermail/openal/attachments/20071110/6848e772/attachment.html


More information about the Openal mailing list