OpenAL Lesson 6:Advancd Loading and Error Handles(転載)


自動回転http://www.devmaster.net/articles/openal-tutorials/lesson6.php
We've been dong some pretty simple stuff up until now that didn't require us to be very precise in the way we've handed things.The reason for this that we have beven writing code for simpcity orease.rather that for robustnes.Since we are going to move some advanced stuuff soon wewewee e e sososoon wewee e some me time to learn the proper ways.Most impopotal we will learararn a more advancnced way of handandandandandandandandandandandandandandaaaaaaaadrdrdrdrdrdrdrdrdrdrdrdrdrerrorsrsrse e e e.Weaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaain particular、but we will need a more organized and flexible approach to the process.
We will first consider a few functions that will help us out a lot by the time we have finished.

  
  
  
  
string  GetALErrorString(ALenum err);
/*
 * 1) Identify the error code.
 * 2) Return the error as a string.
 
*/


string  GetALCErrorString(ALenum err);
/*
 * 1) Identify the error code.
 * 2) Return the error as a string.
 
*/


ALuint LoadALBuffer(
string  path);
/*
 * 1) Creates a buffer.
 * 2) Loads a wav file into the buffer.
 * 3) Returns the buffer id.
 
*/


ALuint GetLoadedALBuffer(
string  path);
/*
 * 1) Checks if file has already been loaded.
 * 2) If it has been loaded already, return the buffer id.
 * 3) If it has not been loaded, load it and return buffer id.
 
*/


ALuint LoadALSample(
string  path,  bool  loop);
/*
 * 1) Creates a source.
 * 2) Calls 'GetLoadedALBuffer' with 'path' and uses the
 *    returned buffer id as it's sources buffer.
 * 3) Returns the source id.
 
*/


void  KillALLoadedData();
/*
 * 1) Releases temporary loading phase data.
 
*/


bool  LoadALData();
/*
 * 1) Loads all buffers and sources for the application.
 
*/


void  KillALData();
/*
 * 1) Releases all buffers.
 * 2) Releases all sources.
 
*/


vector
< string >  LoadedFiles;  //  Holds loaded file paths temporarily.
vector < ALuint >  Buffers;  //  Holds all loaded buffers.
vector < ALuint >  Sources;  //  Holds all validated sources.
Take a close look the functitins and try to undestand what we arargoing to be doing.Baicallywhat wearararararar trying to create isa sssysstem in whihich weのlonger have to woryaout therelatitititititititititititititititititititititishshshshshshshshshshshshshshshshshshshshshshaaaaaaaaaaaaaaaaaathelalalalalatitititititititititititititititititititishshshshshshshshshshshshshshshshshshshsheation on it's own so we don't duplicate a buffer.This system will hall handle the buffers.and will handle the buffers.

  
  
  
  
string  GetALErrorString(ALenum err)
{
    
switch(err)
    
{
        
case AL_NO_ERROR:
            
return string("AL_NO_ERROR");
        
break;

        
case AL_INVALID_NAME:
            
return string("AL_INVALID_NAME");
        
break;

        
case AL_INVALID_ENUM:
            
return string("AL_INVALID_ENUM");
        
break;

        
case AL_INVALID_VALUE:
            
return string("AL_INVALID_VALUE");
        
break;

        
case AL_INVALID_OPERATION:
            
return string("AL_INVALID_OPERATION");
        
break;

        
case AL_OUT_OF_MEMORY:
            
return string("AL_OUT_OF_MEMORY");
        
break;
    }
;
}

This function will convert an OpenAL error code to a string so it can be read on on the consone.The OpenAL sdk says the only exception that need for in the currother device.The OpenAL sdk the ALverisOUT.OF_MEMORY'error.However,we will account for all the errors so that our code will be up to date with later versions.

  
  
  
  
string  GetALCErrorString(ALenum err)
{
    
switch(err)
    
{
        
case ALC_NO_ERROR:
            
return string("AL_NO_ERROR");
        
break;

        
case ALC_INVALID_DEVICE:
            
return string("ALC_INVALID_DEVICE");
        
break;

        
case ALC_INVALID_CONTEXT:
            
return string("ALC_INVALID_CONTEXT");
        
break;

        
case ALC_INVALID_ENUM:
            
return string("ALC_INVALID_ENUM");
        
break;

        
case ALC_INVALID_VALUE:
            
return string("ALC_INVALID_VALUE");
        
break;

        
case ALC_OUT_OF_MEMORY:
            
return string("ALC_OUT_OF_MEMORY");
        
break;
    }
;
}

This function will perform a simiar task a s the previous one accept this one will interpret Alc errors.OpenAL and Alc shar comon id id's,but not common enough and not dissimilar engh to usthe funce bonction.
One more note about the function'alGetErrror':The OpenAL sdk defines that it only holds a single error at time(i.e.there isのstacking).When the function is invoked it will the fiturn the the firersNOの_ERROR'.In other words an error will only be stored in the error bit ifのprevious error is already stored there.

  
  
  
  
ALuint LoadALBuffer( string  path)
{
    
// Variables to store data which defines the buffer.
    ALenum format;
    ALsizei size;
    ALvoid
* data;
    ALsizei freq;
    ALboolean loop;

    
// Buffer id and error checking variable.
    ALuint buffer;
    ALenum result;

    
// Generate a buffer. Check that it was created successfully.
    alGenBuffers(1&buffer);

    
if ((result = alGetError()) != AL_NO_ERROR)
        
throw GetALErrorString(result);

    
// Read in the wav data from file. Check that it loaded correctly.
    alutLoadWAVFile(szFilePath, &format, &data, &size, &freq, &loop);

    
if ((result = alGetError()) != AL_NO_ERROR)
        
throw GetALErrorString(result);

    
// Send the wav data into the buffer. Check that it was received properly.
    alBufferData(buffer, format, data, size, freq);

    
if ((result = alGetError()) != AL_NO_ERROR)
        
throw GetALErrorString(result);

    
// Get rid of the temporary data.
    alutUnloadWAV(format, data, size, freq);

    
if ((result = alGetError()) != AL_NO_ERROR)
        
throw GetALErrorString(result);

    
// Return the buffer id.
    return buffer;
}

As You can see we don error check atery possible phase of the load.Any number of things can happen at this point which will cause an error to be thrown.The could beのmore system the the afficeor an invalid value can be passed to any one of the OpenAL functions which will generanter.

  
  
  
  
ALuint GetLoadedALBuffer( string  path)
{
    
int count = 0// 'count' will be an index to the buffer list.

    ALuint buffer; 
// Buffer id for the loaded buffer.


    
// Iterate through each file path in the list.
    for(vector<string>::iterator iter = LoadedFiles.begin(); iter != LoadedFiles.end(); ++iter, count++)
    
{
        
// If this file path matches one we have loaded already, return the buffer id for it.
        if(*iter == path)
            
return Buffers[count];
    }


    
// If we have made it this far then this file is new and we will create a buffer for it.
    buffer = LoadALBuffer(path);

    
// Add this new buffer to the list, and register that this file has been loaded already.
    Buffers.push_back(buffer);

    LoadedFiles.push_back(path);

    
return buffer;
}

This Will probably be the piece of code most people have trouble with、but it's really not that coplex.We are dong a search through a list which contains the file paths of all the wav's weve the atwith the atch the atwith the atch the atch the atwith.we will simply return the id to the buffer we loaded it into the first time.This way as long as we consistently load our files through this function、Every file loaded this is way must also be kept trat t t of with it's lololololololoth th th the the the the aath the the ath th thethethe aath th thethe aath th th thethe aaath thethethe aaath th thethethethethethethethethe aaaaaath th th thethethethethes s s s s s s s s s s s s s s s s s s s s s s s s s s s s thethethethethethethethethethethethethethethethethethethethethethethethetheaaaaaaaaaaaaaaaaaaaaaaaaaaabuffer was created.

  
  
  
  
ALuint LoadALSample( string  path,  bool  loop)
{
    ALuint source;
    ALuint buffer;
    ALenum result;

    
// Get the files buffer id (load it if necessary).
    buffer = GetLoadedALBuffer(path);

    
// Generate a source.
    alGenSources(1 &source);

    
if ((result = alGetError()) != AL_NO_ERROR)
        
throw GetALErrorString(result);

    
// Setup the source properties.
    alSourcei (source, AL_BUFFER,   buffer   );
    alSourcef (source, AL_PITCH,    
1.0      );
    alSourcef (source, AL_GAIN,     
1.0      );
    alSourcefv(source, AL_POSITION, SourcePos);
    alSourcefv(source, AL_VELOCITY, SourceVel);
    alSourcei (source, AL_LOOPING,  loop     );

    
// Save the source id.
    Sources.push_back(source);

    
// Return the source id.
    return source;
}

Now that we have created a sysstem which will handlee the buffers fors、we just need andandaeeeeeeeeeextetetest itthththwill get the sources.In this code we ooaaaaaaaaasearch forthethethethe file file、whihisisisisisisisisisisithe the the thethe the the thethethethe the the the the file file、whihihihihisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisiy and also return it.

  
  
  
  
void  KillALLoadedData()
{
    LoadedFiles.clear();
}

The global vector'gloaded Filesv'stored the file path of everware file that was loaded into a buffer.It doesn't makense to keep this data lydand after we loaded all of our data.sowell dill of.

  
  
  
  
//  Source id's.

ALuint phaser1;
ALuint phaser2;

void  LoadALData()
{
    
// Anything for your application here. No worrying about buffers.
    phaser1 = LoadALSample("wavdata/phaser.wav"false);
    phaser2 
= LoadALSample("wavdata/phaser.wav"true);

    KillLoadedALData();
}

ウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェウェブブブブブブブブブオフオフオフオフオフオフオフオフオフオフオフオフオフオフオフオフオフオフオフオフ. In it we see whyuseeeeeeemimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimibe created onece,and the sources'gPhasher 1'and'gPhasher 2'will both use that buffer for playbank.The isのmore concern for handing buffers because the system will handle the m autically.

  
  
  
  
void  KillALData()
{
    
// Release all buffer data.
    for (vector<ALuint>::iterator iter = Buffers.begin(); iter != Buffers.end(); ++iter)
        alDeleteBuffers(
1, iter);

    
// Release all source data.
    for (vector<ALuint>::iterator iter = Sources.begin(); iter != Sources.end(); ++iter)
        alDeleteBuffers(
1, iter);

    
// Destroy the lists.
    Buffers.clear();
    Sources.clear();
}

All along we have beve storing the buffer and source id's into stl vectors.We free all the buffers and sources by go througthe m and releasing the m individually.After which we deoy the alth the alth Alftwith the ALtch.
   
  
  
  
  
  try
    
{
        InitOpenAL();

        LoadALData();
    }

    
catch ( string  err)
    
{
        cout 
<< "OpenAL error: " << err.c_str() << endl;
    }

If something has gone wrong during the course of the load we will be notified of it right away.When we catch the error it will be reported on the consold.We can use this for debuggggggg or generaner reporting.
That's it.A more advanced way of reporting errors,and a more robust way of loading your wav files.We may find we need to some modifications in the future to allow for freexbility,but for futurity withwith.