Logo Search packages:      
Sourcecode: qcake version File versions  Download package

audioenv.cpp

/****************************************************************************

   PROGRAM: audioenv.cpp

   DESCRIPTION: audio object class code

****************************************************************************/
#include "audioenv.hpp"
#include "Obstruct.h"
#include <string.h>
#include <errno.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#ifdef WINDOWS // use EAX for Windows
// #define USE_EAX
#endif

// EAX-test
// add initguid.h under Windows
#ifdef USE_EAX
#define OPENAL
#ifdef WINDOWS
#include <initguid.h>
#else
#define INITGUID
#endif
#include "eax.h"
#endif // USE_EAX


/* our vorbis extension */
#define VORBIS_FUNC    "alutLoadVorbis_LOKI"
typedef ALboolean (vorbisLoader)(ALuint, ALvoid *, ALint);
vorbisLoader *alutLoadVorbisp = NULL;

AudioEnv * AudioEnv::theInstancePtr = 0;
// constructor
AudioEnv::AudioEnv (QObject *parent): QObject(parent)
{
      nextBuffer = 0;
      nextSource = 0;
      EAXlevel = 0;
}

// destructor
AudioEnv::~AudioEnv ()
{
      alutExit();
}
AudioEnv * AudioEnv::theInstance(QObject *parent) {
    if (theInstancePtr == 0) {
        theInstancePtr = new AudioEnv(parent);
      theInstancePtr->Init();
    }
    return theInstancePtr;
}

// init
void AudioEnv::Init ()
{
   alutInit (NULL, 0); // init OpenAL

   // global settings
   alListenerf(AL_GAIN, 1.0);
   alDopplerFactor(1.0); // don't exaggerate doppler shift
   alDopplerVelocity(343); // using meters/second

#ifdef USE_EAX
   // determine EAX support level
      if (alIsExtensionPresent((ALubyte *)"EAX2.0") == AL_TRUE)
      {
            EAXlevel = 2;
      } else
      {
            if (alIsExtensionPresent((ALubyte *)"EAX") == AL_TRUE)
            {
                  EAXlevel = 1;
            }
      }

   // set EAX environment if EAX is available
      EAXSet pfPropSet;
      EAXGet pfPropGet;
      unsigned long ulEAXVal;
      long lGlobalReverb;
      if (EAXlevel != 0)
      {
            pfPropSet = (EAXSet) alGetProcAddress((ALubyte *)"EAXSet");
            if (pfPropSet != NULL)
            {
                lGlobalReverb = -10000;
                  pfPropSet(&DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ROOM, 0, &lGlobalReverb, sizeof(unsigned long));
                  ulEAXVal = EAX_ENVIRONMENT_GENERIC;
                  pfPropSet(&DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, 0, &ulEAXVal, sizeof(unsigned long));
            }
      }
#endif // USE_EAX
}

// ListenerPostition -- update listener's position and direction
void AudioEnv::ListenerPosition (float c[4][4])
{
float orient[6];
float position[3];
  position[0] = -c[0][0]*c[3][0]-c[0][1]*c[3][1]-c[0][2]*c[3][2];
  position[1] = -c[1][0]*c[3][0]-c[1][1]*c[3][1]-c[1][2]*c[3][2];
  position[2] = -c[2][0]*c[3][0]-c[2][1]*c[3][1]-c[2][2]*c[3][2];
      alListenerfv(AL_POSITION, position);
      orient[0] = -c[0][2];
      orient[1] = -c[1][2];
      orient[2] = -c[2][2];
      orient[3] = c[0][1];
      orient[4] = c[1][1];
      orient[5] = c[2][1];
      alListenerfv(AL_ORIENTATION, orient);
}

// UpdateObstruction -- update obstruction value for a specific source, using EAX if available
void AudioEnv::UpdateObstruction (int handle)
{
      SVector lposition, sposition;

      alGetListenerfv(AL_POSITION, (float *) &lposition);
      alGetSourcefv(source[handle -1], AL_POSITION, (float *) &sposition);

      // location of each "house"
      SVector svMinHouse1, svMinHouse2, svMaxHouse1, svMaxHouse2;
      svMinHouse1.fX = 0;
      svMaxHouse1.fX = 9;
      svMinHouse1.fY = -100;
      svMaxHouse1.fY = 100;
      svMinHouse1.fZ = -9;
      svMaxHouse1.fZ = 0;

      svMinHouse2.fX = 24;
      svMaxHouse2.fX = 33;
      svMinHouse2.fY = -100;
      svMaxHouse2.fY = 100;
      svMinHouse2.fZ = 9;
      svMaxHouse2.fZ = 18;

// calculate "obstruction level" from 0 to 1
//    float obstructionLevel1 = GetObstructionLevel(lposition, sposition, svMinHouse1, svMaxHouse1);
//    float obstructionLevel2 = GetObstructionLevel(lposition, sposition, svMinHouse2, svMaxHouse2);

      // use value for the house that obstructs the most (lower value)

  float obstructionLevel =0;
/*
      if (obstructionLevel1 < obstructionLevel2)
      {
            obstructionLevel = obstructionLevel1;
      } else
      {
            obstructionLevel = obstructionLevel2;
      }

      //exaggerate obstruction level
      obstructionLevel = (obstructionLevel - 0.98f) * 50.0f;
      if (obstructionLevel < 0)
      {
            obstructionLevel = 0;
      }
*/
#ifdef USE_EAX
      if (EAXlevel == 2)
      {
            // have EAX 2.0, so apply the obstruction
            EAXSet pfPropSet = (EAXSet) alGetProcAddress((ALubyte *)"EAXSet");
            float fvalue = 0.25;
            pfPropSet(&DSPROPSETID_EAX_SourceProperties, DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, source[handle-1], &fvalue, sizeof(float));
            long obstruction = (long) ((1.0f - obstructionLevel) * -10000.0f);
            pfPropSet(&DSPROPSETID_EAX_SourceProperties, DSPROPERTY_EAXBUFFER_OBSTRUCTION, source[handle-1], &obstruction, sizeof(long));
      } else
      {
#endif // USE_EAX
            // the non-EAX case should really involve low-pass filtering, but we'll just do a gain control here...
            alSourcef(source[handle -1], AL_GAIN, obstructionLevel);
#ifdef USE_EAX
      }
#endif // USE_EAX
}

// LoadFile -- loads a file into a buffer and source
int AudioEnv::LoadFile (const char *filename, bool loop)
{
      struct stat sbuf;
   FILE *fh;

   // create buffer
   alGetError(); /* clear */
   alGenBuffers(1, &buffer[nextBuffer]);
   if(alGetError() != AL_NO_ERROR) {
         return 0;
   }

   // create source
   alGetError(); /* clear */
   alGenSources(1, &source[nextSource]);
   if(alGetError() != AL_NO_ERROR) {
         return 0;
   }

   // load data into buffer
#ifdef WINDOWS       
   ALsizei size, freq;
   ALenum format;
   ALvoid *data;
   ALboolean looping;
   
   if(strstr(filename,".wav") != NULL)
   {
     alutLoadWAVFile((ALbyte *)filename, &format, &data, &size, &freq, &looping);
     alBufferData (buffer[nextBuffer], format, data, size, freq);
   }
#endif
#ifdef MACOS
   ALsizei size, freq;
   ALenum format;
   ALvoid *data;
   
   if(strstr(filename,".wav") != NULL)
   {
    alutLoadWAVFile((ALbyte *)filename, &format, &data, &size, &freq);
    alBufferData (buffer[nextBuffer], format, data, size, freq);
   }
#endif
#ifdef LINUX
   ALsizei size, freq;
   ALenum format;
   ALvoid *data;
   ALboolean looping;

   if(strstr(filename,".wav") != NULL)
   {
     alutLoadWAVFile((ALbyte *)filename, &format, &data, &size, &freq, &looping);
     alBufferData (buffer[nextBuffer], format, data, size, freq);
   }
#endif

   if(strstr(filename,".ogg") != NULL)
   {
          if(stat(filename, &sbuf) == -1) {
                perror(filename);
                return errno;
          }

      size = sbuf.st_size;
          data = malloc(size);
          if(data == NULL) {
                exit(1);
          }

          fh = fopen(filename, "rb");
          if(fh == NULL) {
                fprintf(stderr, "Could not open %s\n", filename);
                free(data);
                exit(1);
         }

         fread(data, size, 1, fh);

#ifdef LINUX
    // debian sarge 
    //         alutLoadVorbisp = (vorbisLoader *) alGetProcAddress((ALubyte *) VORBIS_FUNC);
    // debian etch  
         alutLoadVorbisp = (vorbisLoader *) alGetProcAddress( VORBIS_FUNC);
#endif

#ifdef MACOS
         alutLoadVorbisp = (vorbisLoader *) alGetProcAddress((ALubyte *) VORBIS_FUNC);
#endif

#ifdef WINDOWS
         alutLoadVorbisp = (vorbisLoader *) alGetProcAddress( VORBIS_FUNC);
#endif

     if(alutLoadVorbisp == NULL) {
               free(data);
               fprintf(stderr, "Could not GetProc %s\n",
                   (ALubyte *) VORBIS_FUNC);
#ifdef Q_OS_IRIX
               exit(-4);
#endif
               return 0;
         }
     
     alGenBuffers( 1, &buffer[nextBuffer]);

         if(alutLoadVorbisp(buffer[nextBuffer], data, size) != AL_TRUE) {
               fprintf(stderr, "alutLoadVorbis failed\n");
#ifdef Q_OS_IRIX
               exit(-2);
#endif
               return 0;
         }

         free(data);
     // set static source properties
     alSourcei(source[nextSource], AL_BUFFER, buffer[nextBuffer]);
     alSourcei(source[nextSource], AL_LOOPING, 1);
     alSourcef(source[nextSource], AL_REFERENCE_DISTANCE, 10);

     nextBuffer++;
     nextSource++;
     return nextBuffer;
   }

   alBufferData (buffer[nextBuffer], format, data, size, freq);
//#endif   

   // set static source properties
   alSourcei(source[nextSource], AL_BUFFER, buffer[nextBuffer]);
   alSourcei(source[nextSource], AL_LOOPING, 1);
   alSourcef(source[nextSource], AL_REFERENCE_DISTANCE, 10);

   nextBuffer++;
   nextSource++;
   return nextBuffer;
}

// Playfile -- loads a file into a buffer and source, then plays it
int AudioEnv::PlayFile (char *filename, bool loop)
{
      int loadhandle;

      loadhandle = LoadFile(filename, loop);

      if (loadhandle != 0) { 
            Play(loadhandle); 
      } else
      {
            return 0;
      }

      return loadhandle;
}

//SetSourcePosition
void AudioEnv::SetSourcePosition (int handle, float *position)
{
      alSourcefv(source[handle-1], AL_POSITION, position);
}

//SetSourceVelocity
void AudioEnv::SetSourceVelocity (int handle, float *velocity)
{
      alSourcefv(source[handle-1], AL_VELOCITY, velocity);
}

//SetSourceGain
void AudioEnv::SetSourceGain (int handle, float gain)
{
      alSourcef(source[handle-1], AL_GAIN, gain);
}

// Play
void AudioEnv::Play(int handle)
{
      alSourcePlay(source[handle-1]); 
}

// Stop
void AudioEnv::Stop(int handle)
{
      alSourceStop(source[handle-1]);
}

void AudioEnv::Loop(int handle, int flag)
{
   alSourcei(source[handle-1], AL_LOOPING, flag);
}

void AudioEnv::Relative(int handle, int flag)
{
   alSourcei(source[handle-1], AL_SOURCE_RELATIVE, flag);
}

int AudioEnv::IsPlaying(int handle)
{
      ALint state;

      if(alIsSource(handle-1) == AL_FALSE) {
//          return 0;
      }

      state = AL_INITIAL;
      alGetSourcei(source[handle-1], AL_SOURCE_STATE, &state);
      switch(state) {
            case AL_PLAYING:
            case AL_PAUSED:
              return 1;
            default:
              break;
      }

      return 0;
  }


// IncrementEnv -- steps through the global environment presets if available
int AudioEnv::IncrementEnv()
{
#ifdef USE_EAX
    // increment EAX environment if EAX is available
      EAXSet pfPropSet;
      EAXGet pfPropGet;
      long lEAXVal;
      static unsigned long ulEAXEnv = 0;
      if (EAXlevel != 0)
      {
            pfPropSet = (EAXSet) alGetProcAddress((ALubyte *)"EAXSet");
            if (pfPropSet != NULL)
            {
                lEAXVal = -10000;
                  pfPropSet(&DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ROOM, 0, &lEAXVal, sizeof(long));
                  ulEAXEnv += 1;
                  if (ulEAXEnv >= EAX_ENVIRONMENT_COUNT) { ulEAXEnv = EAX_ENVIRONMENT_GENERIC; }
                  pfPropSet(&DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, 0, &ulEAXEnv, sizeof(unsigned long));
            }
      }
      return (int) ulEAXEnv;
#else // not using EAX
      return 0;
#endif // USE_EAX
}




Generated by  Doxygen 1.6.0   Back to index