/* * S_HandlePositionedRawSamplesCmd */ static unsigned S_HandlePositionedRawSamplesCmd( const sndPositionedRawSamplesCmd_t *cmd ) { S_PositionedRawSamples( cmd->entnum, cmd->fvol, cmd->attenuation, cmd->samples, cmd->rate, cmd->width, cmd->channels, cmd->data ); S_Free( ( void * )cmd->data ); return sizeof( *cmd ); }
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_HandleRawSamplesCmd */ static unsigned S_HandleRawSamplesCmd( const sndRawSamplesCmd_t *cmd ) { S_RawSamples( cmd->samples, cmd->rate, cmd->width, cmd->channels, cmd->data, cmd->music ); S_Free( ( void * )cmd->data ); return sizeof( *cmd ); }
void S_ShutdownDecoders( qboolean verbose ) { S_Free( extensionlist ); extensionlist = NULL; extensionlist_size = 0; decoders = NULL; SNDOGG_Shutdown( verbose ); }
static void decoder_register( snd_decoder_t *decoder ) { decoder->next = decoders; decoders = decoder; if( extensionlist_size - strlen( extensionlist ) - 1 < strlen( decoder->ext ) + 1 ) { char *oldlist = extensionlist; extensionlist_size = max( extensionlist_size * 2, (int)( strlen( extensionlist ) + strlen( decoder->ext ) + 1 + 1 ) ); extensionlist = S_Malloc( extensionlist_size ); Q_strncpyz( extensionlist, oldlist, extensionlist_size ); S_Free( oldlist ); } Q_strncatz( extensionlist, " ", extensionlist_size ); Q_strncatz( extensionlist, decoder->ext, extensionlist_size ); }
void * stereo_mono( void *data, snd_info_t *info ) { int i, interleave, gain; void *outdata; outdata = S_Malloc( info->samples * info->width ); interleave = info->channels * info->width; gain = s_stereo2mono->integer; clamp( gain, -1, 1 ); if( info->width == 2 ) { short *pin, *pout; pin = (short*)data; pout = (short*)outdata; for( i = 0; i < info->size; i += interleave, pin += info->channels, pout++ ) { *pout = ((1-gain) * pin[0] + (1+gain) * pin[1]) / 2; } } else if( info->width == 1 ) { char *pin, *pout; pin = (char*)data; pout = (char*)outdata; for( i = 0; i < info->size; i += interleave, pin += info->channels, pout++ ) { *pout = ((1-gain) * pin[0] + (1+gain) * pin[1]) / 2; } } else { S_Free( outdata ); return NULL; } info->channels = 1; info->size = info->samples * info->width; return outdata; }
/* * SF_FreeSounds */ void SF_FreeSounds( void ) { int i; sfx_t *sfx; // wait for the queue to be processed S_FinishSoundCmdPipe( s_cmdPipe ); // free all sounds for( i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++ ) { if( !sfx->name[0] ) { continue; } S_Free( sfx->cache ); memset( sfx, 0, sizeof( *sfx ) ); } }
/* * S_StopBackgroundTrack */ void S_StopBackgroundTrack( void ) { bgTrack_t *next; S_CloseBackgroundTrackTask(); 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_bgTrackMuted = false; s_bgTrackPaused = false; }
/* * S_ShutdownSources */ void S_ShutdownSources( void ) { int i; if( !src_inited ) return; // Destroy all the sources for( i = 0; i < src_count; i++ ) { qalSourceStop( srclist[i].source ); qalDeleteSources( 1, &srclist[i].source ); } memset( srclist, 0, sizeof( srclist ) ); S_Free( entlist ); entlist = NULL; src_inited = qfalse; }
/* * SF_EndRegistration */ void SF_EndRegistration( void ) { int i; sfx_t *sfx; // wait for the queue to be processed S_FinishSoundCmdPipe( s_cmdPipe ); s_registering = false; // free any sounds not from this registration sequence for( i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++ ) { if( !sfx->name[0] ) { continue; } if( sfx->registration_sequence != s_registration_sequence ) { // we don't need this sound S_Free( sfx->cache ); memset( sfx, 0, sizeof( *sfx ) ); } } }
void *decoder_wav_load( const char *filename, snd_info_t *info ) { int filenum; int read; void *buffer; if( trap_FS_IsUrl( filename ) ) return NULL; trap_FS_FOpenFile( filename, &filenum, FS_READ|FS_NOSIZE ); if( !filenum ) return NULL; if( !read_wav_header( filenum, info ) ) { trap_FS_FCloseFile( filenum ); Com_Printf( "Can't understand .wav file: %s\n", filename ); return NULL; } buffer = S_Malloc( info->size ); read = trap_FS_Read( buffer, info->size, filenum ); if( read != info->size ) { S_Free( buffer ); trap_FS_FCloseFile( filenum ); Com_Printf( "Error reading .wav file: %s\n", filename ); return NULL; } byteSwapRawSamples( info->samples, info->width, info->channels, (qbyte *)buffer ); trap_FS_FCloseFile( filenum ); return buffer; }
/* * S_ReadPlaylistFile */ static bgTrack_t *S_ReadPlaylistFile( const char *filename, bool shuffle, bool loop ) { int filenum, length; char *tmpname = 0; size_t tmpname_size = 0; char *data, *line, *entry; playlistItem_t items[MAX_PLAYLIST_ITEMS]; int i, numItems = 0; length = trap_FS_FOpenFile( filename, &filenum, FS_READ ); if( length < 0 ) return NULL; // load the playlist into memory data = S_Malloc( length + 1 ); trap_FS_Read( data, length, filenum ); trap_FS_FCloseFile( filenum ); srand( time( NULL ) ); while( *data ) { size_t s; entry = data; // read the whole line for( line = data; *line != '\0' && *line != '\n'; line++ ); // continue reading from the next character, if possible data = (*line == '\0' ? line : line + 1); *line = '\0'; // trim whitespaces, tabs, etc entry = Q_trim( entry ); // special M3U entry or comment if( !*entry || *entry == '#' ) continue; if( trap_FS_IsUrl( entry ) ) { items[numItems].track = S_AllocTrack( entry ); } else { // append the entry name to playlist path s = strlen( filename ) + 1 + strlen( entry ) + 1; if( s > tmpname_size ) { if( tmpname ) S_Free( tmpname ); tmpname_size = s; tmpname = S_Malloc( tmpname_size ); } Q_strncpyz( tmpname, filename, tmpname_size ); COM_StripFilename( tmpname ); Q_strncatz( tmpname, "/", tmpname_size ); Q_strncatz( tmpname, entry, tmpname_size ); COM_SanitizeFilePath( tmpname ); items[numItems].track = S_AllocTrack( tmpname ); } if( ++numItems == MAX_PLAYLIST_ITEMS ) break; } if( tmpname ) { S_Free( tmpname ); tmpname = NULL; } if( !numItems ) return NULL; // set the playing order for( i = 0; i < numItems; i++ ) items[i].order = (shuffle ? (rand() % numItems) : i); // sort the playlist R_SortPlaylistItems( numItems, items ); // link the playlist for( i = 1; i < numItems; i++ ) { items[i-1].track->next = items[i].track; items[i].track->prev = items[i-1].track; items[i].track->loop = loop; } items[numItems-1].track->next = items[0].track; items[0].track->prev = items[numItems-1].track; items[0].track->loop = loop; return items[0].track; }
void *decoder_ogg_load( const char *filename, snd_info_t *info ) { OggVorbis_File vorbisfile; int filenum, bitstream, bytes_read, bytes_read_total; char *buffer; ov_callbacks callbacks = { ovcb_read, ovcb_seek, ovcb_close, ovcb_tell }; trap_FS_FOpenFile( filename, &filenum, FS_READ|FS_NOSIZE ); if( !filenum ) return NULL; if( trap_FS_IsUrl( filename ) ) { callbacks.seek_func = NULL; callbacks.tell_func = NULL; } qov_open_callbacks( (void *) (qintptr) filenum, &vorbisfile, NULL, 0, callbacks ); if( callbacks.seek_func && !qov_seekable( &vorbisfile ) ) { Com_Printf( "Error unsupported .ogg file (not seekable): %s\n", filename ); qov_clear( &vorbisfile ); // Does FS_FCloseFile return NULL; } if( qov_streams( &vorbisfile ) != 1 ) { Com_Printf( "Error unsupported .ogg file (multiple logical bitstreams): %s\n", filename ); qov_clear( &vorbisfile ); // Does FS_FCloseFile return NULL; } if( !read_ogg_header( vorbisfile, info ) ) { Com_Printf( "Error reading .ogg file header: %s\n", filename ); qov_clear( &vorbisfile ); // Does FS_FCloseFile return NULL; } buffer = S_Malloc( info->size ); bytes_read_total = 0; do { #ifdef ENDIAN_BIG bytes_read = qov_read( &vorbisfile, buffer+bytes_read_total, info->size-bytes_read_total, 1, 2, 1, &bitstream ); #elif defined (ENDIAN_LITTLE) bytes_read = qov_read( &vorbisfile, buffer+bytes_read_total, info->size-bytes_read_total, 0, 2, 1, &bitstream ); #else #error "runtime endianess detection support missing" #endif bytes_read_total += bytes_read; } while( bytes_read > 0 && bytes_read_total < info->size ); qov_clear( &vorbisfile ); // Does FS_FCloseFile if( !bytes_read_total ) { Com_Printf( "Error reading .ogg file: %s\n", filename ); S_Free( buffer ); return NULL; } return buffer; }
static void decoder_ogg_stream_shutdown( snd_stream_t *stream ) { S_Free( stream->ptr ); decoder_stream_shutdown( stream ); }
void decoder_stream_shutdown( snd_stream_t *stream ) { S_Free( stream ); }
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; }