0
0

I have a sound I need to be constantly playing until, lets say, a ball stops rolling. So while it is rolling I make continuous calls to play the sound. I make a check to see if that sound is playing on a channel which that sound was assigned to when first told to play, which also includes a check to see if the sound on that channel is actually the sound I want to check for.

The sound is being used for multiple objects.

The problem comes in when I run the test and I hear maybe one or two out of three balls rolling at the most.

Mind you, PlaySFX() is being called constantly until the balls stop playing. IMPACT is a type of sound for when the ball is first hitting the ground, the opposite of an IMPACT sound is a slide, which is played when the balls are rolling instead of bouncing.

Don’t worry, plenty of code follows..

[code:1t0s8bjh]

define DISTANCEFACTOR 100.0f // Units per meter. I.e feet would = 3.28. centimeters would = 100.

struct _sound_effect
{
irr::core::stringc Name;
FMOD_SOUND* Audio;
FMOD_CHANNEL* Voice;
bool REUSE_VOICE;
bool IS_3D;
bool LOOP;
bool IMPACT;
};

typedef _sound_effect* psound_effect;

class CAudio
{
public:
CAudio(void)
{
FMOD_RESULT result;
// TODO: Implement Support for:
/*
FMOD_SPEAKERMODE_STEREO (left & right)
FMOD_SPEAKERMODE_SURROUND (5 speakers, 2 front, 2 rear, 1 center
FMOD_SPEAKERMODE_5POINT1 (5 speakers 1 sub)

            3D HARDWARE MODE
            3D SOFTWARE MODE
        */

        result = FMOD_System_Create( &System );

        result = FMOD_System_SetSpeakerMode( System, FMOD_SPEAKERMODE_STEREO );
        //ERRCHECK(result);

        // Allow 128 software mixed voices to be audible at once.
        result = FMOD_System_SetSoftwareChannels( System, 256 );
        //ERRCHECK(result);

        FMOD_System_SetSoftwareFormat( System, 44100, FMOD_SOUND_FORMAT_PCM16, 0, 4, FMOD_DSP_RESAMPLER_LINEAR  );

        // Require the soundcard to have at least 32 2D and 3D hardware voices,
        // and clamp it to using 64 if it has more than this.
        result = FMOD_System_SetHardwareChannels( System, 8, 32, 8, 32 );
        //ERRCHECK(result);

        // Initialize FMOD with 128 virtual voices.
        result = FMOD_System_Init( System, 256, FMOD_INIT_DSOUND_HRTFFULL | FMOD_INIT_3D_RIGHTHANDED, 0 );
        //ERRCHECK(result);

        //  Set the distance units. (meters/feet etc).          
        result = FMOD_System_Set3DSettings( System, 1.0, DISTANCEFACTOR, 1.0f );

        FMOD_System_Set3DNumListeners( System, 1 );

    }

    ~CAudio(void)
    {
        // Free memory for every sound effect loaded
        for( u32 i=0; i<sfx_list.size(); i++ )
        {
            psound_effect p_sfx = sfx_list[i];
            FMOD_Sound_Release( p_sfx->Audio );
            delete (p_sfx);
            sfx_list.erase(i);
        }

        FMOD_System_Release( System );
    }

    void Update(void)
    {
        FMOD_System_Update( System );
    }

    void Set3DListener( irr::core::vector3df p, irr::core::vector3df v, irr::core::vector3df f, irr::core::vector3df up )
    {
        FMOD_RESULT result;
        //p *= DISTANCEFACTOR;

        const FMOD_VECTOR _pos = { p.X, p.Y, p.Z };
        const FMOD_VECTOR _vel = {  v.X, v.Y, v.Z };
        const FMOD_VECTOR _forward = { f.X, f.Y, f.Z };
        const FMOD_VECTOR _up = {  up.X, up.Y, up.Z };
        result = FMOD_System_Set3DListenerAttributes( System, 0, &_pos, NULL, &_forward, &_up );
    }

    // Loads a sound effect from file into the sound effect list
    bool NewSFX( const char* Name, const char* Filename, bool IMPACT = true, bool LOOP = false, bool REUSE_VOICE = false, bool IS_3D = true )
    {
        FMOD_RESULT result;
        FMOD_SOUND* TSound;     
        FMOD_CREATESOUNDEXINFO ex;
        memset((void*)&ex, 0, sizeof(ex) );
        ex.decodebuffersize = 44100;

        if(LOOP)
        {
            result = FMOD_System_CreateSound( System, Filename, 
                (FMOD_MODE)( FMOD_CREATESAMPLE | FMOD_ACCURATETIME | FMOD_LOOP_NORMAL | 
                FMOD_SOFTWARE | FMOD_3D ), 
                0, &TSound );
        }
        else
        {
            result = FMOD_System_CreateSound( System, Filename, 
                (FMOD_MODE)( FMOD_CREATESAMPLE | FMOD_ACCURATETIME | FMOD_LOOP_OFF | 
                FMOD_SOFTWARE | FMOD_3D ), 
                0, &TSound );
        }

        FMOD_Sound_Set3DMinMaxDistance( TSound, 1 * DISTANCEFACTOR, 10000 * DISTANCEFACTOR );

        //FMOD_Sound_SetVariations( TSound, 100.0, 0.0, 0.0 );

        if( result!= FMOD_OK ) return false;

        // create new sound effect
        psound_effect p_sfx = new _sound_effect;            
        p_sfx->Name = Name;
        p_sfx->Audio = TSound;           
        p_sfx->Voice = 0;
        p_sfx->REUSE_VOICE = REUSE_VOICE;
        p_sfx->LOOP = LOOP;
        p_sfx->IS_3D = IS_3D;
        p_sfx->IMPACT = IMPACT;
        sfx_list.push_back(  p_sfx );
        return true;
    }

    // Play a sound effect with Name, with optional 3d position & velocity
    bool PlaySFX( irr::core::stringc Name, irr::core::vector3df p = irr::core::vector3df(0.0f, 0.0f, 0.0f), 
        irr::core::vector3df v = irr::core::vector3df(0.0f, 0.0f, 0.0f) )
    {
        FMOD_RESULT result;

        psound_effect p_sfx = RotarySFX( Name );
        if(!p_sfx) return false;
        if(!p_sfx->Audio) return false;  

        // if this sound is a slide sound effect, make sure it is only playing once on it's voice.
        if( (!p_sfx->IMPACT)&&(isSFXPlaying(p_sfx)) ) return false;

        if(p_sfx->REUSE_VOICE)
            result = FMOD_System_PlaySound( System, FMOD_CHANNEL_REUSE, p_sfx->Audio, true, &(p_sfx->Voice) );
        else
            result = FMOD_System_PlaySound( System, FMOD_CHANNEL_FREE, p_sfx->Audio, true, &(p_sfx->Voice) );
        if( result!= FMOD_OK ) return false;

        // set voice position in 3d space
        if(p_sfx->IS_3D)
        {
            //p *= DISTANCEFACTOR;              
            FMOD_VECTOR pos = { p.X, p.Y, p.Z };
            FMOD_VECTOR vel = {  v.X, v.Y, v.Z };
            result = FMOD_Channel_Set3DAttributes( p_sfx->Voice, &pos, NULL );
            if( result!= FMOD_OK ) return false;
        }

        // Unpause the voice
        FMOD_Channel_SetPaused( p_sfx->Voice, false );

        return true;
    }

    // If a channel is playing with the sound effect Name, stop it.
    bool StopSFX( irr::core::stringc Name ) // UNTESTED
    {
        FMOD_RESULT result;
        psound_effect p_sfx = RotarySFX( Name );
        if(!p_sfx) return false;
        if(!p_sfx->Audio) return false;  
        if(!p_sfx->Voice) return false;

        // get the sfx on this sfx's voice, if its playing the voice, continue.
        // otherwise, we've lost track of the voice meaning the sound must not be playing.
        FMOD_SOUND* TSound;
        FMOD_BOOL IS_PLAYING;
        result = FMOD_Channel_GetCurrentSound( p_sfx->Voice, &TSound );          
        if( result!= FMOD_OK ) return false;
        if(TSound!=p_sfx->Audio) return false;

        // if this voice is playing with our sound, stop it.
        result = FMOD_Channel_IsPlaying( p_sfx->Voice, &IS_PLAYING );
        if( result!= FMOD_OK ) return false;
        if( IS_PLAYING )
        {
            result = FMOD_Channel_Stop( p_sfx->Voice );
            if( result!= FMOD_OK ) return false;
        }
        return true;
    }

    FMOD_BOOL isSFXPlaying( irr::core::stringc Name )
    {
        FMOD_RESULT result;
        psound_effect p_sfx = RotarySFX( Name );
        if(!p_sfx) return false;
        if(!p_sfx->Audio) return false;  
        if(!p_sfx->Voice) return false;

        // get the sfx on this sfx's voice, if its playing the voice, continue.
        // otherwise, we've lost track of the voice meaning the sound must not be playing.
        FMOD_SOUND* TSound;
        FMOD_BOOL IS_PLAYING;
        result = FMOD_Channel_GetCurrentSound( p_sfx->Voice, &TSound );          
        if( result!= FMOD_OK ) return false;
        if(TSound!=p_sfx->Audio) return false;

        // if this voice is playing with our sound, stop it.
        result = FMOD_Channel_IsPlaying( p_sfx->Voice, &IS_PLAYING );
        if( result!= FMOD_OK ) return false;
        return ( IS_PLAYING );
    }

    FMOD_BOOL isSFXPlaying( psound_effect p_sfx )
    {
        FMOD_RESULT result;         
        if(!p_sfx) return false;
        if(!p_sfx->Audio) return false;  
        if(!p_sfx->Voice) return false;

        // get the sfx on this sfx's voice, if its playing the voice, continue.
        // otherwise, we've lost track of the voice meaning the sound must not be playing.
        FMOD_SOUND* TSound;
        FMOD_BOOL IS_PLAYING;
        result = FMOD_Channel_GetCurrentSound( p_sfx->Voice, &TSound );          
        if( result!= FMOD_OK ) return false;
        if(TSound!=p_sfx->Audio) return false;

        // if this voice is playing with our sound, stop it.
        result = FMOD_Channel_IsPlaying( p_sfx->Voice, &IS_PLAYING );
        if( result!= FMOD_OK ) return false;
        return ( IS_PLAYING );
    }

    // Returns the sound effect at Index
    psound_effect RotarySFX( u32 Index )
    {
        return sfx_list[Index];
    }

    // Returns the sound effect with Name
    psound_effect RotarySFX( irr::core::stringc Name )
    {
        for( u32 i=0; i<sfx_list.size(); i++ )
        {
            if( Name.equals_ignore_case( sfx_list[i]->Name ) )
                return sfx_list[i];
        }
        return 0;
    }

protected:
    irr::core::array< psound_effect > sfx_list;   
    FMOD_SYSTEM *System;        

};
[/code:1t0s8bjh]

FMOD does have alot of clear examples, but where this kind of problem comes in I have yet to dig it up.

Clearing up what not to do for what I want, and what should be done would help, Thanks.

EDIT: I’m thinking I’ll have to keep a list of channels myself now that I look at my code..

  • You must to post comments
0
0

wouldnt a rolling ball sound simply been a loop that plays until you dont need it any more then you stop it? Continually plays sounds sounds inneficient and possibly clicky/low quality to me.

  • You must to post comments
0
0

I ventured that route before, but looping a sound does not get rid of the problem that I’m only hearing one or two of these sounds at a time, almost sure now it is only one.

I have decided to link my objects somehow to channels with a sound effect playing. Probably an objects name as user data. This way I can also check what object the sound is for along with an is playing? check, avoiding any forced channel stealing which I now read my code as possibly doing.

A loop is still a good idea for performance. I could send something telling the objects sounds channel that the object itself is at rest as user data as well I suppose.

I do enjoy FMOD ! Out of the three libraries I am currently using, it’s been the easiest one to work on. (Irrlicht 3D Engine and Newton Game Dynamics are the other two. ๐Ÿ˜€ )

  • You must to post comments
0
0

well besides this, what is the problem again? That you are only hearing your sounds up to 3 times at once when it should be more? Are you actually using the reuse flag that you pass in via that function?

  • You must to post comments
0
0

Heh. ^^^^ read post above yours.

  • You must to post comments
0
0

[code:3pvbglwp] if(p_sfx->REUSE_VOICE)
result = FMOD_System_PlaySound( System, FMOD_CHANNEL_REUSE, p_sfx->Audio, true, &(p_sfx->Voice) );
else
result = FMOD_System_PlaySound( System, FMOD_CHANNEL_FREE, p_sfx->Audio, true, &(p_sfx->Voice) ); [/code:3pvbglwp]

And to your question about REUSE_VOICE, yes.

I’m sorry, that was alot of code, I wouldn’t have read it either. ๐Ÿ˜‰

  • You must to post comments
Showing 5 results
Your Answer

Please first to submit.