예제 #1
0
/*
===================
idSoundSample::CheckForDownSample
===================
*/
void idSoundSample::CheckForDownSample( void ) {
	if( !idSoundSystemLocal::s_force22kHz.GetBool() ) {
		return;
	}
	if( objectInfo.wFormatTag != WAVE_FORMAT_TAG_PCM || objectInfo.nSamplesPerSec != 44100 ) {
		return;
	}
	int shortSamples = objectSize >> 1;
	short *converted = ( short * )soundCacheAllocator.Alloc( shortSamples * sizeof( short ) );
	if( objectInfo.nChannels == 1 ) {
		for( int i = 0; i < shortSamples; i++ ) {
			converted[i] = ( ( short * )nonCacheData )[i * 2];
		}
	} else {
		for( int i = 0; i < shortSamples; i += 2 ) {
			converted[i + 0] = ( ( short * )nonCacheData )[i * 2 + 0];
			converted[i + 1] = ( ( short * )nonCacheData )[i * 2 + 1];
		}
	}
	soundCacheAllocator.Free( nonCacheData );
	nonCacheData = ( byte * )converted;
	objectSize >>= 1;
	objectMemSize >>= 1;
	objectInfo.nAvgBytesPerSec >>= 1;
	objectInfo.nSamplesPerSec >>= 1;
}
예제 #2
0
/*
===================
idSoundSample::MakeDefault
===================
*/
void idSoundSample::MakeDefault( void ) {
	int		i;
	float	v;
	int		sample;
	memset( &objectInfo, 0, sizeof( objectInfo ) );
	objectInfo.nChannels = 1;
	objectInfo.wBitsPerSample = 16;
	objectInfo.nSamplesPerSec = 44100;
	objectSize = MIXBUFFER_SAMPLES * 2;
	objectMemSize = objectSize * sizeof( short );
	nonCacheData = ( byte * )soundCacheAllocator.Alloc( objectMemSize );
	short *ncd = ( short * )nonCacheData;
	for( i = 0; i < MIXBUFFER_SAMPLES; i ++ ) {
		v = sin( idMath::PI * 2 * i / 64 );
		sample = v * 0x4000;
		ncd[i * 2 + 0] = sample;
		ncd[i * 2 + 1] = sample;
	}
	if( idSoundSystemLocal::useOpenAL ) {
		alGetError();
		alGenBuffers( 1, &openalBuffer );
		if( alGetError() != AL_NO_ERROR ) {
			common->Error( "idSoundCache: error generating OpenAL hardware buffer" );
		}
		alGetError();
		alBufferData( openalBuffer, objectInfo.nChannels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, nonCacheData, objectMemSize, objectInfo.nSamplesPerSec );
		if( alGetError() != AL_NO_ERROR ) {
			common->Error( "idSoundCache: error loading data into OpenAL hardware buffer" );
		} else {
			hardwareBuffer = true;
		}
	}
	defaultSound = true;
}
예제 #3
0
/*
============
idStr::ReAllocate
============
*/
void idStr::ReAllocate( int amount, bool keepold )
{
	char*	newbuffer;
	int		newsize;
	int		mod;
	
	//assert( data );
	assert( amount > 0 );
	
	mod = amount % STR_ALLOC_GRAN;
	if( !mod )
	{
		newsize = amount;
	}
	else
	{
		newsize = amount + STR_ALLOC_GRAN - mod;
	}
	SetAlloced( newsize );
	
#ifdef USE_STRING_DATA_ALLOCATOR
	newbuffer = stringDataAllocator.Alloc( GetAlloced() );
#else
	newbuffer = new( TAG_STRING ) char[ GetAlloced() ];
#endif
	if( keepold && data )
	{
		data[ len ] = '\0';
		strcpy( newbuffer, data );
	}
	
	if( data && data != baseBuffer )
	{
#ifdef USE_STRING_DATA_ALLOCATOR
		stringDataAllocator.Free( data );
#else
		delete [] data;
#endif
	}
	
	data = newbuffer;
}
예제 #4
0
/*
===================
idSoundSample::Load

Loads based on name, possibly doing a MakeDefault if necessary
===================
*/
void idSoundSample::Load( void ) {
	defaultSound = false;
	purged = false;
	hardwareBuffer = false;
	timestamp = GetNewTimeStamp();
	if( timestamp == FILE_NOT_FOUND_TIMESTAMP ) {
		common->DWarning( "Couldn't load sound '%s' using default", name.c_str() );
		MakeDefault();
		return;
	}
	// load it
	idWaveFile	fh;
	waveformatex_t info;
	if( fh.Open( name, &info ) == -1 ) {
		common->DWarning( "Couldn't load sound '%s' using default", name.c_str() );
		MakeDefault();
		return;
	}
	if( info.nChannels != 1 && info.nChannels != 2 ) {
		common->Warning( "idSoundSample: %s has %i channels, using default", name.c_str(), info.nChannels );
		fh.Close();
		MakeDefault();
		return;
	}
	if( info.wBitsPerSample != 16 ) {
		common->Warning( "idSoundSample: %s is %dbits, expected 16bits using default", name.c_str(), info.wBitsPerSample );
		fh.Close();
		MakeDefault();
		return;
	}
	if( info.nSamplesPerSec != 44100 && info.nSamplesPerSec != 22050 && info.nSamplesPerSec != 11025 ) {
		common->Warning( "idSoundCache: %s is %dHz, expected 11025, 22050 or 44100 Hz. Using default", name.c_str(), info.nSamplesPerSec );
		fh.Close();
		MakeDefault();
		return;
	}
	objectInfo = info;
	objectSize = fh.GetOutputSize();
	objectMemSize = fh.GetMemorySize();
	nonCacheData = ( byte * )soundCacheAllocator.Alloc( objectMemSize );
	fh.Read( nonCacheData, objectMemSize, NULL );
	// optionally convert it to 22kHz to save memory
	CheckForDownSample();
	// create hardware audio buffers
	if( idSoundSystemLocal::useOpenAL ) {
		// PCM loads directly
		if( objectInfo.wFormatTag == WAVE_FORMAT_TAG_PCM ) {
			alGetError();
			alGenBuffers( 1, &openalBuffer );
			if( alGetError() != AL_NO_ERROR ) {
				common->Error( "idSoundCache: error generating OpenAL hardware buffer" );
			}
			if( alIsBuffer( openalBuffer ) ) {
				alGetError();
				alBufferData( openalBuffer, objectInfo.nChannels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, nonCacheData, objectMemSize, objectInfo.nSamplesPerSec );
				if( alGetError() != AL_NO_ERROR ) {
					common->Error( "idSoundCache: error loading data into OpenAL hardware buffer" );
				} else {
					hardwareBuffer = true;
				}
			}
		}
		// OGG decompressed at load time (when smaller than s_decompressionLimit seconds, 6 seconds by default)
		if( objectInfo.wFormatTag == WAVE_FORMAT_TAG_OGG ) {
#if defined(MACOS_X)
			if( ( objectSize < ( ( int ) objectInfo.nSamplesPerSec * idSoundSystemLocal::s_decompressionLimit.GetInteger() ) ) ) {
#else
			if( ( alIsExtensionPresent( ID_ALCHAR "EAX-RAM" ) == AL_TRUE ) && ( objectSize < ( ( int ) objectInfo.nSamplesPerSec * idSoundSystemLocal::s_decompressionLimit.GetInteger() ) ) ) {
#endif
				alGetError();
				alGenBuffers( 1, &openalBuffer );
				if( alGetError() != AL_NO_ERROR ) {
					common->Error( "idSoundCache: error generating OpenAL hardware buffer" );
				}
				if( alIsBuffer( openalBuffer ) ) {
					idSampleDecoder *decoder = idSampleDecoder::Alloc();
					float *destData = ( float * )soundCacheAllocator.Alloc( ( LengthIn44kHzSamples() + 1 ) * sizeof( float ) );
					// Decoder *always* outputs 44 kHz data
					decoder->Decode( this, 0, LengthIn44kHzSamples(), destData );
					// Downsample back to original frequency (save memory)
					if( objectInfo.nSamplesPerSec == 11025 ) {
						for( int i = 0; i < objectSize; i++ ) {
							if( destData[i * 4] < -32768.0f ) {
								( ( short * )destData )[i] = -32768;
							} else if( destData[i * 4] > 32767.0f ) {
								( ( short * )destData )[i] = 32767;
							} else {
								( ( short * )destData )[i] = idMath::FtoiFast( destData[i * 4] );
							}
						}
					} else if( objectInfo.nSamplesPerSec == 22050 ) {
						for( int i = 0; i < objectSize; i++ ) {
							if( destData[i * 2] < -32768.0f ) {
								( ( short * )destData )[i] = -32768;
							} else if( destData[i * 2] > 32767.0f ) {
								( ( short * )destData )[i] = 32767;
							} else {
								( ( short * )destData )[i] = idMath::FtoiFast( destData[i * 2] );
							}
						}
					} else {
						for( int i = 0; i < objectSize; i++ ) {
							if( destData[i] < -32768.0f ) {
								( ( short * )destData )[i] = -32768;
							} else if( destData[i] > 32767.0f ) {
								( ( short * )destData )[i] = 32767;
							} else {
								( ( short * )destData )[i] = idMath::FtoiFast( destData[i] );
							}
						}
					}
					alGetError();
					alBufferData( openalBuffer, objectInfo.nChannels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, destData, objectSize * sizeof( short ), objectInfo.nSamplesPerSec );
					if( alGetError() != AL_NO_ERROR ) {
						common->Error( "idSoundCache: error loading data into OpenAL hardware buffer" );
					} else {
						hardwareBuffer = true;
					}
					soundCacheAllocator.Free( ( byte * )destData );
					idSampleDecoder::Free( decoder );
				}
			}
		}
	}
	fh.Close();
}

/*
===================
idSoundSample::PurgeSoundSample
===================
*/
void idSoundSample::PurgeSoundSample() {
	purged = true;
	if( hardwareBuffer && idSoundSystemLocal::useOpenAL ) {
		alGetError();
		alDeleteBuffers( 1, &openalBuffer );
		if( alGetError() != AL_NO_ERROR ) {
			common->Error( "idSoundCache: error unloading data from OpenAL hardware buffer" );
		} else {
			openalBuffer = 0;
			hardwareBuffer = false;
		}
	}
	if( amplitudeData ) {
		soundCacheAllocator.Free( amplitudeData );
		amplitudeData = NULL;
	}
	if( nonCacheData ) {
		soundCacheAllocator.Free( nonCacheData );
		nonCacheData = NULL;
	}
}
예제 #5
0
/*
===================
idSoundSample::Load

Loads based on name, possibly doing a MakeDefault if necessary
===================
*/
void idSoundSample::Load( void ) {
	defaultSound = false;
	purged = false;
	hardwareBuffer = false;

	timestamp = GetNewTimeStamp();

	if ( timestamp == FILE_NOT_FOUND_TIMESTAMP ) {
		common->Warning( "Couldn't load sound '%s' using default", name.c_str() );
		MakeDefault();
		return;
	}

	// load it
	idWaveFile	fh;
	waveformatex_t info;

	if ( fh.Open( name, &info ) == -1 ) {
		common->Warning( "Couldn't load sound '%s' using default", name.c_str() );
		MakeDefault();
		return;
	}

	if ( info.nChannels != 1 && info.nChannels != 2 ) {
		common->Warning( "idSoundSample: %s has %i channels, using default", name.c_str(), info.nChannels );
		fh.Close();
		MakeDefault();
		return;
	}

	if ( info.wBitsPerSample != 16 ) {
		common->Warning( "idSoundSample: %s is %dbits, expected 16bits using default", name.c_str(), info.wBitsPerSample );
		fh.Close();
		MakeDefault();
		return;
	}

	if ( info.nSamplesPerSec != 44100 && info.nSamplesPerSec != 22050 && info.nSamplesPerSec != 11025 ) {
		common->Warning( "idSoundCache: %s is %dHz, expected 11025, 22050 or 44100 Hz. Using default", name.c_str(), info.nSamplesPerSec );
		fh.Close();
		MakeDefault();
		return;
	}

	objectInfo = info;
	objectSize = fh.GetOutputSize();
	objectMemSize = fh.GetMemorySize();

	nonCacheData = (byte *)soundCacheAllocator.Alloc( objectMemSize );
	fh.Read( nonCacheData, objectMemSize, NULL );

	// optionally convert it to 22kHz to save memory
	CheckForDownSample();

	// create hardware audio buffers
	// PCM loads directly
	if ( objectInfo.wFormatTag == WAVE_FORMAT_TAG_PCM ) {
		alGetError();
		alGenBuffers( 1, &openalBuffer );
		if ( alGetError() != AL_NO_ERROR )
			common->Error( "idSoundCache: error generating OpenAL hardware buffer" );
		if ( alIsBuffer( openalBuffer ) ) {
			alGetError();
			alBufferData( openalBuffer, objectInfo.nChannels==1?AL_FORMAT_MONO16:AL_FORMAT_STEREO16, nonCacheData, objectMemSize, objectInfo.nSamplesPerSec );
			if ( alGetError() != AL_NO_ERROR ) {
				common->Error( "idSoundCache: error loading data into OpenAL hardware buffer" );
			} else {
				// Compute amplitude block size
				int blockSize = 512 * objectInfo.nSamplesPerSec / 44100 ;

				// Allocate amplitude data array
				amplitudeData = (byte *)soundCacheAllocator.Alloc( ( objectSize / blockSize + 1 ) * 2 * sizeof( short) );

				// Creating array of min/max amplitude pairs per blockSize samples
				int i;
				for ( i = 0; i < objectSize; i+=blockSize ) {
					short min = 32767;
					short max = -32768;

					int j;
					for ( j = 0; j < Min( objectSize - i, blockSize ); j++ ) {
						min = ((short *)nonCacheData)[ i + j ] < min ? ((short *)nonCacheData)[ i + j ] : min;
						max = ((short *)nonCacheData)[ i + j ] > max ? ((short *)nonCacheData)[ i + j ] : max;
					}

					((short *)amplitudeData)[ ( i / blockSize ) * 2     ] = min;
					((short *)amplitudeData)[ ( i / blockSize ) * 2 + 1 ] = max;
				}

				hardwareBuffer = true;
			}
		}

		// OGG decompressed at load time (when smaller than s_decompressionLimit seconds, 6 seconds by default)
		if ( objectInfo.wFormatTag == WAVE_FORMAT_TAG_OGG ) {
			if ( ( objectSize < ( ( int ) objectInfo.nSamplesPerSec * idSoundSystemLocal::s_decompressionLimit.GetInteger() ) ) ) {
				alGetError();
				alGenBuffers( 1, &openalBuffer );
				if ( alGetError() != AL_NO_ERROR )
					common->Error( "idSoundCache: error generating OpenAL hardware buffer" );
				if ( alIsBuffer( openalBuffer ) ) {
					idSampleDecoder *decoder = idSampleDecoder::Alloc();
					float *destData = (float *)soundCacheAllocator.Alloc( ( LengthIn44kHzSamples() + 1 ) * sizeof( float ) );

					// Decoder *always* outputs 44 kHz data
					decoder->Decode( this, 0, LengthIn44kHzSamples(), destData );

					// Downsample back to original frequency (save memory)
					if ( objectInfo.nSamplesPerSec == 11025 ) {
						for ( int i = 0; i < objectSize; i++ ) {
							if ( destData[i*4] < -32768.0f )
								((short *)destData)[i] = -32768;
							else if ( destData[i*4] > 32767.0f )
								((short *)destData)[i] = 32767;
							else
								((short *)destData)[i] = idMath::FtoiFast( destData[i*4] );
						}
					} else if ( objectInfo.nSamplesPerSec == 22050 ) {
						for ( int i = 0; i < objectSize; i++ ) {
							if ( destData[i*2] < -32768.0f )
								((short *)destData)[i] = -32768;
							else if ( destData[i*2] > 32767.0f )
								((short *)destData)[i] = 32767;
							else
								((short *)destData)[i] = idMath::FtoiFast( destData[i*2] );
						}
					} else {
						for ( int i = 0; i < objectSize; i++ ) {
							if ( destData[i] < -32768.0f )
								((short *)destData)[i] = -32768;
							else if ( destData[i] > 32767.0f )
								((short *)destData)[i] = 32767;
							else
								((short *)destData)[i] = idMath::FtoiFast( destData[i] );
						}
					}

					alGetError();
					alBufferData( openalBuffer, objectInfo.nChannels==1?AL_FORMAT_MONO16:AL_FORMAT_STEREO16, destData, objectSize * sizeof( short ), objectInfo.nSamplesPerSec );
					if ( alGetError() != AL_NO_ERROR )
						common->Error( "idSoundCache: error loading data into OpenAL hardware buffer" );
					else {
						// Compute amplitude block size
						int blockSize = 512 * objectInfo.nSamplesPerSec / 44100 ;

						// Allocate amplitude data array
						amplitudeData = (byte *)soundCacheAllocator.Alloc( ( objectSize / blockSize + 1 ) * 2 * sizeof( short ) );

						// Creating array of min/max amplitude pairs per blockSize samples
						int i;
						for ( i = 0; i < objectSize; i+=blockSize ) {
							short min = 32767;
							short max = -32768;

							int j;
							for ( j = 0; j < Min( objectSize - i, blockSize ); j++ ) {
								min = ((short *)destData)[ i + j ] < min ? ((short *)destData)[ i + j ] : min;
								max = ((short *)destData)[ i + j ] > max ? ((short *)destData)[ i + j ] : max;
							}

							((short *)amplitudeData)[ ( i / blockSize ) * 2     ] = min;
							((short *)amplitudeData)[ ( i / blockSize ) * 2 + 1 ] = max;
						}

						hardwareBuffer = true;
					}

					soundCacheAllocator.Free( (byte *)destData );
					idSampleDecoder::Free( decoder );
				}
			}
		}

		// Free memory if sample was loaded into hardware
		if ( hardwareBuffer ) {
			soundCacheAllocator.Free( nonCacheData );
			nonCacheData = NULL;
		}
	}

	fh.Close();
}
예제 #6
0
void *_decoder_calloc( size_t num, size_t size ) {
	void *ptr = decoderMemoryAllocator.Alloc( num * size );
	assert( ( num * size ) == 0 || ptr != NULL );
	memset( ptr, 0, num * size );
	return ptr;
}
예제 #7
0
void *_decoder_malloc( size_t size ) {
	void *ptr = decoderMemoryAllocator.Alloc( size );
	assert( size == 0 || ptr != NULL );
	return ptr;
}