📄 audbeos.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: audbeos.cpp,v 1.2.42.1 2004/07/09 02:01:42 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 ***** *//******************************************************************* * 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -