/*
	Rogue Trader.
	Copyright (c) 2007, Darragh Coy.
	All rights reserved.
	Original work(s), source code & author(s) details available at: http://www.darraghcoy.com

	Redistribution and use in source and binary forms, with or without modification, are permitted 
	provided that the following conditions are met:

		* 	Redistributions of source code must retain the above copyright notice, this list of 
			conditions and the following disclaimer.
		* 	Redistributions in binary form must reproduce the above copyright notice, this list of 
			conditions and the following disclaimer in the documentation.
		* 	Neither the name of the author nor the names of contributors may be used to endorse or 
			promote products derived from this software without specific prior written permission.
		* 	The use of any third party libraries, modules or data files provided with the source 
			form of the program must follow and respect the individual licensing terms of these 
			components. You do not have permission to modify or circumvent the licensing terms for 
			provided third party components unless the third party licenses specifically allow this. 
			If you do not agree to the terms of provided third party components then you do not have 
			permission to use them in your derived work(s).
		* 	The terms of this license do not apply to separate (but related) distributions if supplied 
			by the author(s), only to the contents of this source distribution, derived works, and the 
			binaries produced by either modified or unmodified versions of the source code. The terms 
			of this license do not also apply to any third party libraries or components provided with 
			the source distribution. Such third party elements are licensed under their own separate 
			agreements.

	THIS SOFTWARE IS PROVIDED BY DARRAGH COY ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
	BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
	ARE DISCLAIMED. IN NO EVENT SHALL DARRAGH COY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################
//
//
// Class Name:   SoundScene
// Purpose:      A SoundScene maintains a scene of various sound sources and
//               handles the playing and positioning of those sources. One of the
//               subclasses of the combined superclass, GameScene
//
//
//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################

#include "SoundScene.h"

//------------------------------------------------------------------------------
// Static variables
//------------------------------------------------------------------------------

// ID of the next sound to be played

static unsigned nextSoundID = 0;

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::SoundScene()
Purpose:  Sets up the sound scene.
Params:   none
Returns:  n/a

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

SoundScene::SoundScene()
{
    // If the current sound id to use is 0 then make it 1: zero is an ID reserved for sounds which didn't play

    if ( nextSoundID == 0 ) nextSoundID = 1;

    // Set the number of sounds playing to zero

    numSounds = 0;

    // Get the direct sound object from the sound system

    this->directSound = SoundSystem::directSound;

    // Set the listener inverse position and orientation to their defaults:

    listenerInvPosition[0] = 0;
    listenerInvPosition[1] = 0;
    listenerInvPosition[2] = 0;

    listenerInvOrientation[0] = 1;
    listenerInvOrientation[1] = 0;
    listenerInvOrientation[2] = 0;
    listenerInvOrientation[3] = 0;
    listenerInvOrientation[4] = 1;
    listenerInvOrientation[5] = 0;
    listenerInvOrientation[6] = 0;
    listenerInvOrientation[7] = 0;
    listenerInvOrientation[8] = 1;

    // Set all sounds in the scene to not paused

    soundsPaused = false;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::~SoundScene()
Purpose:  Destructor. Frees all resources allocated by the sound scene.
Params:   n/a
Returns:  n/a

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

SoundScene::~SoundScene()
{
    //--------------------------------------------------------------------------
    // Stop and release all playing sounds:
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < numSounds ; i++ )
    {
        // Stop the sound:

        sounds[i].buffer->Stop();

        // Release the sound:

        sounds[i].buffer->Release();
    }

    // Set the number of playing sounds to zero

    numSounds = 0;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::addSound()
Purpose:  Trys to add the given sound into the scene.
Params:   As commented.
Returns:  Sound ID of sound played, which is zero on failure to play

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

unsigned SoundScene::addSound
(
    const Sound *   sound,          // sound to play
    float           source_x,       // sound location: x
    float           source_y,       // sound location: y
    float           source_z,       // sound location: z
    float           distance,       // distance from which the sound can be heard
    float           frequency,      // frequency the sound will play at, 1 is normal, 0 is the min and 2 is the max
    bool            looping         // loop the sound or not ?
)
{
    //--------------------------------------------------------------------------
    // Some general checks before we add in the sound
    //--------------------------------------------------------------------------

    // Abort if we couldn't initialise direct sound:

    if ( this->directSound == 0 ) return 0;

    // Abort if sound given is null:

    if ( sound == 0 ) return 0;

    // Abort if sound given doesn't have a proper sound buffer:

    if ( sound->buffer == 0 ) return 0;

    // Abort if the maximum number of playing sounds has been reached

    if ( numSounds >= MAX_SOURCES ) return 0;

    // Make sure the frequency given is ok:

    if ( frequency < 0 ) frequency = 0;
    if ( frequency > 2 ) frequency = 2;

    // Make sure distance is ok:

    if ( distance < 1 ) distance = 1;

    //--------------------------------------------------------------------------
    // Ok so far: create a direct sound buffer for the object
    //--------------------------------------------------------------------------

    // Duplicate the original sounds buffer:

    unsigned result = directSound->DuplicateSoundBuffer
    (
        (IDirectSoundBuffer*)   sound->buffer,              // buffer to duplicate
        (IDirectSoundBuffer**)&(sounds[numSounds].buffer)   // buffer to save duplicate to
    );

    // Now if the buffer was not duplicated then abort creation:

    if ( result != DS_OK ) return 0;

    //--------------------------------------------------------------------------
    // Fill in the struct for this sound:
    //--------------------------------------------------------------------------

    sounds[numSounds].pos_x         = source_x;
    sounds[numSounds].pos_y         = source_y;
    sounds[numSounds].pos_z         = source_z;
    sounds[numSounds].distance      = distance;
    sounds[numSounds].looping       = looping;
    sounds[numSounds].id            = nextSoundID;

    // Increment the id of the next sound to create, but make sure it isn't zero

    nextSoundID++; if ( nextSoundID == 0 ) nextSoundID = 1;

    //--------------------------------------------------------------------------
    // Get the sounds buffer here to save on typing code:
    //--------------------------------------------------------------------------

    IDirectSoundBuffer8 & buffer = * sounds[numSounds].buffer;

    //--------------------------------------------------------------------------
    // Setup sound frequency:
    //--------------------------------------------------------------------------

    // Get the original sound frequency:

    unsigned originalFrequency = 0; buffer.GetFrequency( (DWORD*) &originalFrequency );

    // See if frequency is greater than or less than normal frequency:

    if ( frequency < 1 )
    {
        // Figure out the direct sound frequeny to play the sound at:

        float freq = ( frequency ) * originalFrequency + ( 1.0f - frequency ) * DSBFREQUENCY_MIN;

        // Set the frequency:

        buffer.SetFrequency( (unsigned)(freq) );
    }
    else
    {
        // Map frequency given to a 0-1 range

        frequency -= 1;

        // Figure out the direct sound frequeny to play the sound at:

        float freq = ( frequency ) * DSBFREQUENCY_MAX + ( 1.0f - frequency ) * originalFrequency;

        // Set the frequency:

        buffer.SetFrequency( (unsigned)(freq) );
    }

    //--------------------------------------------------------------------------
    // Update the position and panning of the sound wrt to the listener
    //--------------------------------------------------------------------------

    updateSound( sounds[numSounds] );

    //--------------------------------------------------------------------------
    // Play the sound with direct sound:
    //--------------------------------------------------------------------------

    // Only play the sound if all sounds in the scene are not paused:

    if ( soundsPaused == false )
    {
        // See if the sound is looping or not:

        if ( looping )
        {
            sounds[numSounds].buffer->Play
            (
                0,                  // reserved: must be zero
                0,                  // priority: dont care
                DSBPLAY_LOOPING     // play the sound looping
            );
        }
        else
        {
            sounds[numSounds].buffer->Play
            (
                0,                  // reserved: must be zero
                0,                  // priority: dont care
                0                   // no flags
            );
        }
    }

    //--------------------------------------------------------------------------
    // Return the id of the created sound:
    //--------------------------------------------------------------------------

    // Increment the number of sounds first:

    numSounds++;

    // Return the id of the sound created

    return sounds[ numSounds - 1 ].id;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::updateSound()
Purpose:  Updates a sounds volume and panning with direct sound to take into
          account the current position and orientation of the listener.
Params:   Sound to update
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void SoundScene::updateSound( SoundSource & sound )
{
    //--------------------------------------------------------------------------
    // Transform the sound position into listener coordinates
    //--------------------------------------------------------------------------

    float listenerCoords[3] =
    {
        sound.pos_x,
        sound.pos_y,
        sound.pos_z
    };

    // Translate by the inverse listener position first:

    listenerCoords[0] += listenerInvPosition[0];
    listenerCoords[1] += listenerInvPosition[1];
    listenerCoords[2] += listenerInvPosition[2];

    // Now transform by the inverse listener orientation:

    mlTransform3d( listenerCoords , listenerInvOrientation );

    //--------------------------------------------------------------------------
    // Set the volume of the sound based on the distance from listener
    //--------------------------------------------------------------------------

    // Get the distance from the listener:

    float dist = mlLenght3d( listenerCoords );

    // Figure out how loud the sound should be from 0-1 based on this distance: 1 is silence

    float inverseVolume = dist / sound.distance;

    // Make sure inverse volume is not greater than 1 :

    if ( inverseVolume > 1 ) inverseVolume = 1;

    // Convert this volume to a direct sound volume:

    unsigned dsVolume = unsigned( inverseVolume * DSBVOLUME_MIN );

    // Set the volume with direct sound

    sound.buffer->SetVolume(dsVolume);

    //--------------------------------------------------------------------------
    // Set the panning on the sound pased on the sounds position relative to the
    // listener:
    //--------------------------------------------------------------------------

    // Normalise the listener coordinates position of the sound first:

    mlNormalise3d(listenerCoords);

    // Now map the x position of the sound to a 0-1 range:

    listenerCoords[0] += 1.0f;
    listenerCoords[0] *= 0.5f;

    // Now decide on direct sound panning value to use based on this position

    float pan = listenerCoords[0] * DSBPAN_RIGHT + (1.0f - listenerCoords[0] ) * DSBPAN_LEFT;

    // Hack: if the sounds position in listener coordintates is close then pan
    // the sound towards the center based on how far it is from the listener.
    // this is to keep the sounds of player weapons and such at center stereo position

    if ( dist < 1000 )
    {
        // Figure out how much to pan to the center based on distance:

        float t = dist / 1000.0f;

        // Move panning towards the center

        pan = pan * t;
    }

    // Set the panning value with direct sound

    sound.buffer->SetPan( unsigned(pan) );
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::setListenerPosition()
Purpose:  Sets the position of the listener in the sound scene.
Params:   Vector containing listener position.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void SoundScene::setListenerPosition( float * position )
{
    // Abort if null vector given:

    if ( position == 0  ) return;

    // Set the listener inverse position otherwise:

    listenerInvPosition[0] = -position[0];
    listenerInvPosition[1] = -position[1];
    listenerInvPosition[2] = -position[2];
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::setListenerOrientation()
Purpose:  Sets the orientation of the listener in the sound scene.
Params:   Vector containing listener orientation which is a 3x3 matrix
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void SoundScene::setListenerOrientation( float * orientation )
{
    // Abort if null orientation given:

    if ( orientation == 0  ) return;

    // Set the listener inverse orientation otherwise:

    listenerInvOrientation[0] = orientation[0];
    listenerInvOrientation[1] = orientation[3];
    listenerInvOrientation[2] = orientation[6];

    listenerInvOrientation[3] = orientation[1];
    listenerInvOrientation[4] = orientation[4];
    listenerInvOrientation[5] = orientation[7];

    listenerInvOrientation[6] = orientation[2];
    listenerInvOrientation[7] = orientation[5];
    listenerInvOrientation[8] = orientation[8];
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::updateSounds()
Purpose:  Updates all of the sounds in a scene and kills sounds which are dead
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void SoundScene::updateSounds()
{
    //--------------------------------------------------------------------------
    // Go through the sounds array and look for dead sounds:
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < numSounds ; i++ )
    {
        // Get the status of this sound:

        unsigned status = 0; sounds[i].buffer->GetStatus((DWORD*)&status);

        // See if the sound is still playing: if so move onto the next sound

        if ( status & DSBSTATUS_PLAYING ) continue;

        // Otherwise stop this sound and release it

        sounds[i].buffer->Stop();
        sounds[i].buffer->Release();

        // Otherwise swap the last sound in the array into this position:

        sounds[i] = sounds[numSounds - 1];

        // Decrement the number of sounds

        numSounds--;
    }

    //--------------------------------------------------------------------------
    // Update the volume and panning of all sounds in the scene
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < numSounds ; i++ )
    {
        updateSound( sounds[i] );
    }

}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::soundExists()
Purpose:  Tells if the sound with the given ID exists in the sound scene
Params:   SoundID of sound
Returns:  If it exists or not

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

bool SoundScene::soundExists( unsigned soundID )
{
    // If the sound ID is 0 which is an invalid ID then return false

    if ( soundID == 0  ) return false;

    // Otherwise search through the array for the sound

    for ( unsigned i = 0 ; i < numSounds ; i++ )
    {
        // See if the ID of this sound matches the one given and return true if so

        if ( sounds[i].id == soundID ) return true;
    }

    // If we have got to here then the sound doesn't exist: return false

    return false;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::deleteSound()
Purpose:  Trys to delete the sound with the given ID
Params:   SoundID of sound to delete from the scene
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void SoundScene::deleteSound( unsigned soundID )
{
    // If the sound ID is 0 which is an invalid ID then abort

    if ( soundID == 0  ) return;

    // Otherwise try to find the sound:

    for ( unsigned i = 0 ; i < numSounds ; i++ )
    {
        // See if this is the sound we are looking for:

        if ( sounds[i].id == soundID )
        {
            // Found match: stop this sound from playing and release it

            sounds[i].buffer->Stop();
            sounds[i].buffer->Release();

            // swap last sound into this place

            sounds[i] = sounds[ numSounds - 1 ];

            // Decrement the number of sounds:

            numSounds--;

            // Abort search: now done

            break;
        }
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::updateSoundPosition()
Purpose:  Trys to change the position of te given sound.
Params:   SoundID of sound to update, position to set sound to.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void SoundScene::updateSoundPosition
(
    unsigned    soundID,
    float       positionX,
    float       positionY,
    float       positionZ
)
{
    // If the sound ID is 0 which is an invalid ID then abort

    if ( soundID == 0  ) return;

    // Otherwise try to find the sound:

    for ( unsigned i = 0 ; i < numSounds ; i++ )
    {
        // See if this is the sound we are looking for:

        if ( sounds[i].id == soundID )
        {
            // Found match: set position of the sound

            sounds[i].pos_x = positionX;
            sounds[i].pos_y = positionY;
            sounds[i].pos_z = positionZ;

            // Abort search: now done

            break;
        }
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::updateSoundFrequency()
Purpose:  Updates the frequency of a given sound
Params:   Sound to update, frequency to set to, between 0 and 2
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void SoundScene::updateSoundFrequency( unsigned soundID, float frequency )
{
    // If the sound ID is 0 which is an invalid ID then abort

    if ( soundID == 0  ) return;

    // Otherwise try to find the sound:

    for ( unsigned i = 0 ; i < numSounds ; i++ )
    {
        // See if this is the sound we are looking for:

        if ( sounds[i].id == soundID )
        {
            // Get this sounds buffer here as a reference for handyness:

            IDirectSoundBuffer8 & buffer = * sounds[i].buffer;

            //------------------------------------------------------------------
            // Make sure frequency given is in a 0-2 range
            //------------------------------------------------------------------

            if ( frequency < 0 ) frequency = 0;
            if ( frequency > 2 ) frequency = 2;

            //------------------------------------------------------------------
            // Get the original sound frequency:
            //------------------------------------------------------------------

            unsigned originalFrequency = 0;

            // Set the frequency to zero to restore original frequency

            buffer.SetFrequency(0);

            // Get the original frequency:

            buffer.GetFrequency( (DWORD*) &originalFrequency );

            //------------------------------------------------------------------
            // See if frequency requested is greater than or less than normal frequency:
            //------------------------------------------------------------------

            if ( frequency < 1 )
            {
                // Figure out the direct sound frequeny to play the sound at:

                float freq = ( frequency ) * float(originalFrequency) + ( 1.0f - frequency ) * float(DSBFREQUENCY_MIN);

                // Set the frequency:

                buffer.SetFrequency( (unsigned)(freq) );
            }
            else
            {
                // Map frequency given to a 0-1 range

                frequency -= 1;

                // Figure out the direct sound frequeny to play the sound at:

                float freq = ( frequency ) * float(DSBFREQUENCY_MAX) + ( 1.0f - frequency ) * float(originalFrequency);

                // Set the frequency:

                buffer.SetFrequency( (unsigned)(freq) );
            }

            //------------------------------------------------------------------
            // Finally abort the search after this. we are done.
            //------------------------------------------------------------------

            break;

        }   // end if found sound we are looking for

    }   // end search through the sound array for given sound
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::pauseAllSounds()
Purpose:  Pauses all sounds in the sound scene
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void SoundScene::pauseAllSounds()
{
    // Pause every sound:

    for ( unsigned i = 0 ; i < numSounds ; i++ )
    {
        // Pause this sound:

        sounds[i].buffer->Stop();
    }

    // Set the sounds paused flag to true:

    soundsPaused = true;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     SoundScene::resumeAllSounds()
Purpose:  Resumes all previously paused sounds.
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void SoundScene::resumeAllSounds()
{
    // Resume every sound:

    for ( unsigned i = 0 ; i < numSounds ; i++ )
    {
        // Resume this sound: but see if it is looping first

        if ( sounds[i].looping )
        {
            sounds[i].buffer->Play
            (
                0,                  // reserved: must be zero
                0,                  // priority: dont care
                DSBPLAY_LOOPING     // play the sound looping
            );
        }
        else
        {
            sounds[i].buffer->Play
            (
                0,                  // reserved: must be zero
                0,                  // priority: dont care
                0                   // no flags
            );
        }
    }

    // Set the sounds paused flag to false:

    soundsPaused = false;
}
