Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
AudioPlayer.cpp
Package: gloop.zip [view]
Upload User: shxiangxiu
Upload Date: 2007-01-03
Package Size: 1101k
Code Size: 18k
Category:
OpenGL program
Development Platform:
Visual C++
- /////////////////////////////////////////////////////////////////////////////
- // AudioPlayer.cpp : implementation file
- //
- // glOOP (OpenGL Object Oriented Programming library)
- // Copyright (c) Craig Fahrnbach 1997, 1998
- //
- // OpenGL is a registered trademark of Silicon Graphics
- //
- //
- // This program is provided for educational and personal use only and
- // is provided without guarantee or warrantee expressed or implied.
- //
- // Commercial use is strickly prohibited without written permission
- // from ImageWare Development.
- //
- // This program is -not- in the public domain.
- //
- /////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "glOOP.h"
- #include "DIBUtil.h"
- #include <mmsystem.h>
- #include <time.h>
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CAudioPlayer Global definitions
- // Since we can only have one audio device playing at any time, we declare a few
- // global variable
- BOOL g_bDeviceIsBusy = FALSE; // Audio device flag
- long g_lSample; // Position, in samples, of the avi audio read stream
- long g_lNumSamples; // Number of audio samples in the avi audio stream
- HWAVEOUT g_hWaveOut; // Handle identifying the open waveform-audio output device.
- // Our multi-media timer callback procedure
- static void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD dwUser,
- DWORD dw1, DWORD dw2)
- {
- // The multi-media timer has timed out. Write the wave header to the audio
- // device. The waveOutWrite function returns immediately and waveform data
- // is sent to the output device in the background. If the audio device queue
- // is empty, playback begins immediatly, otherwise the wave header is placed
- // in the queue.
- waveOutWrite(g_hWaveOut, (LPWAVEHDR)dwUser, sizeof(WAVEHDR));
- }
- // Our audio device callback procedure
- static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance,
- DWORD dwParam1, DWORD dwParam2)
- {
- CAudioPlayer* pAudioPlayer;
- pAudioPlayer = (CAudioPlayer*) dwInstance;
- ASSERT(pAudioPlayer);
- if(uMsg == WOM_DONE && pAudioPlayer->m_bPlayAudioClip)
- {
- // The audio device has finished playing the wave header data, so get the next
- // audio 'chunk'.
- pAudioPlayer->GetWaveformData(pAudioPlayer, (LPWAVEHDR)dwParam1);
- // Start a multi-media timer, which when expired, will call our waveOutWrite
- // function. We cannot call the waveOutWrite function here, since, per the
- // waveOutProc documentation: Calling other wave functions will cause deadlock.
- timeSetEvent(10, // Event delay, in milliseconds.
- 10, // Resolution of the timer event, in milliseconds.
- &TimeProc, // Address of the callback function
- dwParam1, // User supplied callback data (pointer to our wavehdr)
- TIME_ONESHOT); // Trigger event once, after uDelay milliseconds.
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // CAudioPlayer
- IMPLEMENT_DYNAMIC(CAudioPlayer, CObject)
- /////////////////////////////////////////////////////////////////////////////
- // CAudioPlayer construction
- CAudioPlayer* CAudioPlayer::Create(LPSTR pszFileName)
- {
- UINT wResult; // Return error code
- if(!pszFileName)
- return NULL;
- // TODO: Add file extension check for formats other than .avi
- CAudioPlayer* pAudioPlayer = new CAudioPlayer;
- ASSERT(pAudioPlayer);
- wResult = pAudioPlayer->InitAVI(pszFileName);
- if(wResult)
- {
- delete pAudioPlayer;
- return (NULL);
- }
- return (pAudioPlayer);
- }
- CAudioPlayer::CAudioPlayer()
- {
- int i;
- m_bPlayAudioClip = FALSE; // Flag for this Audio clip
- m_bDeviceOpen = FALSE; // Audio device not opened
- m_bSynchAudio = FALSE; // Resynchronize audio stream
- m_pAudioStream = NULL; // Pointer to the AVI Audio stream interface.
- m_dwDataSize = 0L; // Size of our audio data buffer
- m_iWBufferScale = 4; // Audio write buffer scale size
- for(i=0; i<WRITE_BUFFERS; i++)
- {
- // Clear our audio data buffer handles and pointers
- m_hAudioData[i] = NULL; // Handle of waveform data memory
- m_lpAudioData[i] = NULL; // Pointer to waveform data memory
- // Clear our wave header handles and pointers
- m_hWaveHdr[i] = NULL; // Handle to waveform data block header
- m_lpWaveHdr[i] = NULL; // Pointer to waveform data block header
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // CAudioPlayer Destructor
- CAudioPlayer::~CAudioPlayer()
- {
- int i;
- if(m_bDeviceOpen)
- {
- Close(); // Close the audio device;
- // End streaming
- AVIStreamEndStreaming(m_pAudioStream);
- for(i=0; i<WRITE_BUFFERS; i++)
- {
- // Clean up the preparation performed by the waveOutPrepareHeader
- // function before we free the header..
- waveOutUnprepareHeader(g_hWaveOut, m_lpWaveHdr[i], sizeof(WAVEHDR));
- // Free the waveform data block header
- if(m_hWaveHdr[i])
- {
- GlobalUnlock(m_hWaveHdr[i]);
- GlobalFree(m_hWaveHdr[i]);
- m_hWaveHdr[i] = NULL;
- m_lpWaveHdr[i] = NULL;
- }
- // Free the waveform data memory block
- if(m_hAudioData[i])
- {
- GlobalUnlock(m_hAudioData[i]);
- GlobalFree(m_hAudioData[i]);
- m_hAudioData[i] = NULL;
- m_lpAudioData[i] = NULL;
- }
- }
- // Clear the handle of the wave out audio device
- g_hWaveOut = NULL;
- // Clear the audio stream pointer
- m_pAudioStream = NULL;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // CAudioPlayer AVI type specific function implementation
- void CAudioPlayer::GetAviWaveformData(LPVOID pInstance, LPWAVEHDR lpWaveHdr)
- {
- UINT wResult; // Return error code
- long lBytes;
- long lSamples;
- CAudioPlayer* pAudioPlayer;
- pAudioPlayer = (CAudioPlayer*) pInstance;
- ASSERT(pAudioPlayer);
- if(pAudioPlayer->m_bSynchAudio)
- {
- clock_t current;
- double dDuration;
- long lTimeOffset;
- // Reset the flag
- pAudioPlayer->m_bSynchAudio = FALSE;
- // Get the current time
- current = clock();
- // Calculate the time offset and ADD to our stream sample index
- dDuration = (double)(current - pAudioPlayer->m_SynchTime) / CLOCKS_PER_SEC;
- lTimeOffset = (long)(dDuration/1000.f);
- g_lSample +=lTimeOffset;
- }
- // Read the waveform data 'chunk' from the stream
- wResult = AVIStreamRead(pAudioPlayer->m_pAudioStream,
- g_lSample,
- pAudioPlayer->m_dwDataSize,
- lpWaveHdr->lpData,
- pAudioPlayer->m_dwDataSize,
- &lBytes,
- &lSamples);
- if(wResult)
- return;
- // Increment the stream sample index and ensure that it does not extend beyond
- // the number of samples in the stream (Note that this will wrap the sample
- // index back to the beginning of the stream if necessary..)
- g_lSample = (g_lSample += lSamples) % g_lNumSamples;
- }
- DWORD CAudioPlayer::InitAVI(LPSTR pszFileName)
- {
- AVISTREAMINFO FAR psi; // AVI Stream Info header pointer
- UINT wResult; // Return error code
- if(m_pAudioStream)
- return (1); // Should initilize the device only once!
- // Try to open the AVI audio stream
- wResult = AVIStreamOpenFromFile(&m_pAudioStream,
- pszFileName,
- streamtypeAUDIO,
- 0,
- OF_READ,
- NULL);
- if(wResult)
- return (wResult); // return error
- // Get the length and number of samples in the audio stream
- m_lAudioLength = AVIStreamLengthTime(m_pAudioStream);
- g_lNumSamples = AVIStreamLength(m_pAudioStream);
- // Fill the AVISTREAMINFO structure information for this stream
- AVIStreamInfo(m_pAudioStream, &psi, sizeof(AVISTREAMINFO FAR));
- // Save the size of the audio data block. We use the SuggestedBuffer
- // size and multiply by our buffer scaling factor.
- // Note: for optimum performance, our buffer should be aprox. 500 ms in size..
- m_dwDataSize = psi.dwSuggestedBufferSize * m_iWBufferScale;
- // Fill the waveform-audio data structure
- // m_WFX.wFormatTag = WAVE_FORMAT_PCM;
- // m_WFX.nChannels = 2;
- // m_WFX.nSamplesPerSec = psi.dwRate/psi.dwScale;
- // m_WFX.nAvgBytesPerSec = m_WFX.nSamplesPerSec*m_WFX.nChannels;
- // m_WFX.nBlockAlign = (unsigned short)psi.dwSampleSize;
- // m_WFX.wBitsPerSample = 8;
- // m_WFX.cbSize = 0;
- // Read the WAVEFORMATEX settings from the audio stream
- long sizeofWFX = sizeof(WAVEFORMATEX);
- wResult = AVIStreamReadFormat(m_pAudioStream,
- AVIStreamTimeToSample(m_pAudioStream, 0L),
- &m_WFX,
- &sizeofWFX);
- if(wResult)
- return (wResult); // return error
- // Set the GetWaveformData function pointer to point to the
- // appropriate static procedure..
- GetWaveformData = CAudioPlayer::GetAviWaveformData;
- // Now that we have the AVI specific audio 'stuff' initialized,
- // allocate memory for our audio data and wave header
- return( Initialize() );
- }
- /////////////////////////////////////////////////////////////////////////////
- // CAudioPlayer generic function implementation
- DWORD CAudioPlayer::Initialize()
- {
- int i;
- for(i=0; i<WRITE_BUFFERS; i++)
- {
- // Allocate and lock memory for the audio data block
- m_hAudioData[i] = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, m_dwDataSize );
- if (!m_hAudioData[i])
- {
- AfxMessageBox("CAudioPlayer::Initialize - Out of memory.",
- MB_OK | MB_ICONEXCLAMATION);
- return (1); // return error
- }
- if ((m_lpAudioData[i] = (HPSTR)GlobalLock(m_hAudioData[i])) == NULL)
- {
- AfxMessageBox("CAudioPlayer::Initialize - Failed to lock memory for data chunk.",
- MB_OK | MB_ICONEXCLAMATION);
- GlobalFree(m_hAudioData[i]);
- m_hAudioData[i] = NULL;
- return (1); // return error
- }
- // Allocate and lock memory for the header.
- m_hWaveHdr[i] = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
- (DWORD) sizeof(WAVEHDR));
- if (m_hWaveHdr[i] == NULL)
- {
- GlobalUnlock(m_hAudioData[i]);
- GlobalFree(m_hAudioData[i]);
- AfxMessageBox("CAudioPlayer::Initialize - Not enough memory for header.",
- MB_OK | MB_ICONEXCLAMATION);
- return (1); // return error
- }
- m_lpWaveHdr[i] = (LPWAVEHDR) GlobalLock(m_hWaveHdr[i]);
- if (m_lpWaveHdr[i] == NULL)
- {
- GlobalUnlock(m_hAudioData[i]);
- GlobalFree(m_hAudioData[i]);
- AfxMessageBox("CAudioPlayer::Initialize - Failed to lock memory for header.",
- MB_OK | MB_ICONEXCLAMATION);
- GlobalFree(m_hWaveHdr[i]);
- m_hWaveHdr[i] = NULL;
- return (1); // return error
- }
- }
- return (0); // No errors
- }
- DWORD CAudioPlayer::Open(LPSTR pszFileName)
- {
- UINT wResult; // Return error code
- // If the audio device is busy (playing another file)
- // return error
- if(g_bDeviceIsBusy)
- return (1);
- // Try to open the AVI audio stream
- wResult = AVIStreamOpenFromFile(&m_pAudioStream,
- pszFileName,
- streamtypeAUDIO,
- 0,
- OF_READ,
- NULL);
- if(wResult)
- return (wResult); // return error
- // Open the audio device
- wResult = waveOutOpen(&g_hWaveOut,
- WAVE_MAPPER, // select a waveform-audio output device
- // capable of playing the given format.
- &m_WFX,
- (DWORD)&waveOutProc, // Callback procedure
- (DWORD)this, // CallbackInstance,
- CALLBACK_FUNCTION |
- WAVE_ALLOWSYNC);
- if(wResult)
- {
- // If an error occurred, display the error message
- DisplayError(wResult);
- return (wResult); // return error
- }
- // This CAudioPlayer class instance has the audio device open
- m_bDeviceOpen = TRUE;
- // Set the global flag (Audio device busy)
- g_bDeviceIsBusy = TRUE;
- return (0); // No errors
- }
- DWORD CAudioPlayer::Close()
- {
- UINT wResult; // Return error code
- int iWait = 0;
- if(m_bPlayAudioClip && m_bDeviceOpen)
- {
- m_bPlayAudioClip = FALSE; // Disable the audio track
- // Wait for the audio 'chunck' to finish
- while(!m_lpWaveHdr[0]->dwFlags & WHDR_DONE)
- {
- // Let's wait for the device to finish. Just so
- // we don't get caught in this loop forever, increment
- // a wait counter and abort if exceeded.
- Sleep(100);
- ++iWait;
- if(iWait > 20) // Max 2 second delay
- break;
- }
- }
- // Close the waveform-audio output device
- if(g_hWaveOut)
- {
- wResult = waveOutReset(g_hWaveOut); // Reset the audio device
- if(!wResult)
- {
- wResult = waveOutClose(g_hWaveOut); // Close the audio device
- if(!wResult)
- {
- m_bDeviceOpen = FALSE;
- g_bDeviceIsBusy = FALSE;
- }
- }
- }
- return (wResult);
- }
- DWORD CAudioPlayer::Play(double dTime)
- {
- // The Play() procedure converts the requested start time to correspond to
- // the stream sample requested, formats the Wave Write Header, prepares the
- // header for writing, gets the audio data from the stream and writes the
- // data to the audio device. We use two write buffers to ensure that the
- // audio is played without 'gaps' by initially writing both buffers to the
- // audio device. Once the audio chunk has been played, our WaveOutProc()
- // takes care of getting the next audio chunk and sending to the device.
- //
- // Note that this procedure just gets things going...
- //
- UINT wResult; // Return error code
- long lTime; // Converted time value to long (milliseconds)
- if(!m_bPlayAudioClip && m_bDeviceOpen)
- {
- m_bPlayAudioClip = TRUE;
- int i;
- // Convert the requested start time to samples, in milliseconds.
- lTime = (long)((int)(dTime*1000) % m_lAudioLength);
- // Get the starting sample
- g_lSample = AVIStreamTimeToSample(m_pAudioStream, lTime);
- for(i=0; i<WRITE_BUFFERS; i++)
- {
- // To ensure that our audio stream is played without 'gaps', we need at
- // least two (2) audio write buffers. Format the wave headers
- m_lpWaveHdr[i]->dwBufferLength = m_dwDataSize;
- m_lpWaveHdr[i]->lpData = m_lpAudioData[i];
- m_lpWaveHdr[i]->dwFlags = 0L;
- m_lpWaveHdr[i]->dwLoops = 0L;
- // Prepare the waveform-audio data block for playback.
- wResult = waveOutPrepareHeader(g_hWaveOut, m_lpWaveHdr[i], sizeof(WAVEHDR));
- if(wResult)
- {
- // If an error occurred, display the error message
- DisplayError(wResult);
- return (wResult); // return error
- }
- // Get the waveform audio data
- GetWaveformData(this, m_lpWaveHdr[i]);
- // Now the data block can be sent to the output device. The
- // waveOutWrite function returns immediately and waveform
- // data is sent to the output device in the background.
- // If the audio device queue is empty, playback begins immediatly,
- // otherwise the wave header is placed in the queue.
- wResult = waveOutWrite(g_hWaveOut, m_lpWaveHdr[i], sizeof(WAVEHDR));
- if(wResult)
- {
- // If an error occurred, display the error message
- DisplayError(wResult);
- return (wResult); // return error
- }
- }
- return (wResult);
- }
- return (1); // Audio already playing or opened by another device..
- }
- DWORD CAudioPlayer::Stop()
- {
- return (Close());
- }
- DWORD CAudioPlayer::GetVolumn(LPDWORD lpdwVolumn)
- {
- UINT wResult; // Return error code
- // UINT uDeviceID; // Audio device ID
- // AUXCAPS Caps; // Structure which describes the audio device capabilities
- /*
- wResult = waveOutGetID(g_hWaveOut, (LPUINT)&uDeviceID);
- if(wResult)
- return (wResult); // Return error code
- wResult = auxGetDevCaps(uDeviceID, &Caps, sizeof(AUXCAPS));
- if(wResult)
- return (wResult); // Return error code
- if(Caps.dwSupport & AUXCAPS_VOLUME)
- {
- // Device supports Volumn control
- wResult = auxGetVolume(uDeviceID, lpdwVolumn);
- if(wResult)
- return (wResult); // Return error code
- }
- */
- // Device supports Volumn control
- wResult = waveOutGetVolume(g_hWaveOut, lpdwVolumn);
- if(wResult)
- return (wResult); // Return error code
- return (0);
- }
- DWORD CAudioPlayer::SetVolumn(DWORD dwVolumn)
- {
- UINT wResult; // Return error code
- // UINT uDeviceID; // Audio device ID
- // AUXCAPS Caps; // Structure which describes the audio device capabilities
- /*
- wResult = waveOutGetID(g_hWaveOut, &uDeviceID);
- if(wResult)
- return (wResult); // Return error code
- wResult = auxGetDevCaps(uDeviceID, &Caps, sizeof(AUXCAPS));
- if(wResult)
- return (wResult); // Return error code
- if(Caps.dwSupport & AUXCAPS_VOLUME)
- {
- // Device supports Volumn control
- wResult = auxSetVolume(uDeviceID, dwVolumn);
- if(wResult)
- return (wResult); // Return error code
- }
- */
- // Device supports Volumn control
- wResult = waveOutSetVolume(g_hWaveOut, dwVolumn);
- if(wResult)
- return (wResult); // Return error code
- return (0);
- }
- DWORD CAudioPlayer::GetPitch(LPDWORD lpdwPitch)
- {
- UINT wResult; // Return error code
- // Get the audio device's pitch or playback rate
- wResult = waveOutGetPitch(g_hWaveOut, lpdwPitch);
- if(wResult)
- return (wResult); // Return error code
- return (0);
- }
- DWORD CAudioPlayer::SetPitch(DWORD dwPitch)
- {
- UINT wResult; // Return error code
- // Set the audio device's pitch or playback rate
- wResult = waveOutSetPitch(g_hWaveOut, dwPitch);
- if(wResult)
- return (wResult); // Return error code
- return (0);
- }
- void CAudioPlayer::SynchAudio(double dTime)
- {
- // Set the Resynch flag and get the time of the request
- m_bSynchAudio = TRUE;
- m_SynchTime = clock();
- }
- void CAudioPlayer::DisplayError(UINT wError)
- {
- char buffer[128];
- switch (wError)
- {
- case MMSYSERR_ALLOCATED:
- sprintf(buffer, "CAudioPlayer - Specified resource is already allocated.");
- case MMSYSERR_BADDEVICEID:
- sprintf(buffer, "CAudioPlayer - Specified device identifier is out of range.");
- case WAVERR_BADFORMAT:
- sprintf(buffer, "CAudioPlayer - Attempted to open with an unsupported waveform-audio format.");
- case WAVERR_SYNC:
- sprintf(buffer, "CAudioPlayer - The device is synchronous but waveOutOpen was called without using the WAVE_ALLOWSYNC flag.");
- case MMSYSERR_INVALHANDLE:
- sprintf(buffer, "CAudioPlayer - Specified device handle is invalid.");
- case MMSYSERR_NODRIVER:
- sprintf(buffer, "CAudioPlayer - No device driver is present.");
- case MMSYSERR_NOMEM:
- sprintf(buffer, "CAudioPlayer - Unable to allocate or lock memory.");
- case WAVERR_UNPREPARED:
- sprintf(buffer, "CAudioPlayer - The data block pointed to by the pwh parameter hasn't been prepared.");
- default:
- sprintf(buffer, "CAudioPlayer - UnDefined error.");
- }
- AfxMessageBox(buffer, MB_OK | MB_ICONEXCLAMATION);
- }