misc/libopenalbridge/commands.c
author nemo
Thu, 01 Jul 2010 23:41:10 -0400
changeset 3608 c509bbc779e7
parent 3529 0e968ba12a84
child 3697 d5b30d6373fc
permissions -rw-r--r--
Revert prior attempted optimisation. Gridding the land pays in some situations, but not all. Restricting to an upper bound might help, but overall, seems too fuzzy to be worth it. On one side is increased cost of Add/Delete + extra test on collision check, on the other is skipping the list iteration. Perhaps for large lists.

/*
 *  commands.c
 *  Hedgewars
 *
 *  Created by Vittorio on 13/06/10.
 *  Copyright 2010 __MyCompanyName__. All rights reserved.
 *
 */

#include "commands.h"
#include "wrappers.h"

ALfloat old_gain;
extern ALuint *Sources;
extern ALuint cache_size, cache_index, sources_number;
extern ALboolean instances_number;
extern al_sound_t *the_sounds;

void openal_pausesound (uint32_t index) {
    if (openal_ready() == AL_TRUE && index < cache_size)
        alSourcePause(Sources[the_sounds[index].source_index]);
}


void openal_stopsound (uint32_t index) {
    if (openal_ready() == AL_TRUE && index < cache_size)
        alSourceStop(Sources[the_sounds[index].source_index]);
}


void openal_playsound (unsigned int index) {
    ALboolean needsSource = AL_TRUE;
    ALfloat SourcePosition[] = { 0.0, 0.0, 0.0 };
    ALfloat SourceVelocity[] = { 0.0, 0.0, 0.0 };
    ALint state;
    int i, j;
    
    if (openal_ready() == AL_TRUE && index < cache_size) {
        // check if sound has already a source
        if (the_sounds[index].source_index != -1) {
            // it has a source, check it's not playing
            alGetSourcei(Sources[the_sounds[index].source_index], AL_SOURCE_STATE, &state);
            if (state != AL_PLAYING && state != AL_PAUSED) { 	 
                // it is not being played, so we can use it safely
	            needsSource = AL_FALSE; 		 
            }
            // else it is being played, so we have to allocate a new source for this buffer
        }
        
        if (needsSource) {
#ifdef DEBUG
            fprintf(stderr,"(Bridge Debug) - looking for a source for sound %d\n", index);
#endif
            for (i = 0; i < sources_number; i++) {
                // let's iterate on Sources until we find a source that is not playing
                alGetSourcei(Sources[i], AL_SOURCE_STATE, &state); 	 
                if (state != AL_PLAYING && state != AL_PAUSED) {
                    // let's iterate on the_sounds until we find the sound using that source
                    for (j = 0; j < cache_size; j++) {
                        if (the_sounds[j].source_index == i) {
                            the_sounds[j].source_index = -1;
                            break;
                        }
                    }
                    // here we know that no-one is using that source so we can use it
                    break;
                }
            }
            
            if (i == sources_number) {
                // this means all sources are busy
            }
            
            // set source properties that it will use when it's in playback
            alSourcei (Sources[i], AL_BUFFER,   the_sounds[index].buffer);
            alSourcef (Sources[i], AL_PITCH,    1.0f);
            alSourcef (Sources[i], AL_GAIN,     1.0f);
            alSourcefv(Sources[i], AL_POSITION, SourcePosition);
            alSourcefv(Sources[i], AL_VELOCITY, SourceVelocity);
            alSourcei (Sources[i], AL_LOOPING,  0);
            
            if (AL_NO_ERROR != alGetError()) {
                fprintf(stderr,"(Bridge ERROR) - failed to set Source properties\n");
                return;
            }
            the_sounds[index].source_index = i;
        }
        
        alSourcePlay(Sources[the_sounds[index].source_index]);
        
        if (AL_NO_ERROR != alGetError()) {
            fprintf(stderr,"(Bridge Warning) - failed to play sound %d\n", index);
            return;
        }
    }
}

void openal_toggleloop (uint32_t index) {
    ALint loop;

    if (openal_ready() == AL_TRUE && index < cache_size) {
        alGetSourcei (Sources[the_sounds[index].source_index], AL_LOOPING, &loop);
        alSourcei (Sources[the_sounds[index].source_index], AL_LOOPING, !((uint8_t) loop) & 0x00000001);
    }
}


void openal_setvolume (uint32_t index, float gain) {
    if (openal_ready() == AL_TRUE && index < cache_size)
        alSourcef (Sources[the_sounds[index].source_index], AL_GAIN, gain);
}


void openal_setglobalvolume (float gain) {
    if (openal_ready() == AL_TRUE)
        alListenerf (AL_GAIN, gain);
}

void openal_togglemute () {
    ALfloat gain;

    if (openal_ready() == AL_TRUE) {
        alGetListenerf (AL_GAIN, &gain);
        if (gain > 0) {
            old_gain = gain;
            gain = 0;
        } else
            gain = old_gain;

        alListenerf (AL_GAIN, gain);
    }
}

// Fade in or out by calling a helper thread
void openal_fade (uint32_t index, uint16_t quantity, al_fade_t direction) {
#ifndef _WIN32
    pthread_t thread;
#else
    HANDLE Thread;
#endif
    fade_t *fade;

    if (openal_ready() == AL_TRUE && index < cache_size) {
        fade = (fade_t*) Malloc(sizeof(fade_t));
        fade->index = index;
        fade->quantity = quantity;
        fade->type = direction;

#ifndef _WIN32
        pthread_create(&thread, NULL, (void *)helper_fade, (void *)fade);
        pthread_detach(thread);
#else
        Thread = (HANDLE) _beginthread((void *)helper_fade, 0, (void *)fade);
#endif
    }
}

void openal_setposition (uint32_t index, float x, float y, float z) {
    if (openal_ready() == AL_TRUE && index < cache_size)
        alSource3f(Sources[the_sounds[index].source_index], AL_POSITION, x, y, z);;
}

void helper_fade(void *tmp) {
    ALfloat gain;
    ALfloat target_gain;
    fade_t *fade;
    uint32_t index;
    uint16_t quantity;
    al_fade_t type;

    fade = tmp;
    index = fade->index;
    quantity = fade->quantity;
    type = fade->type;
    free (fade);

    if (type == AL_FADE_IN) {
#ifdef DEBUG
        fprintf(stderr,"(Bridge Info) - Fade-in in progress [index %d quantity %d]", index, quantity);
#endif

        // save the volume desired after the fade
        alGetSourcef(Sources[the_sounds[index].source_index], AL_GAIN, &target_gain);
        if (target_gain > 1.0f || target_gain <= 0.0f)
            target_gain = 1.0f;

        for (gain = 0.0f ; gain <= target_gain; gain += (float) quantity/10000) {
#ifdef TRACE
            fprintf(stderr,"(Bridge Debug) - Fade-in set gain to %f\n", gain);
#endif
            alSourcef(Sources[the_sounds[index].source_index], AL_GAIN, gain);
            usleep(10000);
        }
    } else {
        alGetSourcef(Sources[the_sounds[index].source_index], AL_GAIN, &target_gain);

        for (gain = target_gain; gain >= 0.00f; gain -= (float) quantity/10000) {
#ifdef TRACE
            fprintf(stderr,"(Bridge Debug) - Fade-out set gain to %f\n", gain);
#endif
            alSourcef(Sources[the_sounds[index].source_index], AL_GAIN, gain);
            usleep(10000);
        }

        if (AL_NO_ERROR != alGetError())
            fprintf(stderr,"(Bridge Warning) - Failed to set fade-out effect\n");

        // stop that sound and reset its volume
        alSourceStop (Sources[the_sounds[index].source_index]);
        alSourcef (Sources[the_sounds[index].source_index], AL_GAIN, target_gain);
    }

    if (AL_NO_ERROR != alGetError())
        fprintf(stderr,"(Bridge Warning) - Failed to set fade effect\n");

#ifndef _WIN32
    pthread_exit(NULL);
#else
    _endthread();
#endif
}