📄 audbeos.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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.
*
* 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 ***** */
/*******************************************************************
* audbeos.cpp
*
* CLASS: CAudioOutBeOS
*
* DESCRIPTION: Class implementation for BeOS-specific audio devices
*
*******************************************************************/
#include "hxtypes.h"
#include "hxresult.h"
#include "hxcom.h"
#include "ihxpckts.h"
#include "hxausvc.h"
#include "auderrs.h"
#include "hxaudev.h"
#include "hxtick.h"
#include "hxthread.h"
#include "hxbuffer.h"
#include "hxslist.h"
#include "hxengin.h"
#include "timeval.h"
#include "hxaudses.h"
#include "audbeos.h"
#include <PushGameSound.h>
#include <MediaDefs.h>
struct IHXCallback; // forward declaration needed for callback.
CAudioOutBeOS::CAudioOutBeOS()
: m_player(NULL)
, m_bFirstWrite(TRUE)
, m_pPendingBufferList(NULL)
, m_ulLastPlayCursor(0)
, m_ulCurrentPlayTime(0)
, m_ulLastTimeSync(0)
, m_bPlaying(FALSE)
, m_ulBufferSize(0)
, m_ulFrameSize(0)
, m_ulNextWriteOffset(0)
, m_ulOldBytesLeft(0)
, m_ulBlockSize(0)
, m_bGotAWrite(FALSE)
#if _BEOS_AUDIODEV_CALLBACK
, m_pPlaybackCountCBTime(NULL)
, m_bCallbackPending(FALSE)
, m_PendingCallbackID(0)
#endif
{
#if _BEOS_AUDIODEV_CALLBACK
m_pPlaybackCountCBTime = new Timeval;
#endif
}
CAudioOutBeOS::~CAudioOutBeOS()
{
_Imp_Close();
#if _BEOS_AUDIODEV_CALLBACK
delete m_pPlaybackCountCBTime;
#endif
}
HX_RESULT
CAudioOutBeOS::_Imp_Open(const HXAudioFormat* pFormat)
{
size_t bufSize;
void *basePtr;
SetFormat(pFormat);
#if _BEOS_AUDIODEV_CALLBACK
if (m_pOwner)
{
m_pOwner->GetScheduler(&m_pScheduler);
m_pScheduler->AddRef();
}
#endif
// set up the player with enough buffer space for about 4 seconds of audio
// m_player = new BPushGameSound(m_gameSoundFormat.frame_rate, &m_gameSoundFormat, 4);
// BPushGameSound->CurrentPosition is accurate to within a buffer
// Therefore, to keep good synchronization between audio and video, a single
// buffer should not have a longer duration than a frame of video. We don't
// know here what the video framerate (if any) may be, but we can assume that it
// isn't over 30fps. Thus, each audio buffer should be no longer than about 30 ms.
// To store about 3 seconds of audio, we'll need 100 buffers.
bufSize = (size_t)(m_gameSoundFormat.frame_rate * 0.03f);
m_player = new BPushGameSound(bufSize, &m_gameSoundFormat, 100);
if (m_player->InitCheck() != B_OK)
{
delete m_player;
m_player = NULL;
return RA_AOE_BADOPEN;
}
if (m_player->LockForCyclic(&basePtr, &bufSize) != BPushGameSound::lock_ok)
m_player->UnlockCyclic();
m_ulBufferSize = bufSize;
m_ulBlockSize = m_ulBytesPerGran;
return HXR_OK;
}
HX_RESULT
CAudioOutBeOS::_Imp_Close()
{
#if _BEOS_AUDIODEV_CALLBACK
if (m_pScheduler)
{
// Remove callback from scheduler
if (m_bCallbackPending)
{
m_pScheduler->Remove(m_PendingCallbackID);
m_bCallbackPending = FALSE;
}
m_pScheduler->Release();
m_pScheduler = NULL;
}
#endif
if (m_pPendingBufferList)
{
while (!m_pPendingBufferList->IsEmpty())
{
IHXBuffer *pBuffer = (IHXBuffer *)m_pPendingBufferList->RemoveHead();
pBuffer->Release();
pBuffer = NULL;
}
delete m_pPendingBufferList;
m_pPendingBufferList = NULL;
}
if (m_player)
{
m_player->StopPlaying();
delete m_player;
m_player = NULL;
}
m_bPlaying = FALSE;
return HXR_OK;
}
HX_RESULT
CAudioOutBeOS::_Imp_Seek(ULONG32 ulSeekTime)
{
return HXR_OK;
}
HX_RESULT
CAudioOutBeOS::_Imp_Pause()
{
if (m_player)
{
size_t curPos = m_player->CurrentPosition() * m_ulFrameSize;
uint8 *pAudioPtr;
size_t i, ulAudioBytes;
m_player->StopPlaying();
if (m_player->LockForCyclic((void **)&pAudioPtr, &ulAudioBytes) == BPushGameSound::lock_ok && pAudioPtr)
{
// shift the audio data all back to the beginning of the buffer
if (m_ulNextWriteOffset > curPos)
{
for (i = curPos; i < m_ulNextWriteOffset; i++)
{
pAudioPtr[i - curPos] = pAudioPtr[i];
}
m_ulNextWriteOffset = m_ulNextWriteOffset - curPos;
}
else
{ // wrap-around
uint32 remaining = ulAudioBytes - curPos;
uint8 *tempBuf = new uint8[m_ulNextWriteOffset];
for (i = 0; i < m_ulNextWriteOffset; i++)
{
tempBuf[i] = pAudioPtr[i];
}
for (i = curPos; i < ulAudioBytes; i++)
{
pAudioPtr[i - curPos] = pAudioPtr[i];
}
for (i = 0; i < m_ulNextWriteOffset; i++)
{
pAudioPtr[i + remaining] = tempBuf[i];
}
delete [] tempBuf;
m_ulNextWriteOffset = remaining + m_ulNextWriteOffset;
}
m_player->UnlockCyclic();
m_bGotAWrite = TRUE;
m_ulLastPlayCursor = 0;
}
}
m_bPlaying = FALSE;
return HXR_OK;
}
HX_RESULT
CAudioOutBeOS::_Imp_Resume()
{
if (m_player)
m_player->StartPlaying();
m_ulLastPlayCursor = 0;
m_bPlaying = TRUE;
m_ulLastTimeSync = HX_GET_TICKCOUNT();
OnTimeSync();
return HXR_OK;
}
HX_RESULT
CAudioOutBeOS::_Imp_Write(const HXAudioData* pAudioOutData)
{
HX_RESULT theErr = HXR_OK;
IHXBuffer *pBuffer = NULL;
#if _BEOS_AUDIODEV_CALLBACK
if (m_bFirstWrite && pAudioOutData)
{
/* Initialize the playback callback time. */
HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime();
m_pPlaybackCountCBTime->tv_sec = lTime.tv_sec;
m_pPlaybackCountCBTime->tv_usec = lTime.tv_usec;
m_bFirstWrite = FALSE;
ReschedPlaybackCheck();
}
#endif
if (pAudioOutData && pAudioOutData->pData)
{
pAudioOutData->pData->AddRef();
}
if (m_pPendingBufferList && m_pPendingBufferList->GetCount() > 0)
{
if (pAudioOutData && pAudioOutData->pData)
m_pPendingBufferList->AddTail(pAudioOutData->pData);
pBuffer = (IHXBuffer *)m_pPendingBufferList->RemoveHead();
}
else
{
if (pAudioOutData && pAudioOutData->pData)
pBuffer = pAudioOutData->pData;
}
BOOL bCanContinue = TRUE;
while (bCanContinue && pBuffer)
{
UINT32 ulBufferSize = pBuffer->GetSize();
uint8* pAudioPtr1 = NULL;
uint8* pAudioPtr2 = NULL;
size_t curPos;
size_t ulAudioBytes1 = 0;
size_t ulAudioBytes2 = 0;
size_t ulAudioBytesWritten1 = 0;
size_t ulAudioBytesWritten2 = 0;
if (m_player->LockForCyclic((void **)&pAudioPtr1, &ulAudioBytes1) == BPushGameSound::lock_ok && pAudioPtr1)
{
size_t ulSizeToWrite, curPos;
if (m_player->IsPlaying())
curPos = m_player->CurrentPosition() * m_ulFrameSize;
else
curPos = 0;
if (m_ulNextWriteOffset >= curPos)
{
pAudioPtr2 = pAudioPtr1;
ulAudioBytes1 -= m_ulNextWriteOffset;
}
else
{
pAudioPtr2 = NULL;
ulAudioBytes1 = curPos - m_ulNextWriteOffset - 1;
}
pAudioPtr1 += m_ulNextWriteOffset;
if (ulAudioBytes1 < 0)
ulAudioBytes1 = 0;
ulSizeToWrite = ulBufferSize;
if (ulSizeToWrite > ulAudioBytes1)
{
ulSizeToWrite = ulAudioBytes1;
}
if (ulSizeToWrite > 0)
{
::memcpy(pAudioPtr1, (void*) pBuffer->GetBuffer(), ulSizeToWrite); /* Flawfinder: ignore */
}
ulAudioBytesWritten1 = ulSizeToWrite;
size_t ulRemainingToWrite = ulBufferSize - ulSizeToWrite;
ulAudioBytes2 = curPos - 1;
if (ulRemainingToWrite > 0 && pAudioPtr2 && ulAudioBytes2 > 0)
{
ulSizeToWrite = ulRemainingToWrite;
if (ulSizeToWrite > ulAudioBytes2)
{
ulSizeToWrite = ulAudioBytes2;
}
::memcpy(pAudioPtr2, (void*) (pBuffer->GetBuffer() + ulAudioBytesWritten1), ulSizeToWrite);
ulAudioBytesWritten2 = ulSizeToWrite;
ulRemainingToWrite -= ulSizeToWrite;
}
if (ulRemainingToWrite > 0)
{
IHXBuffer* pNewBuffer = (IHXBuffer*) new CHXBuffer;
pNewBuffer->AddRef();
pNewBuffer->Set(pBuffer->GetBuffer() + (ulBufferSize - ulRemainingToWrite), ulRemainingToWrite);
if (!m_pPendingBufferList)
{
m_pPendingBufferList = new CHXSimpleList;
}
m_pPendingBufferList->AddHead((void*) pNewBuffer);
// no more space in the secondary buffer
bCanContinue = FALSE;
}
m_player->UnlockCyclic();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -