AudioRenderer.cpp
上传用户:lusi_8715
上传日期:2007-01-08
资源大小:199k
文件大小:8k
源码类别:
流媒体/Mpeg4/MP4
开发平台:
Visual C++
- /**************************************************************************************
- * *
- * This application contains code from OpenDivX and is released as a "Larger Work" *
- * under that license. Consistant with that license, this application is released *
- * under the GNU General Public License. *
- * *
- * The OpenDivX license can be found at: http://www.projectmayo.com/opendivx/docs.php *
- * The GPL can be found at: http://www.gnu.org/copyleft/gpl.html *
- * *
- * Copyright (c) 2001 - Project Mayo *
- * *
- * Authors: Damien Chavarria <adrc at projectmayo.com> *
- * *
- **************************************************************************************/
- #include "AudioRenderer.h"
- /*
- * Class Functions
- *
- */
- /*
- * Constructor: Tries to init an IDirectDound object
- * and a secondary buffer for playback
- *
- */
- AudioRenderer::AudioRenderer(WAVEFORMATEX *inFormat, HWND hwnd)
- {
- this->lpDirectSound = NULL;
- this->lpBuffer = NULL;
- if(inFormat) {
- HRESULT hr;
- if(DirectSoundCreate(NULL, &this->lpDirectSound, NULL) == DS_OK) {
- /*
- * Set cooperative mode
- */
- hr = lpDirectSound->SetCooperativeLevel(hwnd, DSSCL_NORMAL);
- if(hr != DS_OK) {
- MessageBox(NULL, "Couldn't set sound mode!", "", MB_OK);
- return;
- }
- /*
- * Create the buffer
- */
- DSBUFFERDESC dsbdesc;
- WAVEFORMATEX wf;
- memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- ZeroMemory(&wf, sizeof(WAVEFORMATEX));
- memcpy(&wf, inFormat, sizeof(WAVEFORMATEX));
- dsbdesc.lpwfxFormat = (LPWAVEFORMATEX) &wf;
- dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS;
- dsbdesc.dwBufferBytes = 3 * inFormat->nAvgBytesPerSec;
- hr = lpDirectSound->CreateSoundBuffer(&dsbdesc, &lpBuffer, NULL);
- if(hr == DSERR_INVALIDPARAM) {
- char msg[70];
- sprintf(msg, "Cannot create sound buffer for %d, %d, %d!", inFormat->nChannels,
- inFormat->nSamplesPerSec, inFormat->wBitsPerSample);
- MessageBox(NULL, msg, "", MB_OK);
- return;
- }
- /*
- * here we're ok!
- */
- this->ourFormat = inFormat;
- this->dwBufferSize = 3 * inFormat->nAvgBytesPerSec;
- this->lInTimer = FALSE;
- }
- }
- }
- /*
- * Destructor : Cleanup.
- *
- */
- AudioRenderer::~AudioRenderer()
- {
- }
- /*
- * Sets the user-defined callback
- * fo filling the audio buffer
- *
- */
- int AudioRenderer::SetCallback(void *lpData, AudioCallback callback)
- {
- this->lpData = lpData;
- this->callback = callback;
- return 1;
- }
- /*
- * TODO : sets the volume
- *
- */
- int AudioRenderer::SetVolume(int volume)
- {
- if(this->lpBuffer) {
- double vol;
- vol = - ( 70*pow(10, (100.0 - (double) volume)*2.0/100.0) );
- if(this->lpBuffer != NULL)
- this->lpBuffer->SetVolume((int) vol);
- }
- return 1;
- }
- /*
- * Internal timer func for calling the
- * user-defined callback and fill the buffer
- *
- */
- void CALLBACK TimeFunc(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
- {
- AudioRenderer *audioRenderer = (AudioRenderer *) dwUser;
- if (InterlockedExchange(&audioRenderer->lInTimer, TRUE)) return;
- if(audioRenderer->callback) {
- void *buffer1, *buffer2;
- DWORD bytes1, bytes2;
- DWORD dwPlay, dwWrite;
- int dwPlayedLength;
- audioRenderer->lpBuffer->GetCurrentPosition(&dwPlay, &dwWrite);
- if( dwPlay == audioRenderer->dwNextWriteOffset ) {
- InterlockedExchange(&audioRenderer->lInTimer, FALSE);
- return;
- }
- if( dwPlay < audioRenderer->dwNextWriteOffset ) {
- dwPlayedLength = (dwPlay + audioRenderer->dwBufferSize - audioRenderer->dwNextWriteOffset);
- }
- else {
- dwPlayedLength = (dwPlay - audioRenderer->dwNextWriteOffset);
- }
- audioRenderer->dwProgress += dwPlayedLength;
- audioRenderer->lpBuffer->Lock(audioRenderer->dwNextWriteOffset, dwPlayedLength,
- &buffer1, &bytes1, &buffer2, &bytes2, 0);
- if(bytes1) {
- audioRenderer->callback(audioRenderer->lpData, buffer1, bytes1);
- }
- if(bytes2) {
- audioRenderer->callback(audioRenderer->lpData, buffer2, bytes2);
- }
- audioRenderer->lpBuffer->Unlock(buffer1, bytes1, buffer2, bytes2);
- audioRenderer->dwNextWriteOffset += (bytes1 + bytes2);
- if( audioRenderer->dwNextWriteOffset >= audioRenderer->dwBufferSize ) {
- audioRenderer->dwNextWriteOffset -= audioRenderer->dwBufferSize;
- }
- InterlockedExchange(&audioRenderer->lInTimer, FALSE);
- return;
- }
- }
- /*
- * Gives the exact number of milliseconds
- * of audio played since the call to Play()
- *
- */
- unsigned long AudioRenderer::AudioTime()
- {
- DWORD dwPlay, dwWrite;
- if(this->lpBuffer != NULL)
- this->lpBuffer->GetCurrentPosition(&dwPlay, &dwWrite);
- else
- return 0;
- if(dwPlay < this->dwLastPlayPos) {
- this->dwPlayed += ( (this->dwBufferSize - this->dwLastPlayPos) + dwPlay);
- }
- else {
- this->dwPlayed += (dwPlay - this->dwLastPlayPos);
- }
- this->dwLastPlayPos = dwPlay;
- return (unsigned long) (( ((double) this->dwPlayed * (1000/(this->ourFormat->wBitsPerSample*this->ourFormat->nChannels/8)))) / (this->ourFormat->nSamplesPerSec));
- }
- /*
- * Bufferize an entire buffer of data
- * this is used after seeking...
- */
- int AudioRenderer::Bufferize()
- {
- if(this->lpBuffer) {
- void *buffer1, *buffer2;
- DWORD bytes1, bytes2;
- /*
- * First bufferise some data
- */
- this->lpBuffer->SetCurrentPosition(0);
- this->lpBuffer->Lock(0, this->dwBufferSize,
- &buffer1, &bytes1, &buffer2, &bytes2, 0);
- this->callback(this->lpData, buffer1, bytes1);
- this->lpBuffer->Unlock(buffer1, bytes1, buffer2, bytes2);
- this->dwNextWriteOffset = this->dwProgress = this->dwPlayed = this->dwLastPlayPos = 0;
- }
- return 1;
- }
- /*
- * Starts the playback : Bufferize and
- * launch the thread.
- *
- */
- int AudioRenderer::Start()
- {
- if(this->lpBuffer) {
- void *buffer1, *buffer2;
- DWORD bytes1, bytes2;
- /*
- * First bufferise some data
- */
- this->lpBuffer->SetCurrentPosition(0);
- this->lpBuffer->Lock(0, this->dwBufferSize,
- &buffer1, &bytes1, &buffer2, &bytes2, 0);
- this->callback(this->lpData, buffer1, bytes1);
- this->lpBuffer->Unlock(buffer1, bytes1, buffer2, bytes2);
- this->dwNextWriteOffset = this->dwProgress = this->dwPlayed = this->dwLastPlayPos = 0;
- /*
- * Then start playing!
- */
- this->paused = 0;
- this->lpBuffer->Play(0, 0, DSBPLAY_LOOPING);
- if( timeBeginPeriod( 10 ) != 0 ) {
- return 0;
- }
- else {
- this->uTimerID = timeSetEvent( 10, 1, TimeFunc, (DWORD)(LPVOID)this, TIME_PERIODIC );
- }
- }
- return 1;
- }
- /*
- * Toggle Pause
- *
- */
- int AudioRenderer::Pause()
- {
- if(this->paused) {
- this->paused = 0;
- this->lpBuffer->Play(0, 0, DSBPLAY_LOOPING);
- this->uTimerID = timeSetEvent( 10, 1, TimeFunc, (DWORD)(LPVOID)this, TIME_PERIODIC );
- }
- else {
- if(this->uTimerID) {
- timeKillEvent(this->uTimerID);
- }
- this->paused = 1;
- this->lpBuffer->Stop();
- }
- return 1;
- }
- /*
- * Stops the playback
- * and timer
- *
- */
- int AudioRenderer::Stop()
- {
- if(this->uTimerID) {
- timeKillEvent(this->uTimerID);
- }
- if(this->lpBuffer) {
- this->lpBuffer->Stop();
- timeEndPeriod(10);
- }
- return 1;
- }
- /*
- * Closes propermy DSound.
- */
- int AudioRenderer::Close()
- {
- this->Stop();
- if(this->lpDirectSound) {
- if(this->lpBuffer)
- this->lpBuffer->Release();
- this->lpDirectSound->Release();
- }
- return 1;
- }