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

📄 sdl_epocaudio.cpp

📁 SDL库 在进行视频显示程序spcaview安装时必须的库文件
💻 CPP
字号:
/*    SDL - Simple DirectMedia Layer    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Library General Public License for more details.    You should have received a copy of the GNU Library General Public    License along with this library; if not, write to the Free    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    Sam Lantinga    slouken@devolution.com*//*    SDL_epocaudio.cpp    Epoc based SDL audio driver implementation        Markus Mertama*/#ifdef SAVE_RCSIDstatic char rcsid = "@(#) $Id: SDL_epocaudio.c,v 0.0.0.0 2001/06/19 17:19:56 hercules Exp $";#endif#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <signal.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/stat.h>#include "epoc_sdl.h"#include <e32hal.h>extern "C" {#include "SDL_audio.h"#include "SDL_error.h"#include "SDL_audiomem.h"#include "SDL_audio_c.h"#include "SDL_timer.h"#include "SDL_audiodev_c.h"}#include "SDL_epocaudio.h"#include "streamplayer.h"//#define DEBUG_AUDIO/* Audio driver functions */static int EPOC_OpenAudio(SDL_AudioDevice *thisdevice, SDL_AudioSpec *spec);static void EPOC_WaitAudio(SDL_AudioDevice *thisdevice);static void EPOC_PlayAudio(SDL_AudioDevice *thisdevice);static Uint8 *EPOC_GetAudioBuf(SDL_AudioDevice *thisdevice);static void EPOC_CloseAudio(SDL_AudioDevice *thisdevice);static void EPOC_ThreadInit(SDL_AudioDevice *thisdevice);static int Audio_Available(void);static SDL_AudioDevice *Audio_CreateDevice(int devindex);static void Audio_DeleteDevice(SDL_AudioDevice *device);//void sos_adump(SDL_AudioDevice* thisdevice, void* data, int len);#ifdef __WINS__#define DODUMP#endif#ifdef DODUMPNONSHARABLE_CLASS(TDump)	{	public:	TInt Open();	void Close();	void Dump(const TDesC8& aDes);	private:		RFile iFile;    	RFs iFs; 	};	TInt TDump::Open()	{	TInt err = iFs.Connect();	if(err == KErrNone)		{#ifdef __WINS___LIT(target, "C:\\sdlau.raw");#else_LIT(target, "E:\\sdlau.raw");#endif 		err = iFile.Replace(iFs, target, EFileWrite);		}	return err;	}void TDump::Close()	{	iFile.Close();	iFs.Close();	}void TDump::Dump(const TDesC8& aDes)	{	iFile.Write(aDes);	}#endifNONSHARABLE_CLASS(CSimpleWait) : public CTimer	{	public:		void Wait(TTimeIntervalMicroSeconds32 aWait);		static CSimpleWait* NewL();	private:		CSimpleWait();		void RunL();	};CSimpleWait* CSimpleWait::NewL()	{	CSimpleWait* wait = new (ELeave) CSimpleWait();	CleanupStack::PushL(wait);	wait->ConstructL();	CleanupStack::Pop();	return wait;	}void CSimpleWait::Wait(TTimeIntervalMicroSeconds32 aWait)	{	After(aWait);	CActiveScheduler::Start();	}	CSimpleWait::CSimpleWait() : CTimer(CActive::EPriorityStandard)		{	CActiveScheduler::Add(this);	}void CSimpleWait::RunL()	{	CActiveScheduler::Stop();	}const TInt KAudioBuffers(2);	NONSHARABLE_CLASS(CEpocAudio) : public CBase, public MStreamObs, public MStreamProvider    {    public:    	static void* NewL(TInt BufferSize, TInt aFill);    	inline static CEpocAudio& Current(SDL_AudioDevice* thisdevice);    	    	static void Free(SDL_AudioDevice* thisdevice); 		    	void Wait();    	void Play();    //	void SetBuffer(const TDesC8& aBuffer);    	void ThreadInitL(TAny* aDevice);    	void Open(TInt iRate, TInt iChannels, TUint32 aType, TInt aBytes);    	~CEpocAudio();    	TUint8* Buffer();    	TBool SetPause(TBool aPause);    #ifdef DODUMP    	void Dump(const TDesC8& aBuf) {iDump.Dump(aBuf);}    #endif    private:    	CEpocAudio(TInt aBufferSize);    	void Complete(TInt aState, TInt aError);    	TPtrC8 Data();    	void ConstructL(TInt aFill);    private:    	TInt iBufferSize;    	CStreamPlayer* iPlayer;    	TInt iBufferRate;    	TInt iRate;    	TInt iChannels;    	TUint32 iType;    	TInt iPosition;    	TThreadId iTid;    	TUint8* iAudioPtr;    	TUint8* iBuffer;    //	TTimeIntervalMicroSeconds iStart;    	TTime iStart;    	TInt iTune;    	CSimpleWait* iWait;    #ifdef DODUMP    	TDump iDump;    #endif    };inline CEpocAudio& CEpocAudio::Current(SDL_AudioDevice* thisdevice)	{	return *static_cast<CEpocAudio*>((void*)thisdevice->hidden);	}	/*TBool EndSc(TAny*)	{		CActiveScheduler::Stop();	}	LOCAL_C void CleanScL()	{	CIdle* d = CIdle::NewLC(CActive:::EPriorityIdle);	d->Start(TCallBack(EndSc));	CActiveScheduler::Start();		}*/	void CEpocAudio::Free(SDL_AudioDevice* thisdevice)	{    CEpocAudio* ea = static_cast<CEpocAudio*>((void*)thisdevice->hidden);    if(ea)    	{		ASSERT(ea->iTid == RThread().Id());    	delete ea;    	thisdevice->hidden = NULL;	       	CActiveScheduler* as =  CActiveScheduler::Current();    	ASSERT(as->StackDepth() == 0);    	    	delete as;    	CActiveScheduler::Install(NULL);    	}    ASSERT(thisdevice->hidden == NULL);	}	CEpocAudio::CEpocAudio(TInt aBufferSize) : iBufferSize(aBufferSize), iPosition(-1) 	{	}void* CEpocAudio::NewL(TInt aBufferSize, TInt aFill)	{	CEpocAudio* eAudioLib = new (ELeave) CEpocAudio(aBufferSize);	CleanupStack::PushL(eAudioLib);	eAudioLib->ConstructL(aFill);	CleanupStack::Pop();	return eAudioLib;	}	void CEpocAudio::ConstructL(TInt aFill)	{	iBuffer = (TUint8*) User::AllocL(KAudioBuffers * iBufferSize);	memset(iBuffer, aFill, KAudioBuffers * iBufferSize);	iAudioPtr = iBuffer;	}TBool CEpocAudio::SetPause(TBool aPause)	{	if(aPause && iPosition >= 0)		{		iPosition = -1;		if(iPlayer != NULL)			iPlayer->Stop();		}	if(!aPause && iPosition < 0)		{		iPosition = 0;		if(iPlayer != NULL)			iPlayer->Start();		}	return iPosition < 0;	}	void CEpocAudio::ThreadInitL(TAny* aDevice)	{	iTid = RThread().Id(); 	CActiveScheduler* as =  new (ELeave) CActiveScheduler();    CActiveScheduler::Install(as);        EpocSdlEnv::AppendCleanupItem(TSdlCleanupItem((TSdlCleanupOperation)EPOC_CloseAudio, aDevice));       iWait = CSimpleWait::NewL();       iPlayer = new (ELeave) CStreamPlayer(*this, *this);    iPlayer->ConstructL();	    iPlayer->OpenStream(iRate, iChannels, iType);        #ifdef DODUMP    User::LeaveIfError(iDump.Open());    #endif	}			TUint8* CEpocAudio::Buffer()	{	iStart.UniversalTime();//	iStart = iPlayer->Position();			return iAudioPtr;	}	CEpocAudio::~CEpocAudio()	{	if(iWait != NULL)		iWait->Cancel();	delete iWait; 	if(iPlayer != NULL)		iPlayer->Close();	delete iPlayer;	delete iBuffer;	}	void CEpocAudio::Complete(TInt aState, TInt aError)	{	if(aState == MStreamObs::EClose)		{		}	if(iPlayer->Closed())		return;	switch(aError)		{		case KErrUnderflow:		case KErrInUse:			iPlayer->Start();			break;		case KErrAbort:			iPlayer->Open();		}	}	void sos_adump(SDL_AudioDevice* thisdevice, void* data, int len)	{#ifdef DODUMP	const TPtrC8 buf((TUint8*)data, len);	CEpocAudio::Current(thisdevice).Dump(buf);#endif	}const TInt KClip(256);	TPtrC8 CEpocAudio::Data()	{	if(iPosition < 0)		return KNullDesC8();		TPtrC8 data(iAudioPtr + iPosition, KClip);	#ifdef DODUMP	iDump.Dump(data);#endif		iPosition += KClip;	if(iPosition >= iBufferSize) 		{		/*		if(iAudioPtr == iBuffer)			iAudioPtr = iBuffer + iBufferSize;		else			iAudioPtr = iBuffer;*/				iAudioPtr += iBufferSize;				if((iAudioPtr - iBuffer) >= KAudioBuffers * iBufferSize)			iAudioPtr = iBuffer;				iPosition = -1;		if(iWait->IsActive())			{			iWait->Cancel();			CActiveScheduler::Stop();			}		}	return data;	}			void CEpocAudio::Play()	{	iPosition = 0;	}void CEpocAudio::Wait()	{	if(iPosition >= 0 /*&& iPlayer->Playing()*/)		{		const TInt64 bufMs = TInt64(iBufferSize - KClip) * TInt64(1000000);		const TInt64 specTime =  bufMs / TInt64(iRate * iChannels * 2);		iWait->After(specTime);				CActiveScheduler::Start();		TTime end;		end.UniversalTime();		const TTimeIntervalMicroSeconds delta = end.MicroSecondsFrom(iStart);		//		const TTimeIntervalMicroSeconds end = iPlayer->Position();									const TInt diff = specTime - delta.Int64();				if(diff > 0 && diff < 200000)			{			User::After(diff);			}				}	else		{	User::After(10000); //	iWait->Wait(10000); //just give some time...			}		}	void CEpocAudio::Open(TInt aRate, TInt aChannels, TUint32 aType, TInt aBytes)		{	iRate = aRate;	iChannels = aChannels;	iType = aType;    iBufferRate = iRate * iChannels * aBytes; //1/x	}	/* Audio driver bootstrap functions */AudioBootStrap EPOCAudio_bootstrap = {	"epoc\0\0\0",	"EPOC streaming audio\0\0\0",	Audio_Available,	Audio_CreateDevice};static SDL_AudioDevice *Audio_CreateDevice(int /*devindex*/){	SDL_AudioDevice *thisdevice;	/* Initialize all variables that we clean on shutdown */	thisdevice = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));	if ( thisdevice ) {		memset(thisdevice, 0, (sizeof *thisdevice));		thisdevice->hidden = NULL; /*(struct SDL_PrivateAudioData *)			 malloc((sizeof thisdevice->hidden)); */	}	if ( (thisdevice == NULL) /*|| (thisdevice->hidden == NULL) */) {		SDL_OutOfMemory();		if ( thisdevice ) {			free(thisdevice);		}		return(0);	}//	memset(thisdevice->hidden, 0, (sizeof *thisdevice->hidden));	/* Set the function pointers */	thisdevice->OpenAudio = EPOC_OpenAudio;	thisdevice->WaitAudio = EPOC_WaitAudio;	thisdevice->PlayAudio = EPOC_PlayAudio;	thisdevice->GetAudioBuf = EPOC_GetAudioBuf;	thisdevice->CloseAudio = EPOC_CloseAudio;    thisdevice->ThreadInit = EPOC_ThreadInit;	thisdevice->free = Audio_DeleteDevice;	return thisdevice;}static void Audio_DeleteDevice(SDL_AudioDevice *device)    {	//free(device->hidden);	free(device);    }static int Audio_Available(void){	return(1); // Audio stream modules should be always there!}static int EPOC_OpenAudio(SDL_AudioDevice *thisdevice, SDL_AudioSpec *spec){	SDL_TRACE("SDL:EPOC_OpenAudio");		TUint32 type = KMMFFourCCCodePCM16;	TInt bytes = 2;		switch(spec->format)		{		case AUDIO_U16LSB: 			type = KMMFFourCCCodePCMU16; 			break;		case AUDIO_S16LSB: 			type = KMMFFourCCCodePCM16; 			break;		case AUDIO_U16MSB: 			type = KMMFFourCCCodePCMU16B; 			break;		case AUDIO_S16MSB: 			type = KMMFFourCCCodePCM16B; 			break; 			//8 bit not supported!		case AUDIO_U8: 		case AUDIO_S8:		default:			spec->format = AUDIO_S16LSB;		};			if(spec->channels > 2)		spec->channels = 2;		spec->freq = CStreamPlayer::ClosestSupportedRate(spec->freq);		/* Allocate mixing buffer */	const TInt buflen = spec->size;// * bytes * spec->channels;//	audiobuf = NULL;        TRAPD(err, thisdevice->hidden = static_cast<SDL_PrivateAudioData*>(CEpocAudio::NewL(buflen, spec->silence)));    if(err != KErrNone)        return -1;	CEpocAudio::Current(thisdevice).Open(spec->freq, spec->channels, type, bytes);		CEpocAudio::Current(thisdevice).SetPause(ETrue);	   // isSDLAudioPaused = 1;    thisdevice->enabled = 0; /* enable only after audio engine has been initialized!*/	/* We're ready to rock and roll. :-) */	return(0);}static void EPOC_CloseAudio(SDL_AudioDevice* thisdevice)    {#ifdef DEBUG_AUDIO    SDL_TRACE("Close audio\n");#endif	CEpocAudio::Free(thisdevice);	}static void EPOC_ThreadInit(SDL_AudioDevice *thisdevice)    {	SDL_TRACE("SDL:EPOC_ThreadInit");    CEpocAudio::Current(thisdevice).ThreadInitL(thisdevice);    RThread().SetPriority(EPriorityMore);    thisdevice->enabled = 1;    }/* This function waits until it is possible to write a full sound buffer */static void EPOC_WaitAudio(SDL_AudioDevice* thisdevice){#ifdef DEBUG_AUDIO    SDL_TRACE1("wait %d audio\n", CEpocAudio::AudioLib().StreamPlayer(KSfxChannel).SyncTime());    TInt tics = User::TickCount();#endif	CEpocAudio::Current(thisdevice).Wait();#ifdef DEBUG_AUDIO    TInt ntics =  User::TickCount() - tics;    SDL_TRACE1("audio waited %d\n", ntics);    SDL_TRACE1("audio at %d\n", tics);#endif} static void EPOC_PlayAudio(SDL_AudioDevice* thisdevice)	{ 	if(CEpocAudio::Current(thisdevice).SetPause(SDL_GetAudioStatus() == SDL_AUDIO_PAUSED)) 		SDL_Delay(500); //hold on the busy loop 	else 		CEpocAudio::Current(thisdevice).Play();#ifdef DEBUG_AUDIO    SDL_TRACE("buffer has audio data\n");#endif	#ifdef DEBUG_AUDIO	SDL_TRACE1("Wrote %d bytes of audio data\n", buflen);#endif}static Uint8 *EPOC_GetAudioBuf(SDL_AudioDevice* thisdevice)	{	return CEpocAudio::Current(thisdevice).Buffer();	}

⌨️ 快捷键说明

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