📄 macaudio.cp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: macaudio.cp,v 1.5.32.1 2004/07/09 02:01:22 hubbe Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** *///// macaudio.cp// #include <stdio.h>#include "macaudio.h"#include "USound.h" #ifndef _MAC_MACHO#include <AIFF.h>#include <fixmath.h>#endif#include "hxtypes.h" #include "hxerrors.h" #include "hxcom.h"#include "hxausvc.h"#include "auderrs.h"#include "hxaudev.h"#include "hxslist.h"#include "hxtick.h" #include "chxpckts.h"#ifdef THREADS_SUPPORTED#include "hxthread.h"#endif#include "hxmm.h"//#define LOG_MULTIPLE_DEFERRED_TASKS 1BOOL gSoundCallbackTime = FALSE;#if defined( _CARBON ) || defined( _MAC_UNIX )DeferredTaskUPP CAudioOutMac::gDeferredTask = NewDeferredTaskUPP(CAudioOutMac::DeferredTaskCallback);#elseDeferredTaskUPP CAudioOutMac::gDeferredTask = NewDeferredTaskProc(CAudioOutMac::DeferredTaskCallback);#endif#ifdef THREADS_SUPPORTEDHXMutex* CAudioOutMac::zm_pMutex = NULL;#endifCAudioOutMac* gActiveAudioDevice = NULL; #if defined( _CARBON ) || defined( _MAC_UNIX )typedef pascal Handle (*MacAudioNewHandleSysProcPtr)(Size);CFragConnectionID gAudioInterfaceLibConnID = kInvalidID;MacAudioNewHandleSysProcPtr gMacAudioNewHandleSysProc = nil;bool gMacAudioTriedToInitialize = false;void MacAudioInitInterfaceLibProcPtrs(){ if (gMacAudioTriedToInitialize) return; gMacAudioTriedToInitialize = true; if (gAudioInterfaceLibConnID == kInvalidID) { GetSharedLibrary("\pInterfaceLib", kCompiledCFragArch, kReferenceCFrag, &gAudioInterfaceLibConnID, nil, nil); } if (gAudioInterfaceLibConnID != kInvalidID) { OSErr err = noErr; err = FindSymbol(gAudioInterfaceLibConnID, "\pNewHandleSys", (Ptr*)&gMacAudioNewHandleSysProc, nil); }}#endif/*--------------------------------------------------------------------------| CMacWaveFormat|| Default ctor.--------------------------------------------------------------------------*/CMacWaveFormat::CMacWaveFormat (void) { /* begin CMacWaveFormat */ SetFormatDflt (); } /* end CMacWaveFormat *//*--------------------------------------------------------------------------| ~CMacWaveFormat|| dtor.--------------------------------------------------------------------------*/CMacWaveFormat::~CMacWaveFormat (void) { /* begin ~CMacWaveFormat */ } /* end ~CMacWaveFormat *//*--------------------------------------------------------------------------| SetUpSound|| Formats a sound handle.--------------------------------------------------------------------------*/OSErr CMacWaveFormat::SetUpSound ( SndListHandle sndHandle, long numBytes, short *headerLen, long *headerOffset) { /* begin SetUpSound */ OSErr e = noErr; long response; if (sampleSize > 8) { if (USound::CheckSMVersion () < 3) { if ((::Gestalt(gestaltSoundAttr, &response) == noErr) && ((response & (1L << gestalt16BitSoundIO)) == 0)) return (noHardwareErr); } /* if */ else { if ((::Gestalt(gestaltSoundAttr, &response) == noErr) && ((response & (1L << gestalt16BitAudioSupport)) == 0)) return (noHardwareErr); } /* else */ } /* if */ if (noErr != (e = ::SetupSndHeader (sndHandle, numChannels, sampleRate, sampleSize, compressionType, baseFrequency, numBytes, headerLen))) goto CleanUp; if (noErr != (e = USound::GetSoundHeaderOffset (sndHandle, headerOffset))) goto CleanUp; CleanUp: return (e); } /* end SetUpSound *//*--------------------------------------------------------------------------| SetHeaderLength [static]|| Formats a sound header for a given byte count.--------------------------------------------------------------------------*/OSErr CMacWaveFormat::SetHeaderLength ( SoundHeaderPtr pSoundHeader, long numBytes) { /* begin SetHeaderLength */ switch (pSoundHeader->encode) { case stdSH: /*standard sound header*/ pSoundHeader->length = numBytes; break; case extSH: /*extended sound header*/ { ExtSoundHeaderPtr eh = (ExtSoundHeaderPtr) pSoundHeader; eh->numFrames = numBytes / (eh->numChannels * (eh->sampleSize / 8)); } break; case cmpSH: /*compressed sound header*/ { CmpSoundHeaderPtr ch = (CmpSoundHeaderPtr) pSoundHeader; ch->numFrames = numBytes / (ch->numChannels * (ch->sampleSize / 8)); } break; default: return badFormat; } /* switch */ return noErr; } /* SetHeaderLength *//*--------------------------------------------------------------------------| SetFormatDflt|| Sets up the default Sound header information.--------------------------------------------------------------------------*/void CMacWaveFormat::SetFormatDflt (void) { /* begin SetFormatDflt */ //mwf.wf.nAvgBytesPerSec = 22050; //mwf.wf.nBlockAlign = 2; numChannels = 1; //mwf.wf.nChannels = 1; sampleRate = Long2Fix (8000); //mwf.wf.nSamplesPerSec = 8000; //sampleRate = rate11025hz; //mwf.wf.nSamplesPerSec = 11025; sampleSize = 16; //mwf.wBitsPerSample = 16; compressionType = NoneType; //mwf.wf.wFormatTag = WAVE_FORMAT_PCM; baseFrequency = kMiddleC; } /* end SetFormatDflt *//*--------------------------------------------------------------------------| SetFormatDflt|| Sets up the default Sound header information.--------------------------------------------------------------------------*/void CMacWaveFormat::SetFormat ( ULONG32 inSampleRate, UINT16 channels, UINT16 bitsPerSample) { numChannels = channels; sampleRate = inSampleRate << 16L; sampleSize = bitsPerSample; compressionType = NoneType; baseFrequency = kMiddleC; }/*--------------------------------------------------------------------------| CWaveHeader--------------------------------------------------------------------------*/CWaveHeader::CWaveHeader (void) : soundA5 (0) , state (kFreeState) , waveOut (NULL) , mMaxPlay (0) , sndHandle (nil) , mHeaderLen (0) , mSoundHeader (nil) { /* begin CWaveHeader */ soundA5 = SetCurrentA5 (); } /* end CWaveHeader */ /*--------------------------------------------------------------------------| ~CWaveHeader--------------------------------------------------------------------------*/CWaveHeader::~CWaveHeader (void) { /* begin ~CWaveHeader */ if (sndHandle) ::DisposeHandle ((Handle) sndHandle); sndHandle = nil; } /* end ~CWaveHeader */ /*--------------------------------------------------------------------------| CWaveHeader--------------------------------------------------------------------------*/const Size CWaveHeader::kSndHeaderSize = 512; UINT16 CWaveHeader::WAVE_BLOCKSIZE = 4096;OSErr CWaveHeader::Allocate ( UINT16 inMaxPlay, float sampleRate, UINT16 channels, UINT16 bitsPerSample) { /* begin Allocate */ OSErr e = badFormat; long offset; if (!waveOut) goto CleanUp; OSErr theError; sndHandle = (SndListHandle) ::TempNewHandle (kSndHeaderSize + inMaxPlay, &theError); if (!sndHandle) goto CleanUp; check_noerr (theError); waveOut->wf.SetFormat ((long)sampleRate,channels,bitsPerSample); if (noErr != (e = waveOut->wf.SetUpSound (sndHandle, inMaxPlay, &mHeaderLen, &offset))) goto CleanUp; ::SetHandleSize ((Handle) sndHandle, mHeaderLen + inMaxPlay); if (noErr != (e = MemError ())) goto CleanUp; mMaxPlay = inMaxPlay; ::MoveHHi ((Handle) sndHandle); ::HLock ((Handle) sndHandle); mSoundHeader = (SoundHeaderPtr) ((*(Handle) sndHandle) + offset); CleanUp: return (e); } /* end Allocate *//*--------------------------------------------------------------------------| Release--------------------------------------------------------------------------*/void CWaveHeader::Release (short releaseCode, BOOL bSendTimeSync /*= TRUE*/){ /* begin Release */ if (kFreeState != state) { state = kFreeState; if ((CWaveHeader::kResetRelease != releaseCode) && (CWaveHeader::kAbortRelease != releaseCode)) //cz 5/7/96 if (waveOut) waveOut->DonePlaying (cbPlaying, timeEnd,releaseCode == kCallBackRelease, bSendTimeSync); } /* if */ if (kAbortRelease == releaseCode) { if (sndHandle) { ::DisposeHandle ((Handle) sndHandle); sndHandle=NULL; } sndHandle = nil; mMaxPlay = 0; mSoundHeader = nil; } /* if */ } /* end Release *//*--------------------------------------------------------------------------| PlayBuffer--------------------------------------------------------------------------*/OSErr CWaveHeader::PlayBuffer ( char *pData, UINT16 cbPlayingArg, ULONG32 timeEndArg) { /* begin PlayBuffer */ OSErr e = noErr; SndCommand cmd; if (!waveOut) return (badFormat); if (kFreeState != state) return (badFormat); if (!sndHandle) return (nilHandleErr); if (cbPlayingArg > mMaxPlay) return (memFullErr); if (noErr != (e = waveOut->wf.SetHeaderLength (mSoundHeader, cbPlayingArg))) goto CleanUp; if(pData != NULL) ::BlockMove (pData, (*(Handle) sndHandle) + mHeaderLen, cbPlayingArg); cmd.cmd = bufferCmd; cmd.param1 = 0; cmd.param2 = (long) mSoundHeader; if (noErr != (e = ::SndDoCommand (waveOut->chan, &cmd, TRUE))) goto CleanUp; state = kQueuedState; cbPlaying = cbPlayingArg; timeEnd = timeEndArg; waveOut->StartedPlaying (cbPlaying); cmd.cmd = callBackCmd; cmd.param1 = kCallBackRelease; cmd.param2 = (long) this; if (noErr != (e = ::SndDoCommand (waveOut->chan, &cmd, TRUE))) goto CleanUp; waveOut->m_bAudioCallbacksAreAlive = TRUE; CleanUp: return (e); } /* end PlayBuffer */ /*--------------------------------------------------------------------------| NewChannel--------------------------------------------------------------------------*/SndChannelPtr CWaveHeader::NewChannel (void) { /* begin NewChannel */ SndChannelPtr chan = nil;#if defined( _CARBON ) || defined( _MAC_UNIX ) SndCallBackUPP userProc = NewSndCallBackUPP (Callback);#else SndCallBackUPP userProc = NewSndCallBackProc (Callback);#endif // if (noErr != ::SndNewChannel (&chan, sampledSynth, initStereo + initNoDrop + initNoInterp, userProc)) if (noErr != ::SndNewChannel (&chan, sampledSynth, initStereo, userProc)) chan = nil; return chan; } /* end NewChannel *//*--------------------------------------------------------------------------| DisposeChannel--------------------------------------------------------------------------*/OSErr CWaveHeader::DisposeChannel ( SndChannelPtr chan) { /* begin DisposeChannel */ OSErr e; if(chan) { SndCallBackUPP userProc = chan->callBack;#if defined( _CARBON ) || defined( _MAC_UNIX ) if (userProc) DisposeSndCallBackUPP (userProc);#else if (userProc) DisposeRoutineDescriptor (userProc);#endif e = ::SndDisposeChannel (chan, TRUE); } return e; } /* end DisposeChannel *//*--------------------------------------------------------------------------| Callback--------------------------------------------------------------------------*/pascal void CWaveHeader::Callback ( SndChannelPtr chan, SndCommand *cmd) { /* begin Callback */ #ifndef _MAC_UNIX HXMM_INTERRUPTON();#endif // if (HXMM_RAHUL_CHECK())// {// DebugStr("\pCWaveHeader Deferred Task ENTER;g");// } DeferredTask* dtrec = NULL; CWaveHeader* wh = NULL; SndCommand* newCommand; if (cmd) { wh = (CWaveHeader *) cmd->param2; if ( wh ) { CAudioOutMac* theWaveOut = wh->waveOut; if ( theWaveOut ) { CMacWaveFormat wf = theWaveOut->wf; UINT32 ulBytesPerSecond = wf.numChannels * ( (ULONG32)wf.sampleRate >> 16 ) * ( wf.sampleSize / 8 ); theWaveOut->m_millisecondsIntoClip += (double)wh->cbPlaying * 1000.0 / (double)ulBytesPerSecond; } } dtrec=wh->waveOut->mDeferredTaskRec; } if (!dtrec) { goto CleanUp; } newCommand=new SndCommand; HX_ASSERT(newCommand); if (!newCommand) { delete dtrec; goto CleanUp; } if (cmd) { *newCommand=*cmd; } else { delete newCommand; delete dtrec; goto CleanUp; } wh->waveOut->AddToThePendingList(newCommand); if (!wh->waveOut->m_bDeferredTaskPending) { wh->waveOut->m_bDeferredTaskPending = TRUE; short err = 0; if ( wh->waveOut->m_bIsQuitting ) { err = -1; // just so it's nonzero } else { err = DTInstall(dtrec); } if ( err != noErr ) { wh->waveOut->m_bDeferredTaskPending = FALSE; wh->waveOut->m_bAudioCallbacksAreAlive = FALSE; delete dtrec; delete newCommand; goto CleanUp; } } /* if (wh) { long saveA5 = SetA5 (wh->soundA5); wh->Release (cmd->param1); SetA5 (saveA5); } */ CleanUp: #ifndef _MAC_UNIX HXMM_INTERRUPTOFF();#endif // if (HXMM_RAHUL_CHECK())// {// DebugStr("\pCWaveHeader Deferred Task LEAVE;g");// } return; } /* end Callback */ pascal void CAudioOutMac::DeferredTaskCallback(long param){ if (!param) { return; } #ifndef _MAC_UNIX HXMM_INTERRUPTON();#endif CAudioOutMac* pAudioOut = (CAudioOutMac*) param; pAudioOut->m_bAudioCallbacksAreAlive = FALSE; #ifdef THREADS_SUPPORTED
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -