Ejemplo n.º 1
0
Archivo: al.c Proyecto: jayschwa/q2pro
void AL_Update(void)
{
    int         i;
    channel_t   *ch;
    vec_t       orientation[6];

    if (!s_active) {
        return;
    }

    paintedtime = cl.time;

    // set listener parameters
    qalListener3f(AL_POSITION, AL_UnpackVector(listener_origin));
    AL_CopyVector(listener_forward, orientation);
    AL_CopyVector(listener_up, orientation + 3);
    qalListenerfv(AL_ORIENTATION, orientation);
    qalListenerf(AL_GAIN, s_volume->value);
    qalDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);

    // update spatialization for dynamic sounds
    ch = channels;
    for (i = 0; i < s_numchannels; i++, ch++) {
        if (!ch->sfx)
            continue;

        if (ch->autosound) {
            // autosounds are regenerated fresh each frame
            if (ch->autoframe != s_framecount) {
                AL_StopChannel(ch);
                continue;
            }
        } else {
            ALenum state;

            qalGetError();
            qalGetSourcei(ch->srcnum, AL_SOURCE_STATE, &state);
            if (qalGetError() != AL_NO_ERROR || state == AL_STOPPED) {
                AL_StopChannel(ch);
                continue;
            }
        }

#ifdef _DEBUG
        if (s_show->integer) {
            Com_Printf("%.1f %s\n", ch->master_vol, ch->sfx->name);
            //    total++;
        }
#endif

        AL_Spatialize(ch);         // respatialize channel
    }

    s_framecount++;

    // add loopsounds
    AL_AddLoopSounds();

    AL_IssuePlaysounds();
}
Ejemplo n.º 2
0
static void
AL_InitUnderwaterFilter()
{
#if defined (__APPLE__)
	return;
#else
	/* Generate a filter */
	qalGenFilters(1, &underwaterFilter);

	if (qalGetError() != AL_NO_ERROR)
	{
		Com_Printf("Couldn't generate an OpenAL filter!\n");
		return;
	}

	/* Low pass filter for underwater effect */
	qalFilteri(underwaterFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);

	if (qalGetError() != AL_NO_ERROR)
	{
		Com_Printf("Low pass filter is not supported!\n");
		return;
	}

	/* The effect */
	qalFilterf(underwaterFilter, AL_LOWPASS_GAIN, 1.5);
	qalFilterf(underwaterFilter, AL_LOWPASS_GAINHF, 0.25);
#endif
}
Ejemplo n.º 3
0
Archivo: al.c Proyecto: jayschwa/q2pro
void AL_PlayChannel(channel_t *ch)
{
    sfxcache_t *sc = ch->sfx->cache;

#ifdef _DEBUG
    if (s_show->integer > 1)
        Com_Printf("%s: %s\n", __func__, ch->sfx->name);
#endif

    ch->srcnum = s_srcnums[ch - channels];
    qalGetError();
    qalSourcei(ch->srcnum, AL_BUFFER, sc->bufnum);
    //qalSourcei(ch->srcnum, AL_LOOPING, sc->loopstart == -1 ? AL_FALSE : AL_TRUE);
    qalSourcei(ch->srcnum, AL_LOOPING, ch->autosound ? AL_TRUE : AL_FALSE);
    qalSourcef(ch->srcnum, AL_GAIN, ch->master_vol);
    qalSourcef(ch->srcnum, AL_REFERENCE_DISTANCE, SOUND_FULLVOLUME);
    qalSourcef(ch->srcnum, AL_MAX_DISTANCE, 8192);
    qalSourcef(ch->srcnum, AL_ROLLOFF_FACTOR, ch->dist_mult * (8192 - SOUND_FULLVOLUME));

    AL_Spatialize(ch);

    // play it
    qalSourcePlay(ch->srcnum);
    if (qalGetError() != AL_NO_ERROR) {
        AL_StopChannel(ch);
    }
}
Ejemplo n.º 4
0
Archivo: al.c Proyecto: jayschwa/q2pro
sfxcache_t *AL_UploadSfx(sfx_t *s)
{
    sfxcache_t *sc;
    ALsizei size = s_info.samples * s_info.width;
    ALenum format = s_info.width == 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8;
    ALuint name;

    if (!size) {
        s->error = Q_ERR_TOO_FEW;
        return NULL;
    }

    qalGetError();
    qalGenBuffers(1, &name);
    qalBufferData(name, format, s_info.data, size, s_info.rate);
    if (qalGetError() != AL_NO_ERROR) {
        s->error = Q_ERR_LIBRARY_ERROR;
        return NULL;
    }

    // allocate placeholder sfxcache
    sc = s->cache = S_Malloc(sizeof(*sc));
    sc->length = s_info.samples * 1000 / s_info.rate; // in msec
    sc->loopstart = s_info.loopstart;
    sc->width = s_info.width;
    sc->size = size;
    sc->bufnum = name;

    return sc;
}
Ejemplo n.º 5
0
/*
 * Set up the underwater filter
 */
static void
AL_InitUnderwaterFilter()
{
    underwaterFilter = 0;

    if (!(qalGenFilters && qalFilteri && qalFilterf && qalDeleteFilters))
        return;

	/* Generate a filter */
	qalGenFilters(1, &underwaterFilter);

	if (qalGetError() != AL_NO_ERROR)
	{
		Com_Printf("Couldn't generate an OpenAL filter!\n");
		return;
	}

	/* Low pass filter for underwater effect */
	qalFilteri(underwaterFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);

	if (qalGetError() != AL_NO_ERROR)
	{
		Com_Printf("Low pass filter is not supported!\n");
		return;
	}

    qalFilterf(underwaterFilter, AL_LOWPASS_GAIN, AL_LOWPASS_DEFAULT_GAIN);

    s_underwater->modified = true;
    s_underwater_gain_hf->modified = true;
}
Ejemplo n.º 6
0
/*
 * Initializes the OpenAL backend
 */
qboolean
AL_Init(void)
{
	int i;

	if (!QAL_Init())
	{
		Com_Printf("ERROR: OpenAL failed to initialize.\n");
		return false;
	}

	s_openal_maxgain = Cvar_Get("s_openal_maxgain", "1.0", CVAR_ARCHIVE);

	/* check for linear distance extension */
	if (!qalIsExtensionPresent("AL_EXT_LINEAR_DISTANCE"))
	{
		Com_Printf("ERROR: Required AL_EXT_LINEAR_DISTANCE extension is missing.\n");
		QAL_Shutdown();
		return false;
	}

	/* generate source names */
	qalGetError();
	qalGenSources(1, &streamSource);

	if (qalGetError() != AL_NO_ERROR)
	{
		Com_Printf("ERROR: Couldn't get a single Source.\n");
		QAL_Shutdown();
		return false;
	}
	else
	{
		/* -1 because we already got one channel for streaming */
		for (i = 0; i < MAX_CHANNELS - 1; i++)
		{
			qalGenSources(1, &s_srcnums[i]);

			if (qalGetError() != AL_NO_ERROR)
			{
				break;
			}
		}

		if (i < MIN_CHANNELS - 1)
		{
			Com_Printf("ERROR: Required at least %d sources, but got %d.\n",
					MIN_CHANNELS, i + 1);
			QAL_Shutdown();
			return false;
		}
	}

	s_numchannels = i;
	AL_InitStreamSource();
	AL_InitUnderwaterFilter();

	Com_Printf("Number of OpenAL sources: %d\n\n", s_numchannels);
	return true;
}
Ejemplo n.º 7
0
 /*
  * Uploads a sample to OpenAL and places
  * a dummy entry in the frontends cache.
  * This is not nice but necessary for the
  * frontend to work.
  */
 sfxcache_t *
 AL_UploadSfx ( sfx_t *s, wavinfo_t *s_info, byte *data )
 {
   sfxcache_t *sc;
   ALsizei size;
   ALenum format;
   ALuint name;
   size = s_info->samples * s_info->width;
   format = s_info->width == 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8;

   if ( !size ) {
     return NULL;
   }

   qalGetError();
   qalGenBuffers ( 1, &name );
   qalBufferData ( name, format, data, size, s_info->rate );
   active_buffers++;

   if ( qalGetError() != AL_NO_ERROR ) {
     return NULL;
   }

   /* allocate placeholder sfxcache */
   sc = s->cache = Z_TagMalloc ( sizeof ( *sc ), 0 );
   sc->length = s_info->samples * 1000 / s_info->rate;
   sc->loopstart = s_info->loopstart;
   sc->width = s_info->width;
   sc->size = size;
   sc->bufnum = name;
   return sc;
 }
Ejemplo n.º 8
0
 /*
  * Main update function. Called every frame,
  * performes all necessary calculations.
  */
 void
 AL_Update ( void )
 {
   q_int32_t i;
   channel_t *ch;
   vec_t orientation[6];
   paintedtime = cl.time;
   /* set listener (player) parameters */
   AL_CopyVector ( listener_forward, orientation );
   AL_CopyVector ( listener_up, orientation + 3 );
   qalListenerf ( AL_GAIN, s_volume->value );
   qalListenerf ( AL_MAX_GAIN, s_openal_maxgain->value );
   qalDistanceModel ( AL_LINEAR_DISTANCE_CLAMPED );
   qalListener3f ( AL_POSITION, AL_UnpackVector ( listener_origin ) );
   qalListenerfv ( AL_ORIENTATION, orientation );
   /* update spatialization for dynamic sounds */
   ch = channels;

   for ( i = 0; i < s_numchannels; i++, ch++ ) {
     if ( !ch->sfx ) {
       continue;
     }

     if ( ch->autosound ) {
       /* autosounds are regenerated fresh each frame */
       if ( ch->autoframe != s_framecount ) {
         AL_StopChannel ( ch );
         continue;
       }
     } else {
       ALenum state;
       qalGetError();
       qalGetSourcei ( ch->srcnum, AL_SOURCE_STATE, &state );

       if ( ( qalGetError() != AL_NO_ERROR ) || ( state == AL_STOPPED ) ) {
         AL_StopChannel ( ch );
         continue;
       }
     }

     if ( s_show->value ) {
       Com_Printf ( "%3i %s\n", ch->master_vol, ch->sfx->name );
     }

     /* respatialize channel */
     AL_Spatialize ( ch );
   }

   s_framecount++;
   /* add loopsounds */
   AL_AddLoopSounds();
   /* add music */
 #ifdef HT_WITH_OGG
   OGG_Stream();
 #endif
   AL_StreamUpdate();
   AL_IssuePlaysounds();
 }
Ejemplo n.º 9
0
/*
 * Plays a channel (in the frontends
 * sense) with OpenAL.
 */
void
AL_PlayChannel(channel_t *ch)
{
    sfxcache_t *sc;
    float vol;

    /* Debug */
    if (s_show->value > 1)
    {
        Com_Printf("%s: %s\n", __func__, ch->sfx->name);
    }

    /* Clamp volume */
    vol = ch->oal_vol;

    if (vol > 1.0f)
    {
        vol = 1.0f;
    }

    sc = ch->sfx->cache;
    ch->srcnum = s_srcnums[ch - channels];

    qalGetError();
    qalSourcef(ch->srcnum, AL_REFERENCE_DISTANCE, SOUND_FULLVOLUME);
    qalSourcef(ch->srcnum, AL_MAX_DISTANCE, 8192);
    qalSourcef(ch->srcnum, AL_ROLLOFF_FACTOR, ch->dist_mult * (8192 - SOUND_FULLVOLUME));
    qalSourcef(ch->srcnum, AL_GAIN, vol);
    qalSourcei(ch->srcnum, AL_BUFFER, sc->bufnum);
    qalSourcei(ch->srcnum, AL_LOOPING, ch->autosound ? AL_TRUE : AL_FALSE);

    if ((ch->entnum == -1) || (ch->entnum == cl.playernum + 1) || !ch->dist_mult)
    {
        /* anything coming from the view entity will always
         * be full volume and at the listeners position */
        qalSource3f(ch->srcnum, AL_POSITION, 0.0f, 0.0f, 0.0f);
        qalSourcei(ch->srcnum, AL_SOURCE_RELATIVE, AL_TRUE);
    }
    else
    {
        /* all other sources are *not* relative */
        qalSourcei(ch->srcnum, AL_SOURCE_RELATIVE, AL_FALSE);
    }


    /* Spatialize it */
    AL_Spatialize(ch);

    /* Play it */
    qalSourcePlay(ch->srcnum);

    /* Do not play broken channels */
    if (qalGetError() != AL_NO_ERROR)
    {
        AL_StopChannel(ch);
    }
}
Ejemplo n.º 10
0
/*
* S_InitSources
*/
qboolean S_InitSources( int maxEntities, qboolean verbose )
{
	int i;

	memset( srclist, 0, sizeof( srclist ) );
	src_count = 0;

	// Allocate as many sources as possible
	for( i = 0; i < MAX_SRC; i++ )
	{
		qalGenSources( 1, &srclist[i].source );
		if( qalGetError() != AL_NO_ERROR )
			break;
		src_count++;
	}
	if( !src_count )
		return qfalse;

	if( verbose )
		Com_Printf( "allocated %d sources\n", src_count );

	if( maxEntities < 1 )
		return qfalse;

	entlist = ( sentity_t * )S_Malloc( sizeof( sentity_t ) * maxEntities );

	src_inited = qtrue;
	return qtrue;
}
Ejemplo n.º 11
0
void S_StopBackgroundTrack( void )
{
    bgTrack_t *next;

    if( source )
        qalSourceStop( source );

    if( alloced_buffers ) {
        qalSourceUnqueueBuffers( source, MUSIC_BUFFERS, buffers );
        qalDeleteBuffers( MUSIC_BUFFERS, buffers );
        alloced_buffers = queued_buffers = qfalse;
    }

    music_source_free();

    qalGetError();

    while( s_bgTrackHead )
    {
        next = s_bgTrackHead->anext;

        S_CloseMusicTrack( s_bgTrackHead );
        S_Free( s_bgTrackHead );

        s_bgTrackHead = next;
    }

    s_bgTrack = NULL;
    s_bgTrackHead = NULL;

    s_bgTrackBuffering = qfalse;

    s_bgTrackPaused = qfalse;
}
/*
=================
S_AL_SrcInit
=================
*/
static
qboolean S_AL_SrcInit( void )
{
	int i;
	int limit;
	ALenum error;

	// Clear the sources data structure
	memset(srcList, 0, sizeof(srcList));
	srcCount = 0;

	// Cap s_alSources to MAX_SRC
	limit = s_alSources->integer;
	if(limit > MAX_SRC)
		limit = MAX_SRC;
	else if(limit < 16)
		limit = 16;

	// Allocate as many sources as possible
	for(i = 0; i < limit; i++)
	{
		qalGenSources(1, &srcList[i].alSource);
		if((error = qalGetError()) != AL_NO_ERROR)
			break;
		srcCount++;
	}

	// All done. Print this for informational purposes
	Com_Printf( "Allocated %d sources.\n", srcCount);
	alSourcesInitialised = qtrue;
	return qtrue;
}
Ejemplo n.º 13
0
/*
 * Plays a channel (in the frontends
 * sense) with OpenAL.
 */
void
AL_PlayChannel(channel_t *ch)
{
	sfxcache_t *sc;
	float vol;

	/* Debug */
	if (s_show->value > 1)
	{
		Com_Printf("%s: %s\n", __func__, ch->sfx->name);
	}

	/* Clamp volume */
	vol = ch->oal_vol + s_volume->value;

	if (vol > 1.0f)
	{
		vol = 1.0f;
	}

    sc = ch->sfx->cache;
	ch->srcnum = s_srcnums[ch - channels];

	qalGetError();
	qalSourcef(ch->srcnum, AL_REFERENCE_DISTANCE, SOUND_FULLVOLUME);
	qalSourcef(ch->srcnum, AL_MAX_DISTANCE, 8192);
	qalSourcef(ch->srcnum, AL_ROLLOFF_FACTOR, ch->dist_mult * (8192 - SOUND_FULLVOLUME));
	qalSourcef(ch->srcnum, AL_GAIN, vol);
 	qalSourcei(ch->srcnum, AL_BUFFER, sc->bufnum);
	qalSourcei(ch->srcnum, AL_LOOPING, ch->autosound ? AL_TRUE : AL_FALSE);

	/* Spatialize it */
	AL_Spatialize(ch);

	/* Play it */
	qalSourcePlay(ch->srcnum);

	/* Do not play broken channels */
	if (qalGetError() != AL_NO_ERROR)
	{
		AL_StopChannel(ch);
	}
}
Ejemplo n.º 14
0
Archivo: al.c Proyecto: jayschwa/q2pro
qboolean AL_Init(void)
{
    int i;

    Com_DPrintf("Initializing OpenAL\n");

    if (!QAL_Init()) {
        goto fail0;
    }

    // check for linear distance extension
    if (!qalIsExtensionPresent("AL_EXT_LINEAR_DISTANCE")) {
        Com_SetLastError("AL_EXT_LINEAR_DISTANCE extension is missing");
        goto fail1;
    }

    // generate source names
    qalGetError();
    for (i = 0; i < MAX_CHANNELS; i++) {
        qalGenSources(1, &s_srcnums[i]);
        if (qalGetError() != AL_NO_ERROR) {
            break;
        }
    }

    Com_DPrintf("Got %d AL sources\n", i);

    if (i < MIN_CHANNELS) {
        Com_SetLastError("Insufficient number of AL sources");
        goto fail1;
    }

    s_numchannels = i;

    Com_Printf("OpenAL initialized.\n");
    return qtrue;

fail1:
    QAL_Shutdown();
fail0:
    Com_EPrintf("Failed to initialize OpenAL: %s\n", Com_GetLastError());
    return qfalse;
}
Ejemplo n.º 15
0
/*
=================
S_AL_ClearError
=================
*/
static void S_AL_ClearError( qboolean quiet )
{
	int error = qalGetError();

	if( quiet )
		return;
	if(error != AL_NO_ERROR)
		Com_Printf(S_COLOR_YELLOW "WARNING: unhandled AL error: %s\n",
			S_AL_ErrorMsg(error));
}
Ejemplo n.º 16
0
static qboolean music_process( ALuint b )
{
    int l = 0;
    ALuint format;
    ALenum error;
    snd_stream_t *music_stream;

start:
    if( s_bgTrackBuffering )
        return qtrue;

    music_stream = s_bgTrack->stream;
    if( music_stream ) {
        l = S_ReadStream( music_stream, MUSIC_BUFFER_SIZE, decode_buffer );
    }
    else {
        l = 0;
    }

    if( !l )
    {
        bgTrack_t *cur;

        cur = s_bgTrack;
        if( !S_AdvanceBackgroundTrack( 1 ) )
        {
            if( !S_ValidMusicFile( s_bgTrack ) )
                return qfalse;
        }
        else
        {
            // we've advanced to the next track, close this one
            S_CloseMusicTrack( cur );
            goto start;
        }

        if( !S_ResetStream( music_stream ) )
        {
            // if failed, close the track?
            return qfalse;
        }

        goto start;
    }

    format = S_SoundFormat( music_stream->info.width, music_stream->info.channels );
    qalBufferData( b, format, decode_buffer, l, music_stream->info.rate );
    if( ( error = qalGetError() ) != AL_NO_ERROR )
        return qfalse;

    return qtrue;
}
Ejemplo n.º 17
0
/*
* S_GetBufferLength
*
* Returns buffer length expressed in milliseconds
*/
ALuint S_GetBufferLength( ALuint buffer )
{
    ALint size, bits, channels, freq;

    qalGetBufferi( buffer, AL_SIZE, &size );
    qalGetBufferi( buffer, AL_BITS, &bits );
    qalGetBufferi( buffer, AL_FREQUENCY, &freq );
    qalGetBufferi( buffer, AL_CHANNELS, &channels );

	if( qalGetError() != AL_NO_ERROR ) {
        return 0;
	}
    return (ALuint)((ALfloat)(size/(bits/8)/channels) * 1000.0 / freq + 0.5f);
}
Ejemplo n.º 18
0
qboolean AL_Init( void ) {
    int i;

    if( !QAL_Init() ) {
        Com_EPrintf( "OpenAL failed to initialize.\n" );
        return qfalse;
    }

    // check for linear distance extension
    if( !qalIsExtensionPresent( "AL_EXT_LINEAR_DISTANCE" ) ) {
        Com_EPrintf( "Required AL_EXT_LINEAR_DISTANCE extension is missing.\n" );
        goto fail;
    }

    // generate source names
    qalGetError();
    for( i = 0; i < MAX_CHANNELS; i++ ) {
        qalGenSources( 1, &s_srcnums[i] );
        if( qalGetError() != AL_NO_ERROR ) {
            break;
        }
    }

    if( i < MIN_CHANNELS ) {
        Com_EPrintf( "Required at least %d sources, but got %d.\n", MIN_CHANNELS, i );
        goto fail;
    }

    s_numchannels = i;

    Com_Printf( "OpenAL initialized.\n" );
    return qtrue;

fail:
    QAL_Shutdown();
    return qfalse;
}
Ejemplo n.º 19
0
static void AL_InitUnderwaterFilter()
{
	// Generate a filter
	qalGenFilters(1, &underwaterFilter);

	if (qalGetError() != AL_NO_ERROR)
	{
		Com_Printf("Couldn't generate an OpenAL filter!\n");
		return;
	}

	// Low pass filter for underwater effect
	qalFilteri(underwaterFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);

	if (qalGetError() != AL_NO_ERROR)
	{
		Com_Printf("Low pass filter is not supported!\n");
		return;
	}

	// The effect
	qalFilterf(underwaterFilter, AL_LOWPASS_GAIN, 1.5);
	qalFilterf(underwaterFilter, AL_LOWPASS_GAINHF, 0.25);
}
/*
=================
S_AL_BufferUnload
=================
*/
static void S_AL_BufferUnload(sfxHandle_t sfx)
{
	ALenum error;

	if(knownSfx[sfx].filename[0] == '\0')
		return;

	if(!knownSfx[sfx].inMemory)
		return;

	// Delete it
	qalDeleteBuffers(1, &knownSfx[sfx].buffer);
	if((error = qalGetError()) != AL_NO_ERROR)
		Com_Printf( S_COLOR_RED "ERROR: Can't delete sound buffer for %s\n",
				knownSfx[sfx].filename);

	knownSfx[sfx].inMemory = qfalse;
}
Ejemplo n.º 21
0
bool S_UnloadBuffer( sfx_t *sfx )
{
	ALenum error;

	if( !sfx ) {
		return false;
	}
	if( sfx->filename[0] == '\0' || sfx->isLocked || !sfx->inMemory )
		return false;

	qalDeleteBuffers( 1, &sfx->buffer );
	if( ( error = qalGetError() ) != AL_NO_ERROR )
	{
		Com_Printf( "Couldn't delete sound buffer for %s (%s)", sfx->filename, S_ErrorMessage( error ) );
		sfx->isLocked = true;
		return false;
	}

	sfx->inMemory = false;

	return true;
}
/*
=================
S_AL_BufferLoad
=================
*/
static void S_AL_BufferLoad(sfxHandle_t sfx)
{
	ALenum error;

	void *data;
	snd_info_t info;
	ALuint format;

	// Nothing?
	if(knownSfx[sfx].filename[0] == '\0')
		return;

	// Player SFX
	if(knownSfx[sfx].filename[0] == '*')
		return;

	// Already done?
	if((knownSfx[sfx].inMemory) || (knownSfx[sfx].isDefault))
		return;

	// Try to load
	data = S_CodecLoad(knownSfx[sfx].filename, &info);
	if(!data)
	{
		S_AL_BufferUseDefault(sfx);
		return;
	}

	format = S_AL_Format(info.width, info.channels);

	// Create a buffer
	qalGenBuffers(1, &knownSfx[sfx].buffer);
	if((error = qalGetError()) != AL_NO_ERROR)
	{
		S_AL_BufferUseDefault(sfx);
		Z_Free(data);
		Com_Printf( S_COLOR_RED "ERROR: Can't create a sound buffer for %s - %s\n",
				knownSfx[sfx].filename, S_AL_ErrorMsg(error));
		return;
	}

	// Fill the buffer
	if( info.size == 0 )
	{
		// We have no data to buffer, so buffer silence
		byte dummyData[ 2 ] = { 0 };

		qalBufferData(knownSfx[sfx].buffer, AL_FORMAT_MONO16, (void *)dummyData, 2, 22050);
	}
	else
		qalBufferData(knownSfx[sfx].buffer, format, data, info.size, info.rate);

	error = qalGetError();

	// If we ran out of memory, start evicting the least recently used sounds
	while(error == AL_OUT_OF_MEMORY)
	{
		if( !S_AL_BufferEvict( ) )
		{
			S_AL_BufferUseDefault(sfx);
			Z_Free(data);
			Com_Printf( S_COLOR_RED "ERROR: Out of memory loading %s\n", knownSfx[sfx].filename);
			return;
		}

		// Try load it again
		qalBufferData(knownSfx[sfx].buffer, format, data, info.size, info.rate);
		error = qalGetError();
	}

	// Some other error condition
	if(error != AL_NO_ERROR)
	{
		S_AL_BufferUseDefault(sfx);
		Z_Free(data);
		Com_Printf( S_COLOR_RED "ERROR: Can't fill sound buffer for %s - %s\n",
				knownSfx[sfx].filename, S_AL_ErrorMsg(error));
		return;
	}

	// Free the memory
	Z_Free(data);

	// Woo!
	knownSfx[sfx].inMemory = qtrue;
}
/*
=================
S_AL_MusicProcess
=================
*/
static
void S_AL_MusicProcess(ALuint b)
{
	ALenum error;
	int l;
	ALuint format;
	snd_stream_t *curstream;

	if(intro_stream)
		curstream = intro_stream;
	else
		curstream = mus_stream;

	if(!curstream)
		return;

	l = S_CodecReadStream(curstream, MUSIC_BUFFER_SIZE, decode_buffer);

	// Run out data to read, start at the beginning again
	if(l == 0)
	{
		S_CodecCloseStream(curstream);

		// the intro stream just finished playing so we don't need to reopen
		// the music stream.
		if(intro_stream)
			intro_stream = NULL;
		else
			mus_stream = S_CodecOpenStream(s_backgroundLoop);
		
		curstream = mus_stream;

		if(!curstream)
		{
			S_AL_StopBackgroundTrack();
			return;
		}

		l = S_CodecReadStream(curstream, MUSIC_BUFFER_SIZE, decode_buffer);
	}

	format = S_AL_Format(curstream->info.width, curstream->info.channels);

	if( l == 0 )
	{
		// We have no data to buffer, so buffer silence
		byte dummyData[ 2 ] = { 0 };

		qalBufferData( b, AL_FORMAT_MONO16, (void *)dummyData, 2, 22050 );
	}
	else
		qalBufferData(b, format, decode_buffer, l, curstream->info.rate);

	if( ( error = qalGetError( ) ) != AL_NO_ERROR )
	{
		S_AL_StopBackgroundTrack( );
		Com_Printf( S_COLOR_RED "ERROR: while buffering data for music stream - %s\n",
				S_AL_ErrorMsg( error ) );
		return;
	}
}
Ejemplo n.º 24
0
bool S_LoadBuffer( sfx_t *sfx )
{
	ALenum error;
	void *data;
	snd_info_t info;
	ALuint format;

	if( !sfx ) {
		return false;
	}
	if( sfx->filename[0] == '\0' || sfx->inMemory )
		return false;
	if( trap_FS_IsUrl( sfx->filename ) )
		return false;

	data = S_LoadSound( sfx->filename, &info );
	if( !data )
	{
		//Com_DPrintf( "Couldn't load %s\n", sfx->filename );
		return false;
	}

	if( info.channels > 1 )
	{
		void *temp = stereo_mono( data, &info );
		if( temp )
		{
			S_Free( data );
			data = temp;
		}
	}

	format = S_SoundFormat( info.width, info.channels );

	qalGenBuffers( 1, &sfx->buffer );
	if( ( error = qalGetError() ) != AL_NO_ERROR )
	{
		S_Free( data );
		Com_Printf( "Couldn't create a sound buffer for %s (%s)\n", sfx->filename, S_ErrorMessage( error ) );
		return false;
	}

	qalBufferData( sfx->buffer, format, data, info.size, info.rate );
	error = qalGetError();

	// If we ran out of memory, start evicting the least recently used sounds
	while( error == AL_OUT_OF_MEMORY )
	{
		if( !buffer_evict() )
		{
			S_Free( data );
			Com_Printf( "Out of memory loading %s\n", sfx->filename );
			return false;
		}

		// Try load it again
		qalGetError();
		qalBufferData( sfx->buffer, format, data, info.size, info.rate );
		error = qalGetError();
	}

	// Some other error condition
	if( error != AL_NO_ERROR )
	{
		S_Free( data );
		Com_Printf( "Couldn't fill sound buffer for %s (%s)", sfx->filename, S_ErrorMessage( error ) );
		return false;
	}

	S_Free( data );
	sfx->inMemory = true;

	return true;
}
Ejemplo n.º 25
0
void S_UpdateMusic( void )
{
    int i, processed;
    ALint state;
    ALenum error;
    ALuint b;
    int num_processed_buffers;
    ALuint processed_buffers[MUSIC_BUFFERS];

    if( !s_bgTrack )
        return;
    if( !s_musicvolume->value && !s_bgTrack->isUrl )
        return;
    if( s_bgTrackPaused || s_bgTrackLocked )
        return;

    if( s_bgTrackBuffering )
    {
        if( S_EoStream( s_bgTrack->stream ) ) {
            // we should now advance to the next track
            S_CloseMusicTrack( s_bgTrack );
        }
        else {
            if( S_FTellSteam( s_bgTrack->stream ) < BACKGROUND_TRACK_BUFFERING_SIZE )
                return;

            // in case we delayed openening to let the stream be cached for a while,
            // start actually reading from it now
            if( !S_ContOpenStream( s_bgTrack->stream ) ) {
                // let music_process do the dirty job of advancing to the next track
                S_CloseMusicTrack( s_bgTrack );
                s_bgTrack->ignore = qtrue;
            }
        }
        s_bgTrackBuffering = qfalse;
    }

    if( !queued_buffers )
    {
        // if we haven't queued any buffers yet, do it now
        num_processed_buffers = MUSIC_BUFFERS;
        memcpy( processed_buffers, buffers, sizeof( buffers ) );
    }
    else
    {
        num_processed_buffers = 0;

        processed = 0;
        qalGetSourcei( source, AL_BUFFERS_PROCESSED, &processed );
        while( processed-- )
        {
            qalSourceUnqueueBuffers( source, 1, &b );
            processed_buffers[num_processed_buffers++] = b;
        }
    }

    for( i = 0; i < num_processed_buffers; i++ )
    {
        b = processed_buffers[i];
        if( !music_process( b ) )
        {
            Com_Printf( "Error processing music data\n" );
            S_StopBackgroundTrack();
            return;
        }

        qalSourceQueueBuffers( source, 1, &b );
        if( ( error = qalGetError() ) != AL_NO_ERROR )
        {
            Com_Printf( "Couldn't queue music data (%s)\n", S_ErrorMessage( error ) );
            S_StopBackgroundTrack();
            return;
        }
    }

    // If it's not still playing, give it a kick
    qalGetSourcei( source, AL_SOURCE_STATE, &state );
    if( !queued_buffers || state != AL_PLAYING )
    {
        queued_buffers = qtrue;
        qalSourcePlay( source );
    }

    if( s_musicvolume->modified )
        qalSourcef( source, AL_GAIN, s_musicvolume->value );
}
Ejemplo n.º 26
0
void S_StartBackgroundTrack( const char *intro, const char *loop )
{
    int count;
    const char *ext;
    bgTrack_t *t, f;
    bgTrack_t *introTrack, *loopTrack;
    ALenum error;
    int mode = 0;

    // Stop any existing music that might be playing
    S_StopBackgroundTrack();

    if( !intro || !intro[0] )
        return;

    s_bgTrackPaused = qfalse;

    ext = COM_FileExtension( intro );
    if( ext && !Q_stricmp( ext, ".m3u" ) )
    {
        // mode bits:
        // 1 - shuffle
        // 2 - loop the selected track
        if( loop && loop[0] )
            mode = atoi( loop );

        if( S_ReadPlaylistFile( intro, mode & 1 ? qtrue : qfalse ) )
            goto start_playback;
    }

    // the intro track loops unless another loop track has been specified
    introTrack = S_AllocTrack( intro );
    introTrack->next = introTrack->prev = introTrack;

    if( loop && loop[0] && Q_stricmp( intro, loop ) )
    {
        loopTrack = S_AllocTrack( loop );
        if( S_OpenMusicTrack( loopTrack ) )
        {
            S_CloseMusicTrack( loopTrack );
            loopTrack->next = introTrack->next = introTrack->prev = loopTrack;
            loopTrack->prev = introTrack;
        }
    }

    s_bgTrack = introTrack;

start_playback:
    // this effectively precaches the first 15 scheduled tracks in the playlist
    for( count = 0, t = s_bgTrack; count < 15 && t && t != s_bgTrack; count++ )
    {
        if( !t->isUrl )
        {
            S_OpenMusicTrack( t );

            if( t->next == t || t->next == s_bgTrack )
                break; // break on an endless loop or full cycle
            if( !t->ignore && ( mode & 2 ) )
            {
                // no point in precaching the whole playlist when we're only going
                // to loop one single track
                break;
            }
        }
        t = t->next;
    }

    // start playback with the first valid track
    if( count > 1 )
    {
        memset( &f, 0, sizeof( f ) );
        f.next = s_bgTrack;

        s_bgTrack = S_NextMusicTrack( &f );
    }
    else
    {
        S_OpenMusicTrack( s_bgTrack );
    }

    if( !s_bgTrack || s_bgTrack->ignore )
    {
        S_StopBackgroundTrack();
        return;
    }

    if( mode & 2 )
    {
        // loop the same track over and over
        s_bgTrack->next = s_bgTrack->prev = s_bgTrack;
    }

    music_source_get();
    if( !src )
    {
        Com_Printf( "Error couldn't get source for music\n" );
        S_StopBackgroundTrack();
        return;
    }

    alloced_buffers = qfalse;
    queued_buffers = qfalse;

    qalGenBuffers( MUSIC_BUFFERS, buffers );
    if( ( error = qalGetError() ) != AL_NO_ERROR )
    {
        Com_Printf( "Error couldn't generate music buffers (%s)\n", S_ErrorMessage( error ) );
        S_StopBackgroundTrack();
        return;
    }

    alloced_buffers = qtrue;
}