📄 macaudio.cp
字号:
SameProcess(&(currentPtr[i].psn), &psn, &bSameProcess);
if (bSameProcess &&
currentPtr[i].quitting == &m_bIsQuitting &&
currentPtr[i].pending == &m_bAudioCallbacksAreAlive )
{
currentPtr[i].quitting = NULL;
currentPtr[i].pending = NULL;
}
}
}
#endif
::DisposePtr ((Ptr)mDeferredTaskRec);
}
CleanupPendingLists();
HX_DELETE(m_pPendingCallbackList);
gActiveAudioDevice = NULL;
HX_RELEASE(m_pScheduler);
HX_RELEASE(m_pInterruptState);
} /* end ~CAudioOutMac */
UINT16 CAudioOutMac::m_uzVolume = 50;
HX_RESULT
CAudioOutMac::_Imp_Open( const HXAudioFormat* pFormat )
{
/*
** Open the sound channel.
*/
NUM_WAVEHDRS = 45; //params->numBufs;
CWaveHeader::WAVE_BLOCKSIZE = pFormat->uMaxBlockSize;
if (chan) CWaveHeader::DisposeChannel (chan);
m_bAudioCallbacksAreAlive = FALSE;
chan = CWaveHeader::NewChannel ();
if (!chan)
return (HX_AUDIO_DRIVER_ERROR);
if (!m_pPendingCallbackList)
{
m_pPendingCallbackList = new CHXSimpleList;
}
ULONG32 nSampleRate = pFormat->ulSamplesPerSec;
ULONG32 nBlockSize = pFormat->uMaxBlockSize;
#if powerc && FORCE_RATE_CONVERSION
// if we are on a PowerPC we will do our own sample rate conversion
// since the Apple version gives us a lot of pops and aliasing
ULONG32 sysSampleRate = ::USound::GetSystemSampleRate(chan);
// Note: we currently have to HACK 11227 and 22254 sample rates on
// old macs to 11025 and 22050
switch(sysSampleRate)
{
case 11227:
sysSampleRate = 11025;
break;
case 22254:
sysSampleRate = 22050;
break;
}
// we only have a problem if the sample rate is <= 32000 Hz. (sigh!)
if(nSampleRate <= 32000)
{
if(sysSampleRate > 0 && nSampleRate != sysSampleRate)
{
UINT16 bytesPerSample = pFormat->wBitsPerSample > 8 ? 2 : 1;
UINT16 frameSize = bytesPerSample * pFormat->wChannels;
ULONG32 bytesPerSecond = (ULONG32) (nSampleRate * frameSize);
float bufDuration = (float)pFormat->uMaxBlockSize/(float)bytesPerSecond;
// calculate the bytesPerSecond of the system sample rate
bytesPerSecond = (ULONG32) (sysSampleRate * frameSize);
// update the buffer size to handle the new sample rate
nBlockSize = bytesPerSecond * bufDuration;
// round the buffersize to a framesize
nBlockSize = ((nBlockSize/frameSize) * frameSize) + frameSize;
nSampleRate = sysSampleRate;
//pFormat->ulSamplesPerSec = sysSampleRate;
}
}
#ifndef MAC_RELEASE
#if 0
char s[256];
::sprintf(s,"sample rate %ld",sysSampleRate);
::c2pstr(s);
DebugStr((UCHAR *)s);
#endif
#endif // MAC_RELEASE
#endif // powerc && FORCE_RATE_CONVERSION
// SetVolume(pFormat->volume);
_Imp_SetVolume(m_uzVolume);
/*
** Allocate memory for wave block headers and for wave data.
*/
if (NULL == mlpWaveHdrs)
{
if (NULL == (mlpWaveHdrs = new CWaveHeader [NUM_WAVEHDRS]))
return (HX_MEMORY_ERROR);
for (short iwh = 0; iwh < NUM_WAVEHDRS; iwh++)
{
CWaveHeader *pwh = GetWaveHeader (iwh);
if (pwh)
{
pwh->SetOutput (this);
switch (pwh->Allocate (nBlockSize, nSampleRate,
pFormat->uChannels,pFormat->uBitsPerSample))
{
case noErr:
break;
case memFullErr:
return (HX_MEMORY_ERROR);
default:
return (HX_AUDIO_DRIVER_ERROR);
}
}
}
}
/*
** Indicate that no audio blocks are currently playing.
*/
mcbPlaying = 0;
mPaused = FALSE;
if (!m_pScheduler && m_pContext)
{
m_pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
m_pContext->QueryInterface(IID_IHXInterruptState, (void**) &m_pInterruptState);
}
return (HX_NO_ERROR);
}
HX_RESULT
CAudioOutMac::_Imp_Close( void )
{
Abort();
return HXR_OK;
}
HX_RESULT
CAudioOutMac::_Imp_Pause( void )
{
mPaused = TRUE;
if (OkToPauseResume(FALSE))
{
// Stop playback
if (chan != NULL)
DoImmediate (pauseCmd);
}
return HXR_OK;
}
HX_RESULT
CAudioOutMac::_Imp_Resume( void )
{
mPaused = FALSE;
if (OkToPauseResume(TRUE))
{
if (chan != NULL)
{
DoImmediate (resumeCmd);
}
this->OnTimeSync();
}
return HXR_OK;
}
HX_RESULT
CAudioOutMac::_Imp_Write( const HXAudioData* pAudioOutHdr )
{
HX_RESULT err = HX_NO_ERROR;
// CWaveHeader *pwh = GetWaveHeader(0);;
CWaveHeader *pwh=NULL;
Boolean found = FALSE;
void* pBuffer = NULL;
for (short iwh = 0; iwh < NUM_WAVEHDRS && !found; iwh++)
{
pwh = GetWaveHeader(iwh);
found = pwh && pwh->Available ();
}
if (found)
{
pBuffer = pwh->get_buffer();
}
else
{
return playError;
}
if(pwh == 0)
{
return (playError);
}
char* pData = 0;
pData = (char*)pAudioOutHdr->pData->GetBuffer();
ULONG32 nLen = pAudioOutHdr->pData->GetSize();
if (pBuffer)
{
memcpy(pBuffer, pData, nLen);
if (noErr != pwh->PlayBuffer ((char*)pBuffer, nLen, pAudioOutHdr->ulAudioTime))
err = (playError);
}
if (!err)
{
m_uNumBlocksInDevice++;
if(m_bFirstPacket)
{
m_bFirstPacket = FALSE;
m_ulTimeOfFirstPacket = pAudioOutHdr->ulAudioTime;
}
}
return err;
}
HX_RESULT
CAudioOutMac::_Imp_Reset( void )
{
// Stop playback
if (chan != NULL) {
DoImmediate (pauseCmd);
DoImmediate (flushCmd);
DoImmediate (quietCmd);
} /* if */
m_ulCurrentTime = 0;
m_bFirstPacket = TRUE;
// Mark blocks as available.
ReleaseBlocks (CWaveHeader::kResetRelease);
m_uNumBlocksInDevice = 0;
CleanupPendingLists();
return HX_NO_ERROR;
}
HX_RESULT
CAudioOutMac::_Imp_Drain( void )
{
return HX_NO_ERROR;
}
BOOL
CAudioOutMac::_Imp_SupportsVolume( void )
{
return TRUE;
}
UINT16
CAudioOutMac::_Imp_GetVolume()
{
#if 0
unsigned long volume=0;
SndCommand theCmd;
theCmd.cmd = getVolumeCmd;
theCmd.param1 = 0;
theCmd.param2 = volume;
// queue volume command in channel
::SndDoImmediate(chan,&theCmd);
return (UINT16) volume;
#endif
return m_uzVolume;
}
HX_RESULT
CAudioOutMac::_Imp_SetVolume( const UINT16 uVolume )
{
SndCommand theCmd;
unsigned long volume;
unsigned long leftVolume, rightVolume;
// if(uVolume < 0) uVolume = 0;
if(chan)
{
#if defined( _CARBON ) || defined( _MAC_UNIX )
leftVolume = rightVolume = (long) uVolume * 5; //uVolume is between 0 and 100
volume = (rightVolume << 16) + leftVolume;
theCmd.cmd = volumeCmd;
theCmd.param1 = 0;
theCmd.param2 = volume;
// queue volume command in channel
::SndDoImmediate(chan,&theCmd);
#else
#if OLDROUTINENAMES && !GENERATINGCFM
if (USound::CheckSMVersion () < 3)
::SetSoundVol (uVolume);
#else
leftVolume = rightVolume = (long) uVolume * 5; //uVolume is between 0 and 100
volume = (rightVolume << 16) + leftVolume;
theCmd.cmd = volumeCmd;
theCmd.param1 = 0;
theCmd.param2 = volume;
// queue volume command in channel
::SndDoImmediate(chan,&theCmd);
#endif
#endif
}
m_uzVolume = uVolume;
return HXR_OK;
}
HX_RESULT
CAudioOutMac::_Imp_CheckFormat( const HXAudioFormat* pFormat)
{
return HX_NO_ERROR;
}
HX_RESULT
CAudioOutMac::_Imp_Seek(ULONG32 ulSeekTime)
{
m_ulCurrentTime = 0;
return HX_NO_ERROR;
}
/*---------------------------------------------------------------------------
| ReleaseBlocks
|
| Frees the blocks manually
--------------------------------------------------------------------------*/
void CAudioOutMac::ReleaseBlocks (
short releaseCode)
{ /* begin ReleaseBlocks */
// Mark blocks as available.
for (short iwh = 0; iwh < NUM_WAVEHDRS; iwh++) {
CWaveHeader *pwh = GetWaveHeader (iwh);
// if (pwh && !pwh->Available ())
if (pwh)
pwh->Release (releaseCode);
} /* for */
m_millisecondsIntoClip = 0.0;
} /* end ReleaseBlocks */
/*---------------------------------------------------------------------------
| DoImmediate
|
| Executes a sound command
--------------------------------------------------------------------------*/
OSErr CAudioOutMac::DoImmediate (
short cmd,
short param1/*= 0*/,
long param2/*= 0L*/)
{ /* begin DoImmediate */
SndCommand sndCmd;
sndCmd.cmd = cmd;
sndCmd.param1 = param1;
sndCmd.param2 = param2;
return ::SndDoImmediate (chan, &sndCmd);
} /* end DoImmediate */
/*---------------------------------------------------------------------------
| Abort
|
| Halts playback and shuts down
--------------------------------------------------------------------------*/
void CAudioOutMac::Abort (void)
{ /* begin Abort */
// Stop playback
if (chan != NULL) {
// Kludge around usual SM unreliability
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -