3D Audio GSoC:
authorJoerg Mueller <nexyon@gmail.com>
Tue, 21 Jun 2011 20:24:40 +0000 (20:24 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Tue, 21 Jun 2011 20:24:40 +0000 (20:24 +0000)
- Implemented a nice rechanneling solution with unofficial speaker arrangement standards similar to what OpenAL soft has
- Renamend AUD_Channel in the C API to AUD_Handle
- Removed the unlogical 7.2 speaker configuration, that's a hardware only config

intern/audaspace/intern/AUD_C-API.cpp
intern/audaspace/intern/AUD_C-API.h
intern/audaspace/intern/AUD_ChannelMapperFactory.cpp
intern/audaspace/intern/AUD_ChannelMapperFactory.h
intern/audaspace/intern/AUD_ChannelMapperReader.cpp
intern/audaspace/intern/AUD_ChannelMapperReader.h
intern/audaspace/intern/AUD_DefaultMixer.cpp
intern/audaspace/intern/AUD_Space.h
source/blender/blenkernel/intern/sound.c
source/gameengine/Ketsji/KX_SoundActuator.h

index fc693be12d5dc9c14cbd42ba42b36a9f3e63e49c..62888da14c337c5031c8566c7e15d2ee2562b258 100644 (file)
@@ -90,7 +90,7 @@ extern "C" {
 
 typedef AUD_Reference<AUD_IFactory> AUD_Sound;
 typedef AUD_Reference<AUD_ReadDevice> AUD_Device;
-typedef AUD_Reference<AUD_IHandle> AUD_Channel;
+typedef AUD_Reference<AUD_IHandle> AUD_Handle;
 typedef AUD_Reference<AUD_SequencerEntry> AUD_SEntry;
 
 #define AUD_CAPI_IMPLEMENTATION
@@ -374,7 +374,7 @@ AUD_Sound* AUD_loopSound(AUD_Sound* sound)
        }
 }
 
-int AUD_setLoop(AUD_Channel* handle, int loops)
+int AUD_setLoop(AUD_Handle* handle, int loops)
 {
        assert(handle);
 
@@ -409,14 +409,14 @@ void AUD_unload(AUD_Sound* sound)
        delete sound;
 }
 
-AUD_Channel* AUD_play(AUD_Sound* sound, int keep)
+AUD_Handle* AUD_play(AUD_Sound* sound, int keep)
 {
        assert(sound);
        try
        {
-               AUD_Channel channel = AUD_device->play(*sound, keep);
-               if(!channel.isNull())
-                       return new AUD_Channel(channel);
+               AUD_Handle handle = AUD_device->play(*sound, keep);
+               if(!handle.isNull())
+                       return new AUD_Handle(handle);
        }
        catch(AUD_Exception&)
        {
@@ -424,19 +424,19 @@ AUD_Channel* AUD_play(AUD_Sound* sound, int keep)
        return NULL;
 }
 
-int AUD_pause(AUD_Channel* handle)
+int AUD_pause(AUD_Handle* handle)
 {
        assert(handle);
        return (*handle)->pause();
 }
 
-int AUD_resume(AUD_Channel* handle)
+int AUD_resume(AUD_Handle* handle)
 {
        assert(handle);
        return (*handle)->resume();
 }
 
-int AUD_stop(AUD_Channel* handle)
+int AUD_stop(AUD_Handle* handle)
 {
        assert(handle);
        int result = (*handle)->stop();
@@ -444,25 +444,25 @@ int AUD_stop(AUD_Channel* handle)
        return result;
 }
 
-int AUD_setKeep(AUD_Channel* handle, int keep)
+int AUD_setKeep(AUD_Handle* handle, int keep)
 {
        assert(handle);
        return (*handle)->setKeep(keep);
 }
 
-int AUD_seek(AUD_Channel* handle, float seekTo)
+int AUD_seek(AUD_Handle* handle, float seekTo)
 {
        assert(handle);
        return (*handle)->seek(seekTo);
 }
 
-float AUD_getPosition(AUD_Channel* handle)
+float AUD_getPosition(AUD_Handle* handle)
 {
        assert(handle);
        return (*handle)->getPosition();
 }
 
-AUD_Status AUD_getStatus(AUD_Channel* handle)
+AUD_Status AUD_getStatus(AUD_Handle* handle)
 {
        assert(handle);
        return (*handle)->getStatus();
@@ -537,7 +537,7 @@ int AUD_setDistanceModel(AUD_DistanceModel model)
        return false;
 }
 
-int AUD_setSourceLocation(AUD_Channel* handle, const float* location)
+int AUD_setSourceLocation(AUD_Handle* handle, const float* location)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -551,7 +551,7 @@ int AUD_setSourceLocation(AUD_Channel* handle, const float* location)
        return false;
 }
 
-int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity)
+int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -565,7 +565,7 @@ int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity)
        return false;
 }
 
-int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation)
+int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -579,7 +579,7 @@ int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation)
        return false;
 }
 
-int AUD_setRelative(AUD_Channel* handle, int relative)
+int AUD_setRelative(AUD_Handle* handle, int relative)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -592,7 +592,7 @@ int AUD_setRelative(AUD_Channel* handle, int relative)
        return false;
 }
 
-int AUD_setVolumeMaximum(AUD_Channel* handle, float volume)
+int AUD_setVolumeMaximum(AUD_Handle* handle, float volume)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -605,7 +605,7 @@ int AUD_setVolumeMaximum(AUD_Channel* handle, float volume)
        return false;
 }
 
-int AUD_setVolumeMinimum(AUD_Channel* handle, float volume)
+int AUD_setVolumeMinimum(AUD_Handle* handle, float volume)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -618,7 +618,7 @@ int AUD_setVolumeMinimum(AUD_Channel* handle, float volume)
        return false;
 }
 
-int AUD_setDistanceMaximum(AUD_Channel* handle, float distance)
+int AUD_setDistanceMaximum(AUD_Handle* handle, float distance)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -631,7 +631,7 @@ int AUD_setDistanceMaximum(AUD_Channel* handle, float distance)
        return false;
 }
 
-int AUD_setDistanceReference(AUD_Channel* handle, float distance)
+int AUD_setDistanceReference(AUD_Handle* handle, float distance)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -644,7 +644,7 @@ int AUD_setDistanceReference(AUD_Channel* handle, float distance)
        return false;
 }
 
-int AUD_setAttenuation(AUD_Channel* handle, float factor)
+int AUD_setAttenuation(AUD_Handle* handle, float factor)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -657,7 +657,7 @@ int AUD_setAttenuation(AUD_Channel* handle, float factor)
        return false;
 }
 
-int AUD_setConeAngleOuter(AUD_Channel* handle, float angle)
+int AUD_setConeAngleOuter(AUD_Handle* handle, float angle)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -670,7 +670,7 @@ int AUD_setConeAngleOuter(AUD_Channel* handle, float angle)
        return false;
 }
 
-int AUD_setConeAngleInner(AUD_Channel* handle, float angle)
+int AUD_setConeAngleInner(AUD_Handle* handle, float angle)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -683,7 +683,7 @@ int AUD_setConeAngleInner(AUD_Channel* handle, float angle)
        return false;
 }
 
-int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume)
+int AUD_setConeVolumeOuter(AUD_Handle* handle, float volume)
 {
        assert(handle);
        AUD_Reference<AUD_I3DHandle> h(*handle);
@@ -696,7 +696,7 @@ int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume)
        return false;
 }
 
-int AUD_setSoundVolume(AUD_Channel* handle, float volume)
+int AUD_setSoundVolume(AUD_Handle* handle, float volume)
 {
        assert(handle);
        try
@@ -707,7 +707,7 @@ int AUD_setSoundVolume(AUD_Channel* handle, float volume)
        return false;
 }
 
-int AUD_setSoundPitch(AUD_Channel* handle, float pitch)
+int AUD_setSoundPitch(AUD_Handle* handle, float pitch)
 {
        assert(handle);
        try
@@ -730,18 +730,18 @@ AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
        }
 }
 
-AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
+AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
 {
        assert(device);
        assert(sound);
 
        try
        {
-               AUD_Channel channel = (*device)->play(*sound);
-               if(!channel.isNull())
+               AUD_Handle handle = (*device)->play(*sound);
+               if(!handle.isNull())
                {
-                       channel->seek(seek);
-                       return new AUD_Channel(channel);
+                       handle->seek(seek);
+                       return new AUD_Handle(handle);
                }
        }
        catch(AUD_Exception&)
@@ -848,13 +848,13 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high,
        return result;
 }
 
-static void pauseSound(AUD_Channel* handle)
+static void pauseSound(AUD_Handle* handle)
 {
        assert(handle);
        (*handle)->pause();
 }
 
-AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds)
+AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds)
 {
        AUD_Reference<AUD_IFactory> silence = new AUD_SilenceFactory;
        AUD_Reference<AUD_IFactory> limiter = new AUD_LimiterFactory(silence, 0, seconds);
@@ -863,12 +863,12 @@ AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds)
 
        try
        {
-               AUD_Channel channel = AUD_device->play(limiter);
-               if(!channel.isNull())
+               AUD_Handle handle2 = AUD_device->play(limiter);
+               if(!handle2.isNull())
                {
-                       channel->setStopCallback((stopCallback)pauseSound, handle);
+                       handle2->setStopCallback((stopCallback)pauseSound, handle);
                        AUD_device->unlock();
-                       return new AUD_Channel(channel);
+                       return new AUD_Handle(handle2);
                }
        }
        catch(AUD_Exception&)
@@ -996,7 +996,7 @@ void AUD_stopPlayback()
 #endif
 }
 
-void AUD_seekSequencer(AUD_Channel* handle, float time)
+void AUD_seekSequencer(AUD_Handle* handle, float time)
 {
 #ifdef WITH_JACK
        AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
@@ -1010,7 +1010,7 @@ void AUD_seekSequencer(AUD_Channel* handle, float time)
        }
 }
 
-float AUD_getSequencerPosition(AUD_Channel* handle)
+float AUD_getSequencerPosition(AUD_Handle* handle)
 {
 #ifdef WITH_JACK
        AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
@@ -1048,7 +1048,7 @@ AUD_Sound* AUD_copy(AUD_Sound* sound)
        return new AUD_Reference<AUD_IFactory>(*sound);
 }
 
-void AUD_freeChannel(AUD_Channel* channel)
+void AUD_freeHandle(AUD_Handle* handle)
 {
-       delete channel;
+       delete handle;
 }
index 945faa50070976a404de1fde1a7bee235c30e8fd..fad54cdb7212a3a394c0a2c6fe37d2652496edbb 100644 (file)
@@ -57,7 +57,7 @@ typedef struct
 
 #ifndef AUD_CAPI_IMPLEMENTATION
        typedef void AUD_Sound;
-       typedef void AUD_Channel;
+       typedef void AUD_Handle;
        typedef void AUD_Device;
        typedef void AUD_SEntry;
        typedef float (*AUD_volumeFunction)(void*, void*, float);
@@ -159,7 +159,7 @@ extern AUD_Sound* AUD_loopSound(AUD_Sound* sound);
  * \param loops The count of remaining loops, -1 for infinity.
  * \return Whether the handle is valid.
  */
-extern int AUD_setLoop(AUD_Channel* handle, int loops);
+extern int AUD_setLoop(AUD_Handle* handle, int loops);
 
 /**
  * Rectifies a sound.
@@ -181,28 +181,28 @@ extern void AUD_unload(AUD_Sound* sound);
  *             paused when its end has been reached.
  * \return A handle to the played back sound.
  */
-extern AUD_Channel* AUD_play(AUD_Sound* sound, int keep);
+extern AUD_Handle* AUD_play(AUD_Sound* sound, int keep);
 
 /**
  * Pauses a played back sound.
  * \param handle The handle to the sound.
  * \return Whether the handle has been playing or not.
  */
-extern int AUD_pause(AUD_Channel* handle);
+extern int AUD_pause(AUD_Handle* handle);
 
 /**
  * Resumes a paused sound.
  * \param handle The handle to the sound.
  * \return Whether the handle has been paused or not.
  */
-extern int AUD_resume(AUD_Channel* handle);
+extern int AUD_resume(AUD_Handle* handle);
 
 /**
  * Stops a playing or paused sound.
  * \param handle The handle to the sound.
  * \return Whether the handle has been valid or not.
  */
-extern int AUD_stop(AUD_Channel* handle);
+extern int AUD_stop(AUD_Handle* handle);
 
 /**
  * Sets the end behaviour of a playing or paused sound.
@@ -211,7 +211,7 @@ extern int AUD_stop(AUD_Channel* handle);
  *             paused when its end has been reached.
  * \return Whether the handle has been valid or not.
  */
-extern int AUD_setKeep(AUD_Channel* handle, int keep);
+extern int AUD_setKeep(AUD_Handle* handle, int keep);
 
 /**
  * Seeks a playing or paused sound.
@@ -219,7 +219,7 @@ extern int AUD_setKeep(AUD_Channel* handle, int keep);
  * \param seekTo From where the sound file should be played back in seconds.
  * \return Whether the handle has been valid or not.
  */
-extern int AUD_seek(AUD_Channel* handle, float seekTo);
+extern int AUD_seek(AUD_Handle* handle, float seekTo);
 
 /**
  * Retrieves the playback position of a handle.
@@ -227,14 +227,14 @@ extern int AUD_seek(AUD_Channel* handle, float seekTo);
  * \return The current playback position in seconds or 0.0 if the handle is
  *         invalid.
  */
-extern float AUD_getPosition(AUD_Channel* handle);
+extern float AUD_getPosition(AUD_Handle* handle);
 
 /**
  * Returns the status of a playing, paused or stopped sound.
  * \param handle The handle to the sound.
  * \return The status of the sound behind the handle.
  */
-extern AUD_Status AUD_getStatus(AUD_Channel* handle);
+extern AUD_Status AUD_getStatus(AUD_Handle* handle);
 
 /**
  * Sets the listener location.
@@ -281,7 +281,7 @@ extern int AUD_setDistanceModel(AUD_DistanceModel model);
  * \param location The new location.
  * \return Whether the action succeeded.
  */
-extern int AUD_setSourceLocation(AUD_Channel* handle, const float* location);
+extern int AUD_setSourceLocation(AUD_Handle* handle, const float* location);
 
 /**
  * Sets the velocity of a source.
@@ -289,7 +289,7 @@ extern int AUD_setSourceLocation(AUD_Channel* handle, const float* location);
  * \param velocity The new velocity.
  * \return Whether the action succeeded.
  */
-extern int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity);
+extern int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity);
 
 /**
  * Sets the orientation of a source.
@@ -297,7 +297,7 @@ extern int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity);
  * \param orientation The new orientation as quaternion.
  * \return Whether the action succeeded.
  */
-extern int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation);
+extern int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation);
 
 /**
  * Sets whether the source location, velocity and orientation are relative
@@ -306,7 +306,7 @@ extern int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientatio
  * \param relative Whether the source is relative.
  * \return Whether the action succeeded.
  */
-extern int AUD_setRelative(AUD_Channel* handle, int relative);
+extern int AUD_setRelative(AUD_Handle* handle, int relative);
 
 /**
  * Sets the maximum volume of a source.
@@ -314,7 +314,7 @@ extern int AUD_setRelative(AUD_Channel* handle, int relative);
  * \param volume The new maximum volume.
  * \return Whether the action succeeded.
  */
-extern int AUD_setVolumeMaximum(AUD_Channel* handle, float volume);
+extern int AUD_setVolumeMaximum(AUD_Handle* handle, float volume);
 
 /**
  * Sets the minimum volume of a source.
@@ -322,7 +322,7 @@ extern int AUD_setVolumeMaximum(AUD_Channel* handle, float volume);
  * \param volume The new minimum volume.
  * \return Whether the action succeeded.
  */
-extern int AUD_setVolumeMinimum(AUD_Channel* handle, float volume);
+extern int AUD_setVolumeMinimum(AUD_Handle* handle, float volume);
 
 /**
  * Sets the maximum distance of a source.
@@ -332,7 +332,7 @@ extern int AUD_setVolumeMinimum(AUD_Channel* handle, float volume);
  * \param distance The new maximum distance.
  * \return Whether the action succeeded.
  */
-extern int AUD_setDistanceMaximum(AUD_Channel* handle, float distance);
+extern int AUD_setDistanceMaximum(AUD_Handle* handle, float distance);
 
 /**
  * Sets the reference distance of a source.
@@ -340,7 +340,7 @@ extern int AUD_setDistanceMaximum(AUD_Channel* handle, float distance);
  * \param distance The new reference distance.
  * \return Whether the action succeeded.
  */
-extern int AUD_setDistanceReference(AUD_Channel* handle, float distance);
+extern int AUD_setDistanceReference(AUD_Handle* handle, float distance);
 
 /**
  * Sets the attenuation of a source.
@@ -349,7 +349,7 @@ extern int AUD_setDistanceReference(AUD_Channel* handle, float distance);
  * \param factor The new attenuation.
  * \return Whether the action succeeded.
  */
-extern int AUD_setAttenuation(AUD_Channel* handle, float factor);
+extern int AUD_setAttenuation(AUD_Handle* handle, float factor);
 
 /**
  * Sets the outer angle of the cone of a source.
@@ -357,7 +357,7 @@ extern int AUD_setAttenuation(AUD_Channel* handle, float factor);
  * \param angle The new outer angle of the cone.
  * \return Whether the action succeeded.
  */
-extern int AUD_setConeAngleOuter(AUD_Channel* handle, float angle);
+extern int AUD_setConeAngleOuter(AUD_Handle* handle, float angle);
 
 /**
  * Sets the inner angle of the cone of a source.
@@ -365,7 +365,7 @@ extern int AUD_setConeAngleOuter(AUD_Channel* handle, float angle);
  * \param angle The new inner angle of the cone.
  * \return Whether the action succeeded.
  */
-extern int AUD_setConeAngleInner(AUD_Channel* handle, float angle);
+extern int AUD_setConeAngleInner(AUD_Handle* handle, float angle);
 
 /**
  * Sets the outer volume of the cone of a source.
@@ -375,7 +375,7 @@ extern int AUD_setConeAngleInner(AUD_Channel* handle, float angle);
  * \param volume The new outer volume of the cone.
  * \return Whether the action succeeded.
  */
-extern int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume);
+extern int AUD_setConeVolumeOuter(AUD_Handle* handle, float volume);
 
 /**
  * Sets the volume of a played back sound.
@@ -383,7 +383,7 @@ extern int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume);
  * \param volume The new volume, must be between 0.0 and 1.0.
  * \return Whether the action succeeded.
  */
-extern int AUD_setSoundVolume(AUD_Channel* handle, float volume);
+extern int AUD_setSoundVolume(AUD_Handle* handle, float volume);
 
 /**
  * Sets the pitch of a played back sound.
@@ -391,7 +391,7 @@ extern int AUD_setSoundVolume(AUD_Channel* handle, float volume);
  * \param pitch The new pitch.
  * \return Whether the action succeeded.
  */
-extern int AUD_setSoundPitch(AUD_Channel* handle, float pitch);
+extern int AUD_setSoundPitch(AUD_Handle* handle, float pitch);
 
 /**
  * Opens a read device, with which audio data can be read.
@@ -415,7 +415,7 @@ extern int AUD_setDeviceVolume(AUD_Device* device, float volume);
  * \param seek The position where the sound should be seeked to.
  * \return A handle to the played back sound.
  */
-extern AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek);
+extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek);
 
 /**
  * Reads the next samples into the supplied buffer.
@@ -450,7 +450,7 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
  * \param time The time in seconds.
  * \return The silence handle.
  */
-extern AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds);
+extern AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds);
 
 extern AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume);
 
@@ -475,9 +475,9 @@ extern void AUD_startPlayback(void);
 
 extern void AUD_stopPlayback(void);
 
-extern void AUD_seekSequencer(AUD_Channel* handle, float time);
+extern void AUD_seekSequencer(AUD_Handle* handle, float time);
 
-extern float AUD_getSequencerPosition(AUD_Channel* handle);
+extern float AUD_getSequencerPosition(AUD_Handle* handle);
 
 #ifdef WITH_JACK
 extern void AUD_setSyncCallback(AUD_syncFunction function, void* data);
@@ -487,7 +487,7 @@ extern int AUD_doesPlayback(void);
 
 extern AUD_Sound* AUD_copy(AUD_Sound* sound);
 
-extern void AUD_freeChannel(AUD_Channel* channel);
+extern void AUD_freeHandle(AUD_Handle* channel);
 
 #ifdef WITH_PYTHON
 extern PyObject* AUD_getPythonFactory(AUD_Sound* sound);
index d8ed1153dae3ec03c73de63c67e5111b19eef2dc..ea6c738cb587155c768f8c2840be10b2250ea192 100644 (file)
@@ -38,75 +38,10 @@ AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_Reference<AUD_IFactory> f
                                                                                                   AUD_DeviceSpecs specs) :
                AUD_MixerFactory(factory, specs)
 {
-       memset(m_mapping, 0, sizeof(m_mapping));
-}
-
-AUD_ChannelMapperFactory::~AUD_ChannelMapperFactory()
-{
-       for(int i = 1; i < 10; i++)
-               deleteMapping(i);
-}
-
-float** AUD_ChannelMapperFactory::getMapping(int ic)
-{
-       ic--;
-       if(ic > 8 || ic < 0)
-               return 0;
-
-       if(m_mapping[ic])
-       {
-               int channels = -1;
-               while(m_mapping[ic][++channels] != 0);
-               if(channels != m_specs.channels)
-                       deleteMapping(ic+1);
-       }
-
-       if(!m_mapping[ic])
-       {
-               int channels = m_specs.channels;
-
-               m_mapping[ic] = new float*[channels+1];
-               m_mapping[ic][channels] = 0;
-
-               for(int i = 0; i < channels; i++)
-               {
-                       m_mapping[ic][i] = new float[ic+1];
-                       for(int j = 0; j <= ic; j++)
-                               m_mapping[ic][i][j] = ((i == j) || (channels == 1) ||
-                                                                          (ic == 0)) ? 1.0f : 0.0f;
-               }
-       }
-
-       return m_mapping[ic];
-}
-
-void AUD_ChannelMapperFactory::deleteMapping(int ic)
-{
-       ic--;
-       if(ic > 8 || ic < 0)
-               return;
-
-       if(m_mapping[ic])
-       {
-               for(int i = 0; 1; i++)
-               {
-                       if(m_mapping[ic][i] != 0)
-                       {
-                               delete[] m_mapping[ic][i];
-                       }
-                       else
-                               break;
-               }
-               delete[] m_mapping[ic];
-               m_mapping[ic] = 0;
-       }
 }
 
 AUD_Reference<AUD_IReader> AUD_ChannelMapperFactory::createReader()
 {
        AUD_Reference<AUD_IReader> reader = getReader();
-       int ic = reader->getSpecs().channels;
-
-       return new AUD_ChannelMapperReader(reader,
-                                  const_cast<AUD_ChannelMapperFactory*>(this)->getMapping(ic));
+       return new AUD_ChannelMapperReader(reader, m_specs.channels);
 }
index 7c48aa791a644b5d0220e6af494fd6e49afc4e64..ce43c6462de29ed8e9d1cb3c3458a80646603a80 100644 (file)
 class AUD_ChannelMapperFactory : public AUD_MixerFactory
 {
 private:
-       /**
-        * The mapping specification.
-        */
-       float **m_mapping[9];
-
        // hide copy constructor and operator=
        AUD_ChannelMapperFactory(const AUD_ChannelMapperFactory&);
        AUD_ChannelMapperFactory& operator=(const AUD_ChannelMapperFactory&);
@@ -53,20 +48,6 @@ private:
 public:
        AUD_ChannelMapperFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs);
 
-       virtual ~AUD_ChannelMapperFactory();
-
-       /**
-        * Returns the mapping array for editing.
-        * \param ic The count of input channels the array should have.
-        * \note The count of output channels is read of the desired output specs.
-        */
-       float** getMapping(int ic);
-
-       /**
-        * Deletes the current channel mapping.
-        */
-       void deleteMapping(int ic);
-
        virtual AUD_Reference<AUD_IReader> createReader();
 };
 
index 5c135153d0e2a52a6d94c6ab863ce5c814865bde..ab7b5317be1407590f91fe9dfced03cf12601226 100644 (file)
  *  \ingroup audaspaceintern
  */
 
+#include <cmath>
 
 #include "AUD_ChannelMapperReader.h"
 
 AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader,
-                                                                                                float **mapping) :
-               AUD_EffectReader(reader)
+                                                                                                AUD_Channels channels) :
+               AUD_EffectReader(reader), m_target_channels(channels),
+       m_source_channels(AUD_CHANNELS_INVALID), m_mapping(0)
 {
-       m_specs = reader->getSpecs();
+}
 
-       int channels = -1;
-       m_rch = m_specs.channels;
-       while(mapping[++channels] != 0);
+AUD_ChannelMapperReader::~AUD_ChannelMapperReader()
+{
+       delete[] m_mapping;
+}
 
-       m_mapping = new float*[channels];
-       m_specs.channels = (AUD_Channels)channels;
+float AUD_ChannelMapperReader::angleDistance(float alpha, float beta)
+{
+       alpha = fabs(alpha - beta);
 
-       float sum;
-       int i;
+       if(alpha > M_PI)
+               alpha = fabs(alpha - 2 * M_PI);
 
-       while(channels--)
-       {
-               m_mapping[channels] = new float[m_rch];
-               sum = 0.0f;
-               for(i=0; i < m_rch; i++)
-                       sum += mapping[channels][i];
-               for(i=0; i < m_rch; i++)
-                       m_mapping[channels][i] = sum > 0.0f ?
-                                                                        mapping[channels][i]/sum : 0.0f;
-       }
+       return alpha;
 }
 
-AUD_ChannelMapperReader::~AUD_ChannelMapperReader()
+void AUD_ChannelMapperReader::calculateMapping()
 {
-       int channels = m_specs.channels;
+       delete[] m_mapping;
+       m_mapping = new float[m_source_channels * m_target_channels];
 
-       while(channels--)
+       const AUD_Channel* source_channels = CHANNEL_MAPS[m_source_channels - 1];
+       const AUD_Channel* target_channels = CHANNEL_MAPS[m_target_channels - 1];
+
+       int lfe = -1;
+
+       for(int i = 0; i < m_target_channels; i++)
        {
-               delete[] m_mapping[channels];
+               if(target_channels[i] == AUD_CHANNEL_LFE)
+               {
+                       lfe = i;
+                       break;
+               }
        }
 
-       delete[] m_mapping;
+       const float* source_angles = CHANNEL_ANGLES[m_source_channels - 1];
+       const float* target_angles = CHANNEL_ANGLES[m_target_channels - 1];
+
+       int channel_min1, channel_min2;
+       float angle_min1, angle_min2, angle;
+
+       for(int i = 0; i < m_source_channels; i++)
+       {
+               if(source_channels[i] == AUD_CHANNEL_LFE)
+               {
+                       if(lfe != -1)
+                               m_mapping[lfe * m_source_channels + i] = 1;
+
+                       continue;
+               }
+
+               channel_min1 = channel_min2 = -1;
+               angle_min1 = angle_min2 = 2 * M_PI;
+
+               for(int j = 0; j < m_target_channels; j++)
+               {
+                       angle = angleDistance(source_angles[i], target_angles[j]);
+                       if(angle < angle_min1)
+                       {
+                               channel_min2 = channel_min1;
+                               angle_min2 = angle_min1;
+
+                               channel_min1 = j;
+                               angle_min1 = angle;
+                       }
+                       else if(angle < angle_min2)
+                       {
+                               channel_min2 = j;
+                               angle_min2 = angle;
+                       }
+               }
+
+               if(channel_min2 == -1)
+               {
+                       m_mapping[channel_min1 * m_source_channels + i] = 1;
+               }
+               else
+               {
+                       angle = angle_min1 + angle_min2;
+                       m_mapping[channel_min1 * m_source_channels + i] = cos(M_PI_2 * angle_min1 / angle);
+                       m_mapping[channel_min2 * m_source_channels + i] = cos(M_PI_2 * angle_min2 / angle);
+               }
+       }
 }
 
 AUD_Specs AUD_ChannelMapperReader::getSpecs() const
 {
-       return m_specs;
+       AUD_Specs specs = m_reader->getSpecs();
+       specs.channels = m_target_channels;
+       return specs;
 }
 
 void AUD_ChannelMapperReader::read(int& length, bool& eos, sample_t* buffer)
 {
-       m_buffer.assureSize(length * m_rch * sizeof(sample_t));
+       AUD_Channels channels = m_reader->getSpecs().channels;
+       if(channels != m_source_channels)
+       {
+               m_source_channels = channels;
+               calculateMapping();
+       }
+
+       if(m_source_channels == m_target_channels)
+       {
+               m_reader->read(length, eos, buffer);
+               return;
+       }
+
+       m_buffer.assureSize(length * channels * sizeof(sample_t));
 
        sample_t* in = m_buffer.getBuffer();
 
@@ -88,12 +155,172 @@ void AUD_ChannelMapperReader::read(int& length, bool& eos, sample_t* buffer)
 
        for(int i = 0; i < length; i++)
        {
-               for(int j = 0; j < m_specs.channels; j++)
+               for(int j = 0; j < m_target_channels; j++)
                {
                        sum = 0;
-                       for(int k = 0; k < m_rch; k++)
-                               sum += m_mapping[j][k] * in[i * m_rch + k];
-                       buffer[i * m_specs.channels + j] = sum;
+                       for(int k = 0; k < m_source_channels; k++)
+                               sum += m_mapping[j * m_source_channels + k] * in[i * m_source_channels + k];
+                       buffer[i * m_target_channels + j] = sum;
                }
        }
 }
+
+const AUD_Channel AUD_ChannelMapperReader::MONO_MAP[] =
+{
+       AUD_CHANNEL_FRONT_CENTER
+};
+
+const AUD_Channel AUD_ChannelMapperReader::STEREO_MAP[] =
+{
+       AUD_CHANNEL_FRONT_LEFT,
+       AUD_CHANNEL_FRONT_RIGHT
+};
+
+const AUD_Channel AUD_ChannelMapperReader::STEREO_LFE_MAP[] =
+{
+       AUD_CHANNEL_FRONT_LEFT,
+       AUD_CHANNEL_FRONT_RIGHT,
+       AUD_CHANNEL_LFE
+};
+
+const AUD_Channel AUD_ChannelMapperReader::SURROUND4_MAP[] =
+{
+       AUD_CHANNEL_FRONT_LEFT,
+       AUD_CHANNEL_FRONT_RIGHT,
+       AUD_CHANNEL_REAR_LEFT,
+       AUD_CHANNEL_REAR_RIGHT
+};
+
+const AUD_Channel AUD_ChannelMapperReader::SURROUND5_MAP[] =
+{
+       AUD_CHANNEL_FRONT_LEFT,
+       AUD_CHANNEL_FRONT_RIGHT,
+       AUD_CHANNEL_FRONT_CENTER,
+       AUD_CHANNEL_REAR_LEFT,
+       AUD_CHANNEL_REAR_RIGHT
+};
+
+const AUD_Channel AUD_ChannelMapperReader::SURROUND51_MAP[] =
+{
+       AUD_CHANNEL_FRONT_LEFT,
+       AUD_CHANNEL_FRONT_RIGHT,
+       AUD_CHANNEL_FRONT_CENTER,
+       AUD_CHANNEL_LFE,
+       AUD_CHANNEL_REAR_LEFT,
+       AUD_CHANNEL_REAR_RIGHT
+};
+
+const AUD_Channel AUD_ChannelMapperReader::SURROUND61_MAP[] =
+{
+       AUD_CHANNEL_FRONT_LEFT,
+       AUD_CHANNEL_FRONT_RIGHT,
+       AUD_CHANNEL_FRONT_CENTER,
+       AUD_CHANNEL_LFE,
+       AUD_CHANNEL_REAR_CENTER,
+       AUD_CHANNEL_REAR_LEFT,
+       AUD_CHANNEL_REAR_RIGHT
+};
+
+const AUD_Channel AUD_ChannelMapperReader::SURROUND71_MAP[] =
+{
+       AUD_CHANNEL_FRONT_LEFT,
+       AUD_CHANNEL_FRONT_RIGHT,
+       AUD_CHANNEL_FRONT_CENTER,
+       AUD_CHANNEL_LFE,
+       AUD_CHANNEL_REAR_LEFT,
+       AUD_CHANNEL_REAR_RIGHT,
+       AUD_CHANNEL_SIDE_LEFT,
+       AUD_CHANNEL_SIDE_RIGHT
+};
+
+const AUD_Channel* AUD_ChannelMapperReader::CHANNEL_MAPS[] =
+{
+       AUD_ChannelMapperReader::MONO_MAP,
+       AUD_ChannelMapperReader::STEREO_MAP,
+       AUD_ChannelMapperReader::STEREO_LFE_MAP,
+       AUD_ChannelMapperReader::SURROUND4_MAP,
+       AUD_ChannelMapperReader::SURROUND5_MAP,
+       AUD_ChannelMapperReader::SURROUND51_MAP,
+       AUD_ChannelMapperReader::SURROUND61_MAP,
+       AUD_ChannelMapperReader::SURROUND71_MAP
+};
+
+const float AUD_ChannelMapperReader::MONO_ANGLES[] =
+{
+       0.0f * M_PI / 180.0f
+};
+
+const float AUD_ChannelMapperReader::STEREO_ANGLES[] =
+{
+       -90.0f * M_PI / 180.0f,
+        90.0f * M_PI / 180.0f
+};
+
+const float AUD_ChannelMapperReader::STEREO_LFE_ANGLES[] =
+{
+   -90.0f * M_PI / 180.0f,
+       90.0f * M_PI / 180.0f,
+        0.0f * M_PI / 180.0f
+};
+
+const float AUD_ChannelMapperReader::SURROUND4_ANGLES[] =
+{
+        -45.0f * M_PI / 180.0f,
+         45.0f * M_PI / 180.0f,
+       -135.0f * M_PI / 180.0f,
+        135.0f * M_PI / 180.0f
+};
+
+const float AUD_ChannelMapperReader::SURROUND5_ANGLES[] =
+{
+        -30.0f * M_PI / 180.0f,
+         30.0f * M_PI / 180.0f,
+          0.0f * M_PI / 180.0f,
+       -110.0f * M_PI / 180.0f,
+        110.0f * M_PI / 180.0f
+};
+
+const float AUD_ChannelMapperReader::SURROUND51_ANGLES[] =
+{
+         -30.0f * M_PI / 180.0f,
+          30.0f * M_PI / 180.0f,
+          0.0f * M_PI / 180.0f,
+          0.0f * M_PI / 180.0f,
+       -110.0f * M_PI / 180.0f,
+        110.0f * M_PI / 180.0f
+};
+
+const float AUD_ChannelMapperReader::SURROUND61_ANGLES[] =
+{
+         -30.0f * M_PI / 180.0f,
+          30.0f * M_PI / 180.0f,
+          0.0f * M_PI / 180.0f,
+          0.0f * M_PI / 180.0f,
+        180.0f * M_PI / 180.0f,
+       -110.0f * M_PI / 180.0f,
+        110.0f * M_PI / 180.0f
+};
+
+const float AUD_ChannelMapperReader::SURROUND71_ANGLES[] =
+{
+         -30.0f * M_PI / 180.0f,
+          30.0f * M_PI / 180.0f,
+          0.0f * M_PI / 180.0f,
+          0.0f * M_PI / 180.0f,
+       -110.0f * M_PI / 180.0f,
+        110.0f * M_PI / 180.0f
+       -150.0f * M_PI / 180.0f,
+        150.0f * M_PI / 180.0f
+};
+
+const float* AUD_ChannelMapperReader::CHANNEL_ANGLES[] =
+{
+       AUD_ChannelMapperReader::MONO_ANGLES,
+       AUD_ChannelMapperReader::STEREO_ANGLES,
+       AUD_ChannelMapperReader::STEREO_LFE_ANGLES,
+       AUD_ChannelMapperReader::SURROUND4_ANGLES,
+       AUD_ChannelMapperReader::SURROUND5_ANGLES,
+       AUD_ChannelMapperReader::SURROUND51_ANGLES,
+       AUD_ChannelMapperReader::SURROUND61_ANGLES,
+       AUD_ChannelMapperReader::SURROUND71_ANGLES
+};
index b1246c08f75f8b190fcb6f6ab61e3f174cdcec7a..949bb4427e2012b571248894e4472413ed413db8 100644 (file)
@@ -50,29 +50,59 @@ private:
        /**
         * The output specification.
         */
-       AUD_Specs m_specs;
+       AUD_Channels m_target_channels;
 
        /**
         * The channel count of the reader.
         */
-       int m_rch;
+       AUD_Channels m_source_channels;
 
        /**
         * The mapping specification.
         */
-       float **m_mapping;
+       float* m_mapping;
+
+       static const AUD_Channel MONO_MAP[];
+       static const AUD_Channel STEREO_MAP[];
+       static const AUD_Channel STEREO_LFE_MAP[];
+       static const AUD_Channel SURROUND4_MAP[];
+       static const AUD_Channel SURROUND5_MAP[];
+       static const AUD_Channel SURROUND51_MAP[];
+       static const AUD_Channel SURROUND61_MAP[];
+       static const AUD_Channel SURROUND71_MAP[];
+       static const AUD_Channel* CHANNEL_MAPS[];
+
+       static const float MONO_ANGLES[];
+       static const float STEREO_ANGLES[];
+       static const float STEREO_LFE_ANGLES[];
+       static const float SURROUND4_ANGLES[];
+       static const float SURROUND5_ANGLES[];
+       static const float SURROUND51_ANGLES[];
+       static const float SURROUND61_ANGLES[];
+       static const float SURROUND71_ANGLES[];
+       static const float* CHANNEL_ANGLES[];
 
        // hide copy constructor and operator=
        AUD_ChannelMapperReader(const AUD_ChannelMapperReader&);
        AUD_ChannelMapperReader& operator=(const AUD_ChannelMapperReader&);
 
+       /**
+        * Calculates the mapping matrix.
+        */
+       void calculateMapping();
+
+       /**
+        * Calculates the distance between two angles.
+        */
+       float angleDistance(float alpha, float beta);
+
 public:
        /**
         * Creates a channel mapper reader.
         * \param reader The reader to map.
         * \param mapping The mapping specification as two dimensional float array.
         */
-       AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader, float **mapping);
+       AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader, AUD_Channels channels);
 
        /**
         * Destroys the reader.
index 24fea6527ba5962026aa49df8a85e062540c3006..62992b0201d721d5bb6a178c0d1ade52af5b0782 100644 (file)
@@ -47,31 +47,15 @@ AUD_DefaultMixer::AUD_DefaultMixer(AUD_DeviceSpecs specs) :
 
 AUD_Reference<AUD_IReader> AUD_DefaultMixer::prepare(AUD_Reference<AUD_IReader> reader)
 {
-       // hacky for now, until a better channel mapper reader is available
-       AUD_ChannelMapperFactory cmf(NULL, m_specs);
-
-       AUD_Specs specs = reader->getSpecs();
-
-       // if channel count is lower in output, rechannel before resampling
-       if(specs.channels < m_specs.channels)
-       {
-               reader = new AUD_ChannelMapperReader(reader,
-                                                                                        cmf.getMapping(specs.channels));
-               specs.channels = m_specs.channels;
-       }
-
        // resample
-       if(specs.rate != m_specs.rate)
 #ifdef WITH_SAMPLERATE
-               reader = new AUD_SRCResampleReader(reader, m_specs.specs);
+       reader = new AUD_SRCResampleReader(reader, m_specs.specs);
 #else
-               reader = new AUD_LinearResampleReader(reader, m_specs.specs);
+       reader = new AUD_LinearResampleReader(reader, m_specs.specs);
 #endif
        
        // rechannel
-       if(specs.channels != m_specs.channels)
-               reader = new AUD_ChannelMapperReader(reader,
-                                                                                        cmf.getMapping(specs.channels));
+       reader = new AUD_ChannelMapperReader(reader, m_specs.channels);
 
        return reader;
 }
index ee28a05b80d84dcaeb291b0f675e23a5d777197b..00bc22b97c652d09d2a4176873f4ba1618b9a1fa 100644 (file)
@@ -41,6 +41,9 @@
 /// Throws a AUD_Exception with the provided error code.
 #define AUD_THROW(exception, errorstr) { AUD_Exception e; e.error = exception; e.str = errorstr; throw e; }
 
+/// Returns the bit for a channel mask.
+#define AUD_CHANNEL_BIT(channel) (0x01 << channel)
+
 /// Returns the smaller of the two values.
 #define AUD_MIN(a, b) (((a) < (b)) ? (a) : (b))
 /// Returns the bigger of the two values.
@@ -79,10 +82,24 @@ typedef enum
        AUD_CHANNELS_SURROUND5  = 5,    /// 5 channel surround sound.
        AUD_CHANNELS_SURROUND51 = 6,    /// 5.1 surround sound.
        AUD_CHANNELS_SURROUND61 = 7,    /// 6.1 surround sound.
-       AUD_CHANNELS_SURROUND71 = 8,    /// 7.1 surround sound.
-       AUD_CHANNELS_SURROUND72 = 9             /// 7.2 surround sound.
+       AUD_CHANNELS_SURROUND71 = 8     /// 7.1 surround sound.
 } AUD_Channels;
 
+/// The channel names.
+typedef enum
+{
+       AUD_CHANNEL_FRONT_LEFT = 0,
+       AUD_CHANNEL_FRONT_RIGHT,
+       AUD_CHANNEL_FRONT_CENTER,
+       AUD_CHANNEL_LFE,
+       AUD_CHANNEL_REAR_LEFT,
+       AUD_CHANNEL_REAR_RIGHT,
+       AUD_CHANNEL_REAR_CENTER,
+       AUD_CHANNEL_SIDE_LEFT,
+       AUD_CHANNEL_SIDE_RIGHT,
+       AUD_CHANNEL_MAX
+} AUD_Channel;
+
 /**
  * The sample rate tells how many samples are played back within one second.
  * Some exotic formats may use other sample rates than provided here.
index 18eab71692428c912c6e791e55ec555b82c43ecf..60a24c2eace35a8efbd52ae7ccbfe824d0db170f 100644 (file)
@@ -346,7 +346,7 @@ AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start,
 
        AUD_setDeviceVolume(mixdown, volume);
 
-       AUD_freeChannel(AUD_playDevice(mixdown, scene->sound_scene, start / FPS));
+       AUD_freeHandle(AUD_playDevice(mixdown, scene->sound_scene, start / FPS));
 
        return mixdown;
 }
index dc90d7d24decf85a4c234a73eb03074d8a1afb37..9f145a71546261caa3db257dd6395f5409655d31 100644 (file)
@@ -53,14 +53,14 @@ typedef struct KX_3DSoundSettings
 
 class KX_SoundActuator : public SCA_IActuator
 {
-        Py_Header;
-        bool                                   m_isplaying;
+       Py_Header;
+       bool                                    m_isplaying;
        AUD_Sound*                              m_sound;
        float                                   m_volume;
        float                                   m_pitch;
        bool                                    m_is3d;
        KX_3DSoundSettings              m_3d;
-               AUD_Channel*                            m_handle;
+       AUD_Handle*                             m_handle;
 
        void play();