⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 soundengine.cpp

📁 在iPhone OS上使用用Objective-C语言开发的Demo程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
				result = SetupQueue(fileInfo);					AssertNoError("Error setting up queue", fail);				result = SetupBuffers(fileInfo);					AssertNoError("Error setting up queue buffers", fail);								}			// if this is just part of the playlist, close the file for now			else			{				result = AudioFileClose(fileInfo->mAFID);					AssertNoError("Error closing file", fail);			}				return result;				fail:			if (fileInfo)				delete fileInfo;			return result;		}				OSStatus UpdateGain()		{			return SetVolume(mVolume);		}				OSStatus SetVolume(Float32 inVolume)		{			mVolume = inVolume;			return AudioQueueSetParameter(mQueue, kAudioQueueParam_Volume, mVolume * gMasterVolumeGain);		}				OSStatus Start()		{			OSStatus result = AudioQueuePrime(mQueue, 1, NULL);				if (result)			{				printf("Error priming queue");				return result;			}			return AudioQueueStart(mQueue, NULL);		}				OSStatus Stop(Boolean inStopAtEnd)		{			if (inStopAtEnd)			{				mStopAtEnd = true;				return noErr;			}			else				return AudioQueueStop(mQueue, true);		}		private:		AudioQueueRef						mQueue;		AudioQueueBufferRef					mBuffers[kNumberBuffers];		UInt32								mBufferByteSize;		SInt64								mCurrentPacket;		UInt32								mNumPacketsToRead;		Float32								mVolume;		AudioStreamPacketDescription *		mPacketDescs;		std::vector<BG_FileInfo*>			mBGFileInfo;		UInt32								mCurrentFileIndex;		Boolean								mMakeNewQueueWhenStopped;		Boolean								mStopAtEnd;		std::vector<AudioQueueBufferRef>	mBuffersToDispose;};#pragma mark ***** SoundEngineEffect *****//==================================================================================================//	SoundEngineEffect class//==================================================================================================class SoundEngineEffect{	public:			// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		SoundEngineEffect(const char* inLoopPath, const char* inAttackPath, const char* inDecayPath, Boolean inDoLoop) 			:	mSourceID(0),				mAttackBufferID(0),				mLoopBufferID(0),				mDecayBufferID(0),				mLoopPath(inLoopPath),				mAttackPath(inAttackPath),				mDecayPath(inDecayPath),				mLoopData(NULL),				mAttackData(NULL),				mDecayData(NULL),				mLoopDataSize(0),				mAttackDataSize(0),				mDecayDataSize(0),				mIsLoopingEffect(inDoLoop),				mPlayThread(NULL),				mPlayThreadState(kPlayThreadState_Loop) { alGenSources(1, &mSourceID); }				~SoundEngineEffect()		{			alDeleteSources(1, &mSourceID);						if (mLoopData)				free(mLoopData);			if (mAttackData)				free(mAttackData);			if (mDecayData)				free(mDecayData);		}				// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		// Accessors		// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		UInt32	GetEffectID() { return mSourceID; }		UInt32	GetPlayThreadState() { return mPlayThreadState; }		Boolean	HasAttackBuffer() { return mAttackBufferID != 0; }		// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		// Helper Functions		// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		ALenum GetALFormat(AudioStreamBasicDescription inFileFormat)		{			if (inFileFormat.mFormatID != kAudioFormatLinearPCM)				return kSoundEngineErrInvalidFileFormat;							if ((inFileFormat.mChannelsPerFrame > 2) || (inFileFormat.mChannelsPerFrame < 1))				return kSoundEngineErrInvalidFileFormat;						if(inFileFormat.mBitsPerChannel == 8)				return (inFileFormat.mChannelsPerFrame == 1) ? AL_FORMAT_MONO8 : AL_FORMAT_STEREO8;			else if(inFileFormat.mBitsPerChannel == 16)				return (inFileFormat.mChannelsPerFrame == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;			return kSoundEngineErrInvalidFileFormat;		}		OSStatus LoadFileData(const char *inFilePath, void* &outData, UInt32 &outDataSize, ALuint &outBufferID)		{			AudioFileID theAFID = 0;			OSStatus result = noErr;			UInt64 theFileSize = 0;			AudioStreamBasicDescription theFileFormat;						result = LoadFileDataInfo(inFilePath, theAFID, theFileFormat, theFileSize);			outDataSize = (UInt32)theFileSize;				AssertNoError("Error loading file info", fail)			outData = malloc(outDataSize);			result = AudioFileReadBytes(theAFID, false, 0, &outDataSize, outData);				AssertNoError("Error reading file data", fail)							if (!TestAudioFormatNativeEndian(theFileFormat) && (theFileFormat.mBitsPerChannel > 8)) 				return kSoundEngineErrInvalidFileFormat;					alGenBuffers(1, &outBufferID);				AssertNoOALError("Error generating buffer\n", fail);						alBufferDataStaticProc(outBufferID, GetALFormat(theFileFormat), outData, outDataSize, theFileFormat.mSampleRate);				AssertNoOALError("Error attaching data to buffer\n", fail);			AudioFileClose(theAFID);			return result;					fail:						if (theAFID)				AudioFileClose(theAFID);			if (outData)			{				free(outData);				outData = NULL;			}			return result;		}				OSStatus AttachFilesToSource()		{			OSStatus result = AL_NO_ERROR;						// first check for the attack file. That will be first in the queue if present			if (mAttackPath)			{				result = LoadFileData(mAttackPath, mAttackData, mAttackDataSize, mAttackBufferID);					AssertNoError("Error loading attack file info", end)			}						result = LoadFileData(mLoopPath, mLoopData, mLoopDataSize, mLoopBufferID);				AssertNoError("Error loading looping file info", end)						// if one-shot effect, attach the buffer to the source now			if (!mIsLoopingEffect)			{				alSourcei(mSourceID, AL_BUFFER, mLoopBufferID);					AssertNoOALError("Error attaching file data to effect", end)			}			if (mDecayPath)			{				result = LoadFileData(mDecayPath, mDecayData, mDecayDataSize, mDecayBufferID);					AssertNoError("Error loading decay file info", end)			}		end:			return result;		}				OSStatus ClearSourceBuffers()		{			OSStatus result = AL_NO_ERROR;			ALint numQueuedBuffers = 0;			ALuint *bufferIDs = (ALuint*)malloc(numQueuedBuffers * sizeof(ALint));			alGetSourcei(mSourceID, AL_BUFFERS_QUEUED, &numQueuedBuffers);				AssertNoOALError("Error getting OpenAL queued buffer size", end)							alSourceUnqueueBuffers(mSourceID, numQueuedBuffers, bufferIDs);				AssertNoOALError("Error unqueueing buffers from source", end)						end:			free(bufferIDs);			return result;		}		static void* PlaybackProc(void *args)		{			OSStatus result = AL_NO_ERROR;			SoundEngineEffect *THIS = (SoundEngineEffect*)args;															alSourcePlay(THIS->GetEffectID());				AssertNoOALError("Error starting effect playback", end)						// if attack buffer is present, wait until it has completed, then turn looping on			if (THIS->HasAttackBuffer())			{				ALint numBuffersProcessed = 0;										while (numBuffersProcessed < 1)				{					alGetSourcei(THIS->GetEffectID(), AL_BUFFERS_PROCESSED, &numBuffersProcessed);						AssertNoOALError("Error getting processed buffer number", end)				}								ALuint tmpBuffer = 0;				alSourceUnqueueBuffers(THIS->GetEffectID(), 1, &tmpBuffer);					AssertNoOALError("Error unqueueing buffers from source", end)			}				// now that we have processed the attack buffer, loop the main one			THIS->SetLooping(true);		end:				return NULL;		}						// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		// Effect management		// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		OSStatus Start()		{			OSStatus result = AL_NO_ERROR;							alSourceStop(mSourceID);				AssertNoOALError("Error stopping source", end)			if (!mIsLoopingEffect)			{				// if we are just playing one-short effects, start playback here				alSourcePlay(mSourceID);				return alGetError();			}			// for loops we need to spawn a new thread								mPlayThread = new OpenALThread(PlaybackProc, (void*)this);			// we want this to delete upon thread completion			mPlayThreadState = kPlayThreadState_Loop;			// clean up remnants from any previous playback of the source			result = ClearSourceBuffers();				AssertNoError("Error clearing buffers", end)						// if the effect has an attack sample, queue this first			if (HasAttackBuffer())			{				alSourceQueueBuffers(mSourceID, 1, &mAttackBufferID);					AssertNoOALError("Error queueing buffers for attack", end)				// turn on looping after the attack buffer has been processed				SetLooping(false);			}			alSourceQueueBuffers(mSourceID, 1, &mLoopBufferID);				AssertNoOALError("Error queueing looping buffer", end)			mPlayThread->Start();		end:						return result;		}				OSStatus StartDecay()		{			// turn off looping, and queue the decay buffer			OSStatus result = AL_NO_ERROR;			alSourcei(mSourceID, AL_LOOPING, 0);				AssertNoOALError("Error turning off looping", end)			alSourceQueueBuffers(mSourceID, 1, &mDecayBufferID);				AssertNoOALError("Error queueing decay file", end)		end:			return result;		}				OSStatus Stop(Boolean inDoDecay)		{			OSStatus result = AL_NO_ERROR;			// for non looped effects and loops with no decay sample			if ((mDecayBufferID == 0) || !inDoDecay)			{				// if no decay to play, just stop the source				alSourceStop(mSourceID);					AssertNoOALError("Error stopping source", end)			}			else				return StartDecay();		end:			return result;		}		OSStatus SetPitch(Float32 inValue)		{			alSourcef(mSourceID, AL_PITCH, inValue);			return alGetError();		}						OSStatus SetLooping(Boolean inDoLoop)		{			ALint doLoop = inDoLoop ? 1 : 0;			alSourcei(mSourceID, AL_LOOPING, doLoop);			return alGetError();		}				OSStatus SetPosition(Float32 inX, Float32 inY, Float32 inZ)		{			alSource3f(mSourceID, AL_POSITION, inX, inY, inZ);			return alGetError();		}		OSStatus SetMaxDistance(Float32 inValue)		{			alSourcef(mSourceID, AL_MAX_DISTANCE, inValue);			return alGetError();		}		OSStatus SetReferenceDistance(Float32 inValue)		{			alSourcef(mSourceID, AL_REFERENCE_DISTANCE, inValue);			return alGetError();		}				OSStatus SetLevel(Float32 inValue)		{			alSourcef(mSourceID, AL_GAIN, inValue * gMasterVolumeGain);			return alGetError();		}				enum {			kPlayThreadState_Loop	= 0,			kPlayThreadState_Decay	= 1,			kPlayThreadState_End	= 2		};			private:		ALuint					mSourceID;		ALuint					mAttackBufferID;		ALuint					mLoopBufferID;		ALuint					mDecayBufferID;				UInt32					mNumberBuffers;		const char*				mLoopPath;		const char*				mAttackPath;		const char*				mDecayPath;		void*					mLoopData;		void*					mAttackData;		void*					mDecayData;		UInt32					mLoopDataSize;		UInt32					mAttackDataSize;		UInt32					mDecayDataSize;		Boolean					mIsLoopingEffect;		OpenALThread*			mPlayThread;		UInt32					mPlayThreadState;};#pragma mark ***** SoundEngineEffectMap *****//==================================================================================================//	SoundEngineEffectMap class//==================================================================================================class SoundEngineEffectMap 	: std::multimap<UInt32, SoundEngineEffect*, std::less<ALuint> > {	public:    // add a new context to the map    void Add (const	ALuint	inEffectToken, SoundEngineEffect **inEffect)	{		iterator	it = upper_bound(inEffectToken);		insert(it, value_type (inEffectToken, *inEffect));	}    SoundEngineEffect* Get(ALuint	inEffectToken) 	{        iterator	it = find(inEffectToken);        if (it != end())            return ((*it).second);		return (NULL);    }    void Remove (const	ALuint	inSourceToken) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -