//----------------------------------------------------------------------------- // Torque Game Engine // Copyright (C) GarageGames.com, Inc. //----------------------------------------------------------------------------- #include "platform/platform.h" #include "platform/platformAudio.h" #include "console/simBase.h" #include "audio/audioDataBlock.h" extern ALuint alxGetWaveLen(ALuint buffer); extern F32 mAudioTypeVolume[Audio::NumAudioTypes]; //-------------------------------------------------------------------------- // Expose all al get/set methods... //-------------------------------------------------------------------------- enum AL_GetSetBits{ Source = BIT(0), Listener = BIT(1), Context = BIT(2), Environment = BIT(3), Get = BIT(4), Set = BIT(5), Int = BIT(6), Float = BIT(7), Float3 = BIT(8), Float6 = BIT(9) }; static ALenum getEnum(const char * name, U32 flags) { AssertFatal(name, "Audio getEnum: bad param"); static struct { char * mName; ALenum mAlenum; U32 mFlags; } table[] = { //----------------------------------------------------------------------------------------------------------------- // "name" ENUM Flags //----------------------------------------------------------------------------------------------------------------- { "AL_GAIN", AL_GAIN, (Source|Listener|Get|Set|Float) }, { "AL_GAIN_LINEAR", AL_GAIN_LINEAR, (Source|Listener|Get|Set|Float) }, { "AL_PITCH", AL_PITCH, (Source|Get|Set|Float) }, { "AL_REFERENCE_DISTANCE", AL_REFERENCE_DISTANCE, (Source|Get|Set|Float) }, { "AL_MAX_DISTANCE", AL_MAX_DISTANCE, (Source|Get|Set|Float) }, { "AL_CONE_OUTER_GAIN", AL_CONE_OUTER_GAIN, (Source|Get|Set|Float) }, { "AL_POSITION", AL_POSITION, (Source|Listener|Get|Set|Float3) }, { "AL_DIRECTION", AL_DIRECTION, (Source|Get|Set|Float3) }, { "AL_VELOCITY", AL_VELOCITY, (Source|Listener|Get|Set|Float3) }, { "AL_ORIENTATION", AL_ORIENTATION, (Listener|Set|Float6) }, { "AL_CONE_INNER_ANGLE", AL_CONE_INNER_ANGLE, (Source|Get|Set|Int) }, { "AL_CONE_OUTER_ANGLE", AL_CONE_OUTER_ANGLE, (Source|Get|Set|Int) }, { "AL_LOOPING", AL_LOOPING, (Source|Get|Set|Int) }, //{ "AL_STREAMING", AL_STREAMING, (Source|Get|Set|Int) }, //{ "AL_BUFFER", AL_BUFFER, (Source|Get|Set|Int) }, { "AL_VENDOR", AL_VENDOR, (Context|Get) }, { "AL_VERSION", AL_VERSION, (Context|Get) }, { "AL_RENDERER", AL_RENDERER, (Context|Get) }, { "AL_EXTENSIONS", AL_EXTENSIONS, (Context|Get) }, /* // environment { "AL_ENV_ROOM_IASIG", AL_ENV_ROOM_IASIG, (Environment|Get|Set|Int) }, { "AL_ENV_ROOM_HIGH_FREQUENCY_IASIG", AL_ENV_ROOM_HIGH_FREQUENCY_IASIG, (Environment|Get|Set|Int) }, { "AL_ENV_REFLECTIONS_IASIG", AL_ENV_REFLECTIONS_IASIG, (Environment|Get|Set|Int) }, { "AL_ENV_REVERB_IASIG", AL_ENV_REVERB_IASIG, (Environment|Get|Set|Int) }, { "AL_ENV_ROOM_ROLLOFF_FACTOR_IASIG", AL_ENV_ROOM_ROLLOFF_FACTOR_IASIG, (Environment|Get|Set|Float) }, { "AL_ENV_DECAY_TIME_IASIG", AL_ENV_DECAY_TIME_IASIG, (Environment|Get|Set|Float) }, { "AL_ENV_DECAY_HIGH_FREQUENCY_RATIO_IASIG", AL_ENV_DECAY_HIGH_FREQUENCY_RATIO_IASIG, (Environment|Get|Set|Float) }, { "AL_ENV_REFLECTIONS_DELAY_IASIG", AL_ENV_REFLECTIONS_DELAY_IASIG, (Environment|Get|Set|Float) }, { "AL_ENV_REVERB_DELAY_IASIG", AL_ENV_REVERB_DELAY_IASIG, (Environment|Get|Set|Float) }, { "AL_ENV_DIFFUSION_IASIG", AL_ENV_DIFFUSION_IASIG, (Environment|Get|Set|Float) }, { "AL_ENV_DENSITY_IASIG", AL_ENV_DENSITY_IASIG, (Environment|Get|Set|Float) }, { "AL_ENV_HIGH_FREQUENCY_REFERENCE_IASIG", AL_ENV_HIGH_FREQUENCY_REFERENCE_IASIG, (Environment|Get|Set|Float) }, { "AL_ENV_ROOM_VOLUME_EXT", AL_ENV_ROOM_VOLUME_EXT, (Environment|Get|Set|Int) }, { "AL_ENV_FLAGS_EXT", AL_ENV_FLAGS_EXT, (Environment|Get|Set|Int) }, { "AL_ENV_EFFECT_VOLUME_EXT", AL_ENV_EFFECT_VOLUME_EXT, (Environment|Get|Set|Float) }, { "AL_ENV_DAMPING_EXT", AL_ENV_DAMPING_EXT, (Environment|Get|Set|Float) }, { "AL_ENV_ENVIRONMENT_SIZE_EXT", AL_ENV_ENVIRONMENT_SIZE_EXT, (Environment|Get|Set|Float) }, // sample environment { "AL_ENV_SAMPLE_DIRECT_EXT", AL_ENV_SAMPLE_DIRECT_EXT, (Source|Get|Set|Int) }, { "AL_ENV_SAMPLE_DIRECT_HF_EXT", AL_ENV_SAMPLE_DIRECT_HF_EXT, (Source|Get|Set|Int) }, { "AL_ENV_SAMPLE_ROOM_EXT", AL_ENV_SAMPLE_ROOM_EXT, (Source|Get|Set|Int) }, { "AL_ENV_SAMPLE_ROOM_HF_EXT", AL_ENV_SAMPLE_ROOM_HF_EXT, (Source|Get|Set|Int) }, { "AL_ENV_SAMPLE_OUTSIDE_VOLUME_HF_EXT", AL_ENV_SAMPLE_OUTSIDE_VOLUME_HF_EXT, (Source|Get|Set|Int) }, { "AL_ENV_SAMPLE_FLAGS_EXT", AL_ENV_SAMPLE_FLAGS_EXT, (Source|Get|Set|Int) }, { "AL_ENV_SAMPLE_REVERB_MIX_EXT", AL_ENV_SAMPLE_REVERB_MIX_EXT, (Source|Get|Set|Float) }, { "AL_ENV_SAMPLE_OBSTRUCTION_EXT", AL_ENV_SAMPLE_OBSTRUCTION_EXT, (Source|Get|Set|Float) }, { "AL_ENV_SAMPLE_OBSTRUCTION_LF_RATIO_EXT", AL_ENV_SAMPLE_OBSTRUCTION_LF_RATIO_EXT, (Source|Get|Set|Float) }, { "AL_ENV_SAMPLE_OCCLUSION_EXT", AL_ENV_SAMPLE_OCCLUSION_EXT, (Source|Get|Set|Float) }, { "AL_ENV_SAMPLE_OCCLUSION_LF_RATIO_EXT", AL_ENV_SAMPLE_OCCLUSION_LF_RATIO_EXT, (Source|Get|Set|Float) }, { "AL_ENV_SAMPLE_OCCLUSION_ROOM_RATIO_EXT", AL_ENV_SAMPLE_OCCLUSION_ROOM_RATIO_EXT, (Source|Get|Set|Float) }, { "AL_ENV_SAMPLE_ROOM_ROLLOFF_EXT", AL_ENV_SAMPLE_ROOM_ROLLOFF_EXT, (Source|Get|Set|Float) }, { "AL_ENV_SAMPLE_AIR_ABSORPTION_EXT", AL_ENV_SAMPLE_AIR_ABSORPTION_EXT, (Source|Get|Set|Float) }, */ }; for(U32 i = 0; i < (sizeof(table) / sizeof(table[0])); i++) { if((table[i].mFlags & flags) != flags) continue; if(dStricmp(table[i].mName, name) == 0) return(table[i].mAlenum); } return(AL_INVALID); } //----------------------------------------------- ConsoleFunctionGroupBegin(Audio, "Functions dealing with the OpenAL audio layer.\n\n" "@see www.OpenAL.org for what these functions do. Variances from posted" " behaviour is described below."); ConsoleFunction(OpenALInitDriver, bool, 1, 1, "Initializes the OpenAL driver.\n\n" "@note You must call this before any sounds will work!") { if (Audio::OpenALInit()) { static bool registered = false; if (!registered) { ResourceManager->registerExtension(".wav", AudioBuffer::construct); ResourceManager->registerExtension(".ogg", AudioBuffer::construct); } registered = true; return true; } return false; } //----------------------------------------------- ConsoleFunction(OpenALShutdownDriver, void, 1, 1, "OpenALShutdownDriver()") { Audio::OpenALShutdown(); } //----------------------------------------------- ConsoleFunction(OpenALRegisterExtensions, void, 1, 1, "OpenALRegisterExtensions()") { } //----------------------------------------------- ConsoleFunction(alGetString, const char *, 2, 2, "(string item)\n\n" "This wraps alGetString().") { argc; ALenum e = getEnum(argv[1], (Context|Get)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "alGetString: invalid enum name '%s'", argv[1]); return ""; } return (const char*)alGetString(e); } //-------------------------------------------------------------------------- // Soundfile //-------------------------------------------------------------------------- ConsoleFunction(alxGetWaveLen, S32, 2, 2, "(string filename)\n\n" "@param filename File to determine length of.\n" "@returns Length in milliseconds.") { Resource buffer = AudioBuffer::find(argv[1]); if (bool(buffer)) { ALuint alBuffer = buffer->getALBuffer(); return alxGetWaveLen(alBuffer); } else { return 0; } } //-------------------------------------------------------------------------- // Source //-------------------------------------------------------------------------- ConsoleFunction(alxCreateSource, S32, 2, 6, "(profile) or " "(profile, x,y,z) or " "(description, filename) or " "(description, filename, x,y,z)") { AudioDescription *description = NULL; AudioProfile *profile = dynamic_cast( Sim::findObject( argv[1] ) ); if (profile == NULL) { description = dynamic_cast( Sim::findObject( argv[1] ) ); if (description == NULL) { Con::printf("Unable to locate audio profile/description '%s'", argv[1]); return NULL_AUDIOHANDLE; } } if (profile) { if (argc == 2) return alxCreateSource(profile); MatrixF transform; transform.set(EulerF(0,0,0), Point3F( dAtof(argv[2]),dAtof(argv[3]),dAtof(argv[4]) )); return alxCreateSource(profile, &transform); } if (description) { if (argc == 3) return alxCreateSource(description, argv[2]); MatrixF transform; transform.set(EulerF(0,0,0), Point3F( dAtof(argv[3]),dAtof(argv[4]),dAtof(argv[5]) )); return alxCreateSource(description, argv[2], &transform); } return NULL_AUDIOHANDLE; } //----------------------------------------------- ConsoleFunction(alxSourcef, void, 4, 4, "(handle, ALenum, value)") { ALenum e = getEnum(argv[2], (Source|Set|Float)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "cAudio_alxSourcef: invalid enum name '%s'", argv[2]); return; } alxSourcef(dAtoi(argv[1]), e, dAtof(argv[3])); } //----------------------------------------------- ConsoleFunction(alxSource3f, void, 3, 6, "(handle, ALenum, x, y, z)\n\n" "@note You can replace the last three parameters with a string, " "\"x y z\"") { ALenum e = getEnum(argv[2], (Source|Set|Float3)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "cAudio_alxSource3f: invalid enum name '%s'", argv[2]); return; } if((argc != 4 && argc != 6)) { Con::errorf(ConsoleLogEntry::General, "cAudio_alxSource3f: wrong number of args"); return; } Point3F pos; if(argc == 4) dSscanf(argv[3], "%g %g %g", &pos.x, &pos.y, &pos.z); else { pos.x = dAtof(argv[3]); pos.y = dAtof(argv[4]); pos.z = dAtof(argv[5]); } alxSource3f(dAtoi(argv[1]), e, pos.x, pos.y, pos.z); } //----------------------------------------------- ConsoleFunction(alxSourcei, void, 4, 4, "(handle, ALenum, value)") { ALenum e = getEnum(argv[2], (Source|Set|Int)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "cAudio_alxSourcei: invalid enum name '%s'", argv[2]); return; } alxSourcei(dAtoi(argv[1]), e, dAtoi(argv[3])); } //----------------------------------------------- ConsoleFunction(alxGetSourcef, F32, 3, 3, "(handle, ALenum)") { ALenum e = getEnum(argv[2], (Source|Get|Float)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "cAudio_alxGetSourcef: invalid enum name '%s'", argv[2]); return(0.f); } F32 value; alxGetSourcef(dAtoi(argv[1]), e, &value); return(value); } //----------------------------------------------- ConsoleFunction(alxGetSource3f, const char *, 3, 3, "(handle, ALenum)" ) { ALenum e = getEnum(argv[2], (Source|Get|Float)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "cAudio_alxGetSource3f: invalid enum name '%s'", argv[2]); return("0 0 0"); } F32 value1, value2, value3; alxGetSource3f(dAtoi(argv[1]), e, &value1, &value2, &value3); char * ret = Con::getReturnBuffer(64); dSprintf(ret, 64, "%7.3f %7.3 %7.3", value1, value2, value3); return(ret); } //----------------------------------------------- ConsoleFunction(alxGetSourcei, S32, 3, 3, "(handle, ALenum)") { ALenum e = getEnum(argv[2], (Source|Get|Int)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "cAudio_alxGetSourcei: invalid enum name '%s'", argv[2]); return(0); } S32 value; alxGetSourcei(dAtoi(argv[1]), e, &value); return(value); } //----------------------------------------------- ConsoleFunction(alxPlay, S32, 2, 5, "alxPlay(handle) or " "alxPlay(profile) or " "alxPlay(profile, x,y,z)") { if (argc == 2) { AUDIOHANDLE handle = dAtoi(argv[1]); if (handle != 0) return alxPlay(handle); } AudioProfile *profile = dynamic_cast( Sim::findObject( argv[1] ) ); if (profile == NULL) { Con::printf("Unable to locate audio profile '%s'", argv[1]); return NULL_AUDIOHANDLE; } Point3F pos(0.f, 0.f, 0.f); if(argc == 3) dSscanf(argv[2], "%g %g %g", &pos.x, &pos.y, &pos.z); else if(argc == 5) pos.set(dAtof(argv[2]), dAtof(argv[3]), dAtof(argv[4])); MatrixF transform; transform.set(EulerF(0,0,0), pos); return alxPlay(profile, &transform, NULL); } //----------------------------------------------- ConsoleFunction(alxStop, void, 2, 2, "(int handle)") { AUDIOHANDLE handle = dAtoi(argv[1]); if(handle == NULL_AUDIOHANDLE) return; alxStop(handle); } //----------------------------------------------- ConsoleFunction(alxStopAll, void, 1, 1, "()") { alxStopAll(); } //----------------------------------------------- ConsoleFunction(alxIsPlaying, bool, 2, 5, "alxIsPlaying(handle)") { AUDIOHANDLE handle = dAtoi(argv[1]); if(handle == NULL_AUDIOHANDLE) return false; return alxIsPlaying(handle); } //-------------------------------------------------------------------------- // Listener //-------------------------------------------------------------------------- ConsoleFunction(alxListenerf, void, 3, 3, "alxListener(ALenum, value)") { ALenum e = getEnum(argv[1], (Listener|Set|Float)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "alxListenerf: invalid enum name '%s'", argv[1]); return; } alxListenerf(e, dAtof(argv[2])); } //----------------------------------------------- ConsoleFunction(alListener3f, void, 3, 5, "alListener3f(ALenum, \"x y z\") or " "alListener3f(ALenum, x, y, z)") { ALenum e = getEnum(argv[1], (Listener|Set|Float3)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "alListener3f: invalid enum name '%s'", argv[1]); return; } if(argc != 3 || argc != 5) { Con::errorf(ConsoleLogEntry::General, "alListener3f: wrong number of arguments"); return; } Point3F pos; if(argc == 3) dSscanf(argv[2], "%g %g %g", &pos.x, &pos.y, &pos.z); else { pos.x = dAtof(argv[2]); pos.y = dAtof(argv[3]); pos.z = dAtof(argv[4]); } alListener3f(e, pos.x, pos.y, pos.z); } //----------------------------------------------- ConsoleFunction(alxGetListenerf, F32, 2, 2, "alxGetListenerf(Alenum)") { ALenum e = getEnum(argv[1], (Source|Get|Float)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "alxGetListenerf: invalid enum name '%s'", argv[1]); return(0.f); } F32 value; alxGetListenerf(e, &value); return(value); } //----------------------------------------------- ConsoleFunction(alGetListener3f, const char *, 2, 2, "alGetListener3f(Alenum)") { ALenum e = getEnum(argv[2], (Source|Get|Float)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "alGetListener3f: invalid enum name '%s'", argv[1]); return("0 0 0"); } F32 value1, value2, value3; alGetListener3f(e, &value1, &value2, &value3); char * ret = Con::getReturnBuffer(64); dSprintf(ret, 64, "%7.3f %7.3 %7.3", value1, value2, value3); return(ret); } //----------------------------------------------- ConsoleFunction(alGetListeneri, S32, 2, 2, "alGetListeneri(Alenum)") { ALenum e = getEnum(argv[1], (Source|Get|Int)); if(e == AL_INVALID) { Con::errorf(ConsoleLogEntry::General, "alGetListeneri: invalid enum name '%s'", argv[1]); return(0); } S32 value; alGetListeneri(e, &value); return(value); } //-------------------------------------------------------------------------- // Channel Volumes //-------------------------------------------------------------------------- ConsoleFunction(alxGetChannelVolume, F32, 2, 2, "(int channel_id)\n\n" "@param channel_id ID of channel to fetch volume from.\n" "@return Volume of channel.") { U32 type = dAtoi(argv[1]); if(type >= Audio::NumAudioTypes) { Con::errorf(ConsoleLogEntry::General, "alxGetChannelVolume: invalid channel '%d'", dAtoi(argv[1])); return(0.f); } return(mAudioTypeVolume[type]); } //----------------------------------------------- ConsoleFunction(alxSetChannelVolume, bool, 3, 3, "(int channel_id, float volume)\n\n" "@param channel_id ID of channel to set volume on.\n" "@param volume New volume of channel, from 0.0f-1.0f" ) { U32 type = dAtoi(argv[1]); F32 volume = mClampF(dAtof(argv[2]), 0.f, 1.f); if(type >= Audio::NumAudioTypes) { Con::errorf(ConsoleLogEntry::General, "alxSetChannelVolume: channel '%d' out of range [0, %d]", dAtoi(argv[1]), Audio::NumAudioTypes); return false; } mAudioTypeVolume[type] = volume; alxUpdateTypeGain(type); return true; } //----------------------------------------------- ConsoleFunction(alxGetStreamPosition, F32, 2, 2, "alxGetStreamPosition(handle)" ) { AUDIOHANDLE handle = dAtoi(argv[1]); if(handle == NULL_AUDIOHANDLE) return -1; return alxGetStreamPosition( handle ); } //----------------------------------------------- ConsoleFunction(alxGetStreamDuration, F32, 2, 2, "alxGetStreamDuration(handle)" ) { AUDIOHANDLE handle = dAtoi(argv[1]); if(handle == NULL_AUDIOHANDLE) return -1; return alxGetStreamDuration( handle ); } ConsoleFunctionGroupEnd(Audio);