Example #1
0
bool OpenALMusicPlayer::streamBuffer(ALuint buffer)
{
	char pcm[BUFFERSIZE];
	int size = 0;
	const char* error = '\0';
	
	if (!stream->read(pcm, BUFFERSIZE, &size, error)) {
		GfError("OpenALMusicPlayer: Stream read error: %s\n", error);
		return false;
	} else {
		int format;
		switch (stream->getSoundFormat()) {
			case SoundStream::FORMAT_MONO16:
				format = AL_FORMAT_MONO16;
				break;
			case SoundStream::FORMAT_STEREO16:
				format = AL_FORMAT_STEREO16;
				break;
			default:
				GfError("OpenALMusicPlayer: Format error: \n");
				return false;
		}
		
		alBufferData(buffer, format, pcm, size, stream->getRateInHz());
		return check();
	}
}
Example #2
0
static tPSCommand* parseFormulaStringIntern( char **string )
{
	parseSkipWhitespace( string );
	char ret = TRUE;
	tPSCommand *result = NULL;
	tPSCommand *current = NULL;
	
	while( ret ) {
		if( (*string)[0] == '{' ) {
			ret = parseSubCommands( string, &current );
		} else if( (*string)[0] >= '0' && (*string)[0] <= '9' ) {
			ret = parseNumber( string, &current );
		} else if( ( (*string)[0] >= 'a' && (*string)[0] <= 'z' ) || ( (*string)[0] >= 'A' && (*string)[0] <= 'Z' ) ) {
			ret = parseCommandVar( string, &current );
		} else if( (*string)[0] == '\0' || (*string)[0] == '}' ) {
			return result;
		} else if( (*string)[0] == '%' ) {
			parseSkipComment( string );
		} else {
			GfError( "Invalid token found: %c.", (*string)[0] );
			ret = FALSE;
		}
		if( current && !result )
			result = current;
		parseSkipWhitespace( string );
	}

	return result;
}
Example #3
0
bool OpenALMusicPlayer::playAndManageBuffer()
{
	if (!ready) {
		return false;
	}
	
	int processed;
	bool active = true;

	alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);

	while(processed--) {
		ALuint buffer;
		
		alSourceUnqueueBuffers(source, 1, &buffer);
		check();
		active = streamBuffer(buffer);
		alSourceQueueBuffers(source, 1, &buffer);
		check();
	}

	if (!active && !isPlaying()) {
		// Try to reanimate playback
		if(!startPlayback()) {
			GfError("OpenALMusicPlayer: Cannot play stream.\n");
		}
	}
	
	return true;
}
Example #4
0
bool OpenALMusicPlayer::initContext()
{
	device = alcOpenDevice(NULL);
	if( device == NULL ) {
		GfError("OpenALMusicPlayer: OpenAL could not open device\n");
		return false;
	}

	context = alcCreateContext(device, NULL);
	if(context == NULL) {
		alcCloseDevice(device);
		GfError("OpenALMusicPlayer: OpenAL could not create contect for device\n");
		return false;
	}

	alcMakeContextCurrent(context);
	alcGetError(device);
	
	return check();
}
Example #5
0
bool OpenALMusicPlayer::check()
{
	int error = alGetError();

	if(error != AL_NO_ERROR) {
		GfError("OpenALMusicPlayer: OpenAL error was raised: %d\n", error);
		return false;
	}

	return true;
}
Example #6
0
static void simplifyToParse( tFormNode **node )
{
	tFormNode *curNode = *node;
	tFormNode *prevNode = NULL;
	char skipChilds;
	char againThisNode;

	while( curNode ) {
		skipChilds = FALSE;
		againThisNode = FALSE;
		if( curNode->type == FORMNODE_TYPE_TOPARSE_BLOCK ) {
			if( curNode->firstChild == NULL ) {
				prevNode->next = curNode->next;
				FREEZ( curNode->string );
				free( curNode );
				curNode = prevNode;
				skipChilds = TRUE;
			} else {
				if( curNode->firstChild->next == NULL ) {
					if( prevNode ) {
						prevNode->next = curNode->firstChild;
						prevNode->next->next = curNode->next;
						FREEZ( curNode->string );
						free( curNode );
						curNode = prevNode->next;
					} else {
						*node = curNode->firstChild;
						(*node)->next = curNode->next;
						FREEZ( curNode->string );
						free( curNode );
						curNode = *node;
					}
					againThisNode = TRUE;
				} else {
					GfError( "WARNING: could not simplify all blocks in a formula\n" );
				}
			}
		} else if( curNode->type == FORMNODE_TYPE_TOPARSE_STRING ) {
			/* Unparsed string found: assume variable */
			curNode->type = FORMNODE_TYPE_VARIABLE;
		}

		if( !skipChilds && curNode->firstChild )
			simplifyToParse( &(curNode->firstChild) );

		if( !againThisNode ) {
			prevNode = curNode;
			curNode = curNode->next;
		}
	}
}
Example #7
0
void OpenALMusicPlayer::start()
{
	if (!ready) {
		if (stream->getSoundFormat() == SoundStream::FORMAT_INVALID) {
			GfError("OpenALMusicPlayer: Sound stream has invalid format\n");
			return;
		}
		
		if (initContext() && initBuffers() && initSource()) {
			ready = true;
			startPlayback();
		}
		
		return;
	}
}
Example #8
0
bool OpenALMusicPlayer::initSource()
{
    alGenSources(1, &source);
    if (!check()) {
		GfError("OpenALMusicPlayer: initSource failed to get sound source.\n");
		return false;
	};
    
    alSource3f(source, AL_POSITION,        0.0, 0.0, 0.0);
    alSource3f(source, AL_VELOCITY,        0.0, 0.0, 0.0);
    alSource3f(source, AL_DIRECTION,       0.0, 0.0, 0.0);
    alSourcef (source, AL_ROLLOFF_FACTOR,  0.0          );
    alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE      );
	
	return true;
}
Example #9
0
void GfFormFreeCommand( void *commands )
{
	tPSCommand *next;
	tPSCommand *current = (tPSCommand*)commands;
	while( current ) {
		if( current->data ) {
			if( current->func == &cmdPushVar )
				free( current->data );
			else if( current->func == &cmdPushNumber )
				free( current->data );
			else if( current->func == &cmdPushCommand )
				GfFormFreeCommand( (tPSCommand*)current->data );
			else
				GfError( "WARNING: Data found, but no clue about it's contents\n" );
		}
		next = current->next;
		free( current );
		current = next;
	}
}
Example #10
0
// Create the left walls, start must point to a segment with a wall on the left and a leading
// non wall segment.
// FIXME: Does not work for a closed ring "by design".
void buildWalls(tTrackSeg *start, int side) {

	if (start == NULL) {
		return;
	}

	tTrackSeg *current = start;
	bool close = false;

	// Going down the wall.
	do {
		tTrackSeg* s = current->side[side];
		tTrackSeg* p = current->prev->side[side];
		tTrackSeg* n = current->next->side[side];

		// Current segment is a wall?
		if (s != NULL && s->style == TR_WALL && s->side[side] != NULL) {

			float h = s->height;
			t3Dd svl = s->vertex[TR_SL];
			t3Dd svr = s->vertex[TR_SR];
			t3Dd evl = s->vertex[TR_EL];
			t3Dd evr = s->vertex[TR_ER];
			static float weps = 0.01f;

			// Close the start with a ploygon?
			if (p == NULL || p->style != TR_WALL ||
				(fabs(p->vertex[TR_EL].x - svl.x) > weps) ||
				(fabs(p->vertex[TR_ER].x - svr.x) > weps) ||
				(fabs(h - p->height) > weps) ||
				fixedid == 0)
			{
				// Enough space in array?
				if (fixedid >= sizeof(fixedobjects)/sizeof(fixedobjects[0])) {
					GfError("fixedobjects full in %s, line %d\n", __FILE__, __LINE__);
					return;
				}

				if (close == true) {
					dtEndComplexShape();
					GfError("Shape not closed %s, line %d\n", __FILE__, __LINE__);
				}

				// Start new shape.
				fixedobjects[fixedid] = dtNewComplexShape();
				fixedid++;
				close = true;

				dtBegin(DT_POLYGON);
					dtVertex(svl.x, svl.y, svl.z);
					dtVertex(svr.x, svr.y, svr.z);
					dtVertex(svr.x, svr.y, svr.z + h);
					dtVertex(svl.x, svl.y, svl.z + h);
				dtEnd();
			}

			// Build sides, left, top, right. Depending on how we want to use it we
			// can remove top perhaps.
			// TODO: do we want the top poly?
			if (close == true) {
				// Left.
				dtBegin(DT_POLYGON);
					dtVertex(svl.x, svl.y, svl.z);
					dtVertex(svl.x, svl.y, svl.z + h);
					dtVertex(evl.x, evl.y, evl.z + h);
					dtVertex(evl.x, evl.y, evl.z);
				dtEnd();
				/*
				// Top.
				dtBegin(DT_POLYGON);
					dtVertex(svl.x, svl.y, svl.z + h);
					dtVertex(svr.x, svr.y, svr.z + h);
					dtVertex(evr.x, evr.y, evr.z + h);
					dtVertex(evl.x, evl.y, evl.z + h);
				dtEnd();*/
				// Right.
				dtBegin(DT_POLYGON);
					dtVertex(svr.x, svr.y, svr.z + h);
					dtVertex(svr.x, svr.y, svr.z);
					dtVertex(evr.x, evr.y, evr.z);
					dtVertex(evr.x, evr.y, evr.z + h);
				dtEnd();
			} else {
				GfError("Shape not open %s, line %d\n", __FILE__, __LINE__);
			}

			// Close the end with a ploygon?
			if (n == NULL || n->style != TR_WALL ||
				(fabs(n->vertex[TR_SL].x - evl.x) > weps) ||
				(fabs(n->vertex[TR_SR].x - evr.x) > weps) ||
				(fabs(h - n->height) > weps))
			{
				if (close == true) {
					dtBegin(DT_POLYGON);
						dtVertex(svl.x, svl.y, svl.z);
						dtVertex(svr.x, svr.y, svr.z);
						dtVertex(svr.x, svr.y, svr.z + h);
						dtVertex(svl.x, svl.y, svl.z + h);
					dtEnd();

					dtEndComplexShape();
					close = false;
				} else {
					GfError("Shape not open %s, line %d\n", __FILE__, __LINE__);
				}
			}

		}

		current = current->next;

	} while (current != start);

}
Example #11
0
void grInitSound(tSituation* s, int ncars)
{
	const int BUFSIZE = 1024;
	char buf[BUFSIZE];

	GfOut("-- grInitSound\n");

	// Check if we want sound (sound.xml).
	const char *soundDisabledStr = GR_ATT_SOUND_STATE_DISABLED;
	const char *soundOpenALStr = GR_ATT_SOUND_STATE_OPENAL;
	const char *soundPlibStr = GR_ATT_SOUND_STATE_PLIB;
	snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), GR_SOUND_PARM_CFG);
	void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
	const char *optionName = GfParmGetStr(paramHandle, GR_SCT_SOUND, GR_ATT_SOUND_STATE, soundOpenALStr);
	float global_volume = GfParmGetNum(paramHandle, GR_SCT_SOUND, GR_ATT_SOUND_VOLUME, "%", 100.0f);
	if (!strcmp(optionName, soundDisabledStr)) {
		sound_mode = DISABLED;
	} else if (!strcmp(optionName, soundOpenALStr)) {
		sound_mode = OPENAL_MODE;
	} else if (!strcmp(optionName, soundPlibStr)) {
		sound_mode = PLIB_MODE;
	}
	//printf ("vol:%f\n", global_volume);
	GfParmReleaseHandle(paramHandle);
	paramHandle = NULL;

	lastUpdated = -1000.0;
	
	switch (sound_mode) {
	case OPENAL_MODE:
		try {
			sound_interface = new OpenalSoundInterface (44100, 32);
		} catch (const char* err) {
			GfError("Disabling Sound: OpenAL initialisation failed: %s\n", err ? err : "");
			sound_mode = DISABLED;
			return;
		}
		break;
	case PLIB_MODE:
		sound_interface = new PlibSoundInterface(44100, 32);
		break;
	case DISABLED:
		return;
	default:
		GfOut (" -- Unknown sound mode %d\n", sound_mode);
		exit(-1);
	}

	sound_interface->setGlobalGain(global_volume/100.0f);

	car_sound_data = new CarSoundData* [ncars];

	int i;
	for (i = 0; i<ncars; i++) {
		void* handle = s->cars[i]->_carHandle;
		tCarElt	*car = s->cars[i];
		const char* param;
        FILE *file = NULL;

		// ENGINE PARAMS
		tdble rpm_scale;
		param = GfParmGetStr(handle, "Sound", "engine sample", "engine-1.wav");
		rpm_scale = GfParmGetNum(handle, "Sound", "rpm scale", NULL, 1.0);
        snprintf (buf, BUFSIZE, "cars/%s/%s", car->_carName, param);
        file = fopen(buf, "r");
        if (!file)
        {
 		    snprintf (buf, BUFSIZE, "data/sound/%s", param);
        }
        else
        {
            fclose(file);
        }

		car_sound_data[car->index] = new CarSoundData (car->index, sound_interface);
		TorcsSound* engine_sound = sound_interface->addSample(buf, ACTIVE_VOLUME | ACTIVE_PITCH | ACTIVE_LP_FILTER, true, false);
		car_sound_data[i]->setEngineSound (engine_sound, rpm_scale);

		// TURBO PARAMS
		float default_turbo_rpm = 100.0f;//0.5f*car->_enginerpmMaxTq;
		bool turbo_on;
		param = GfParmGetStr(handle, SECT_ENGINE, PRM_TURBO, "false");
		if (!strcmp(param, "true")) {
			turbo_on = true;
		} else {
			if (strcmp(param, "false")) {
				fprintf (stderr, "expected true or false, found %s\n", param);
			}
			turbo_on = false;
		}
		
		float turbo_rpm = GfParmGetNum(handle, SECT_ENGINE, PRM_TURBO_RPM, NULL, default_turbo_rpm);
		float turbo_lag = GfParmGetNum(handle, SECT_ENGINE, PRM_TURBO_LAG, NULL, 1.0f);
		car_sound_data[i]->setTurboParameters (turbo_on, turbo_rpm, turbo_lag);
	}


	
	sound_interface->setSkidSound("data/sound/skid_tyres.wav");
	sound_interface->setRoadRideSound("data/sound/road-ride.wav");
	sound_interface->setGrassRideSound("data/sound/out_of_road.wav");
	sound_interface->setGrassSkidSound("data/sound/out_of_road-3.wav");
	sound_interface->setMetalSkidSound("data/sound/skid_metal.wav");
	sound_interface->setAxleSound("data/sound/axle.wav");
	sound_interface->setTurboSound("data/sound/turbo1.wav");
	sound_interface->setBackfireLoopSound("data/sound/backfire_loop.wav");

    for (i = 0; i < NB_CRASH_SOUND; i++) {
		snprintf(buf, BUFSIZE, "data/sound/crash%d.wav", i+1);
		sound_interface->setCrashSound(buf, i);
    }

	sound_interface->setBangSound("data/sound/boom.wav");
	sound_interface->setBottomCrashSound("data/sound/bottom_crash.wav");
	sound_interface->setBackfireSound("data/sound/backfire.wav");
	sound_interface->setGearChangeSound("data/sound/gear_change1.wav");

	sound_interface->setNCars(ncars);
    soundInitialized = 1;
	// Must happen after all static non-shared have been allocated. 
	sound_interface->initSharedSourcePool();
}
Example #12
0
static void parseFormStringStep1( tFormNode **node, const char *string )
{
	tFormNode *newNode;
	tFormNode *prevNode = NULL;
	int type = 0;
	int startPos = -1;
	int currentPos = 0;
	int stringLength = strlen( string );
	int xx;

	(*node) = NULL;

	while( currentPos < stringLength ) {
		if( startPos >= 0 ) {
			/* Check if block has ended */
			if( type == FORMNODE_TYPE_STRING && string[ currentPos ] == '#' ) {
				/* String ended here */
				newNode = (tFormNode*)malloc( sizeof( tFormNode ) );
				newNode->firstChild = NULL;
				newNode->next = NULL;
				newNode->type = FORMNODE_TYPE_STRING;
				newNode->number = 0.0f;
				newNode->string = (char*)malloc( sizeof( char ) * ( currentPos - startPos + 1 ) );
				newNode->func = NULL;

				for( xx = startPos; xx < currentPos; ++xx )
					newNode->string[ xx - startPos ] = string[ xx ];
				newNode->string[ currentPos - startPos ] = '\0';
				if( *node )
					prevNode->next = newNode;
				else
					(*node) = newNode;
				startPos = -1;
				prevNode = newNode;
			} else if( type == FORMNODE_TYPE_NUMBER && ( string[ currentPos ] < '0' || string[ currentPos ] > '9' )
			                                        && string[ currentPos ] != '.' ) {
				/* Number ended here */
				newNode = (tFormNode*)malloc( sizeof( tFormNode ) );
				newNode->firstChild = NULL;
				newNode->next = NULL;
				newNode->type = FORMNODE_TYPE_NUMBER;
				newNode->number = 0.0f;
				newNode->string = (char*)malloc( sizeof( char ) * ( currentPos - startPos + 1 ) );
				newNode->func = NULL;

				for( xx = startPos; xx < currentPos; ++xx )
					newNode->string[ xx - startPos ] = string[ xx ];
				newNode->string[ currentPos - startPos ] = '\0';
				newNode->number = (tdble)atof( newNode->string );
				FREEZ( newNode->string );

				if( *node )
					prevNode->next = newNode;
				else
					(*node) = newNode;
				prevNode = newNode;
				startPos = -1;
				--currentPos;
			} else if( type == FORMNODE_TYPE_TOPARSE_STRING &&
			           ( string[ currentPos ] < 'a' || string[ currentPos ] > 'z' ) &&
				   ( string[ currentPos ] < 'A' || string[ currentPos ] > 'Z' ) &&
				   ( string[ currentPos ] != '_' ) ) {
				/* Toparse String ended here */
				newNode = (tFormNode*)malloc( sizeof( tFormNode ) );
				newNode->firstChild = NULL;
				newNode->next = NULL;
				newNode->type = FORMNODE_TYPE_TOPARSE_STRING;
				newNode->number = 0.0f;
				newNode->string = (char*)malloc( sizeof( char ) * ( currentPos - startPos + 1 ) );
				newNode->func = NULL;

				for( xx = startPos; xx < currentPos; ++xx )
					newNode->string[ xx - startPos ] = string[ xx ];
				newNode->string[ currentPos - startPos ] = '\0';

				if( *node )
					prevNode->next = newNode;
				else
					(*node) = newNode;
				prevNode = newNode;
				startPos = -1;
				--currentPos;
			}
		} else {
			if( string[ currentPos ] == '#' ) {
				startPos = currentPos + 1;
				type = FORMNODE_TYPE_STRING;
			} else if( string[ currentPos ] >= '0' && string[ currentPos ] <= '9' ) {
				startPos = currentPos;
				type = FORMNODE_TYPE_NUMBER;
			} else if( ( string[ currentPos ] >= 'a' && string[ currentPos ] <= 'z' ) ||
			           ( string[ currentPos ] >= 'A' && string[ currentPos ] <= 'Z' ) ) {
				startPos = currentPos;
				type = FORMNODE_TYPE_TOPARSE_STRING;
			} else if( string[ currentPos ] == '(' || string[ currentPos ] == ')' || string[ currentPos ] == ',' ||
			           string[ currentPos ] == '+' || string[ currentPos ] == '-' || string[ currentPos ] == '*' || string[ currentPos ] == '/' ||
				   string[ currentPos ] == '\\' )
			{
				/* Extra token */
				newNode = (tFormNode*)malloc( sizeof( tFormNode ) );
				newNode->firstChild = NULL;
				newNode->next = NULL;
				newNode->type = FORMNODE_TYPE_TOPARSE_STRING;
				newNode->number = 0.0f;
				newNode->string = (char*)malloc( sizeof( char ) * 3 );
				newNode->func = NULL;

				if( ( string[ currentPos ] == '/' || string[ currentPos ] == '\\' ) &&
				    ( string[ currentPos + 1 ] == '/' || string[ currentPos + 1 ] == '\\' ) &&
				    string[ currentPos ] != string[ currentPos + 1 ] ) {
					newNode->string[ 0 ] = string[ currentPos ];
					newNode->string[ 1 ] = string[ currentPos + 1 ];
					newNode->string[ 2 ] = '\0';
					++currentPos;
				} else {
					newNode->string[ 0 ] = string[ currentPos ];
					newNode->string[ 1 ] = '\0';
				}

				if( *node )
					prevNode->next = newNode;
				else
					(*node) = newNode;
				prevNode = newNode;
			} else if( string[ currentPos ] != ' ' && string[ currentPos ] != '\n' && string[ currentPos ] != '\r' ) {
				GfError( "Formula parser: invalid token: \'%c\'\n", string[ currentPos ] );
			}
		}
		++currentPos;
	}
}
Example #13
0
OpenalSound::OpenalSound(const char* filename, OpenalSoundInterface* sitf,
						 int flags, bool loop, bool static_pool)
: Sound(flags, loop)
{
	this->static_pool = static_pool;
	poolindex = -1;
	itf = sitf;

	MAX_DISTANCE = 10000.0f;
	MAX_DISTANCE_LOW = 5.0f;
	REFERENCE_DISTANCE = 5.0f;
	ROLLOFF_FACTOR = 0.5f;

	int i;
	for (i = 0; i<3; i++) {
		source_position[i] = 0.0f;
		source_velocity[i] = 0.0f;
		zeroes[i] = 0.0f;
	}

	GfLogTrace("OpenAL : Creating %s source from %s\n",
			   static_pool ? "static" : "dynamic", filename);

	int error = alGetError();
	if (error != AL_NO_ERROR) {
		printf("Uncatched OpenAL Error on entry: %d with file %s\n", error, filename);
	}
	
	alGenBuffers (1, &buffer);
	error = alGetError();
	if (error != AL_NO_ERROR) {
		printf("OpenAL Error: %d, alGenBuffers failed %s\n", error, filename);
		is_enabled = false;
		return;
	}

	SDL_AudioSpec wavspec;
	Uint32 wavlen;
	Uint8 *wavbuf;
	if (!SDL_LoadWAV(filename, &wavspec, &wavbuf, &wavlen))
	{
		if (alIsBuffer(buffer))
			alDeleteBuffers(1, &buffer);
		GfError("OpenAL Error: Could not load %s (%s)\n", filename, SDL_GetError());
		is_enabled = false;
		return;
	}

	if (wavspec.channels > 1)
	{
		if (alIsBuffer(buffer))
			alDeleteBuffers(1, &buffer);
		GfError("OpenAL Error: Unsupported stereo sample %s\n", filename);
		is_enabled = false;
		return;
	}

	// Map WAV header to OpenAL format
	ALenum format;
	switch(wavspec.format)
	{
		case AUDIO_U8:
		case AUDIO_S8:
			format = AL_FORMAT_MONO8;
			break;
		case AUDIO_U16:
		case AUDIO_S16:
			format = AL_FORMAT_MONO16;
			break;
		default:
			SDL_FreeWAV(wavbuf);
			if (alIsBuffer(buffer))
				alDeleteBuffers(1, &buffer);
			GfError("OpenAL Error: Unsupported WAV format %d for %s (not among U8, S8, U16, S16)\n",
					wavspec.format, filename);
			is_enabled = false;
			return;
	}

	alBufferData(buffer, format, wavbuf, wavlen, wavspec.freq);
	error = alGetError();
	if (error != AL_NO_ERROR)
	{
		GfError("OpenAL Error: %d, alBufferData %s\n", error, filename);
		SDL_FreeWAV(wavbuf);
		if (alIsBuffer(buffer)) {
			alDeleteBuffers(1, &buffer);
			alGetError();
		}
		is_enabled = false;
		return;
	}
	
	SDL_FreeWAV(wavbuf);
	
	if (!static_pool) {
		is_enabled = true;
		return;
	}
	
	if (!sitf->getStaticSource(&source)) {
		is_enabled = false;
		printf("    No static sources left: %s\n", filename);
		if (alIsBuffer(buffer)) {
			alDeleteBuffers(1, &buffer);
			alGetError();
		}
		return;
	} else {
		is_enabled = true;	
	}

	alSourcefv (source, AL_POSITION, source_position);
	error = alGetError();
	if (error != AL_NO_ERROR) {
		printf("OpenAL Error: %d, alSourcefv AL_POSITION %s\n", error, filename);
	}

	alSourcefv (source, AL_VELOCITY, source_velocity);
	error = alGetError();
	if (error != AL_NO_ERROR) {
		printf("OpenAL Error: %d, alSourcefv AL_VELOCITY %s\n", error, filename);
	}

	alSourcei (source, AL_BUFFER, buffer);
	error = alGetError();
	if (error != AL_NO_ERROR) {
		printf("OpenAL Error: %d, alSourcei AL_BUFFER %s\n", error, filename);
	}

	alSourcei (source, AL_LOOPING, loop);
	if (error != AL_NO_ERROR) {
		printf("OpenAL Error: %d, alSourcei AL_LOOPING %s\n", error, filename);
	}

	alSourcef (source, AL_MAX_DISTANCE, MAX_DISTANCE);
	if (error != AL_NO_ERROR) {
		printf("OpenAL Error: %d, alSourcef AL_MAX_DISTANCE %s\n", error, filename);
	}

	alSourcef (source, AL_REFERENCE_DISTANCE, REFERENCE_DISTANCE);
	if (error != AL_NO_ERROR) {
		printf("OpenAL Error: %d, alSourcef AL_REFERENCE_DISTANCE %s\n", error, filename);
	}

	alSourcef (source, AL_ROLLOFF_FACTOR, ROLLOFF_FACTOR);
	if (error != AL_NO_ERROR) {
		printf("OpenAL Error: %d, alSourcef AL_ROLLOFF_FACTOR %s\n", error, filename);
	}

	alSourcef (source, AL_GAIN, 0.0f);
	if (error != AL_NO_ERROR) {
		printf("OpenAL Error: %d, alSourcef AL_GAIN %s\n", error, filename);
	}
}