⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sound_win32.cxx

📁 pwlib源码库
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/* * sound.cxx * * Implementation of sound classes for Win32 * * Portable Windows Library * * Copyright (c) 1993-1998 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Portions are Copyright (C) 1993 Free Software Foundation, Inc. * All Rights Reserved. * * Contributor(s): ______________________________________. * * $Log: sound_win32.cxx,v $ * Revision 1.12  2005/07/03 13:48:58  shorne * Add the ability to play sound to specified device. * * Revision 1.11  2005/04/21 05:27:04  csoutheren * Prevent weird deadlocks when using record-only or play-only sound channels * * Revision 1.10  2005/01/04 07:44:04  csoutheren * More changes to implement the new configuration methodology, and also to * attack the global static problem * * Revision 1.9  2004/10/23 11:16:17  ykiryanov * Added ifdef _WIN32_WCE for PocketPC 2003 SDK port * * Revision 1.8  2004/08/16 06:41:00  csoutheren * Added adapters template to make device plugins available via the abstract factory interface * * Revision 1.7  2004/04/09 06:52:18  rjongbloed * Removed #pargma linker command for /delayload of DLL as documentations sais that *   you cannot do this. * * Revision 1.6  2004/02/23 23:52:20  csoutheren * Added pragmas to avoid every Windows application needing to include libs explicitly * * Revision 1.5  2004/02/15 03:59:20  rjongbloed * Fixed the default number of buffer to be the value determined emprirically in *    OpenH323, thanks Ted Szoczei * * Revision 1.4  2003/12/29 03:29:26  csoutheren * Allowed access to Windows sound channel declaration, just in case it is required * * Revision 1.3  2003/12/29 02:00:40  csoutheren * Moved some declarations to sound_win32.h to allow access * * Revision 1.2  2003/11/18 10:50:44  csoutheren * Changed name of Windows sound device * * Revision 1.1  2003/11/12 04:39:56  csoutheren * Changed to work with new plugin system * * Revision 1.37  2003/11/05 05:57:58  csoutheren * Added #pragma to include required libs * * Revision 1.36  2003/09/17 05:45:10  csoutheren * Removed recursive includes * * Revision 1.35  2003/06/05 05:20:35  rjongbloed * Fixed WinCE compatibility, thanks Yuri Kiryanov * * Revision 1.34  2003/05/29 08:57:38  rjongbloed * Futher changes to not alter balance when changing volume setting, also fixed *   correct return of volume level if balance not centred, thanks Diego T醨tara * * Revision 1.33  2003/05/01 00:17:40  robertj * Fixed setting of stereo volume levels, thanks Diego T醨tara * * Revision 1.32  2002/08/05 01:22:59  robertj * Fixed possible range error on SetVolume(), thanks Sonya Cooper-Hull * * Revision 1.31  2002/02/08 09:59:45  robertj * Slight adjustment to API and documentation for volume functions. * Added implementation for volume function on play, still needs recording. * * Revision 1.30  2002/02/07 20:57:21  dereks * add SetVolume and GetVolume methods to PSoundChannel * * Revision 1.29  2001/10/23 02:49:48  robertj * Fixed problem with Abort() not always breaking I/O blocked threads. * * Revision 1.28  2001/10/12 03:50:27  robertj * Fixed race condition on using Abort() which Reading from another thread. * Fixed failure to start recording if called WaitForXXXFull() functions. * * Revision 1.27  2001/10/10 03:29:34  yurik * Added open with format other than PCM * * Revision 1.26  2001/09/22 03:36:56  yurik * Put code to prevent audio channel disconnection * * Revision 1.25  2001/09/10 02:51:23  robertj * Major change to fix problem with error codes being corrupted in a *   PChannel when have simultaneous reads and writes in threads. * * Revision 1.24  2001/09/10 02:48:51  robertj * Removed previous change as breaks semantics of Read() function, moved test *   for zero buffer length to part that waits for buffer to be full. * * Revision 1.23  2001/09/09 17:37:49  yurik * dwBytesRecorded in WAVEHDR could return 0. We should not close the channel in this case * * Revision 1.22  2001/09/09 02:17:11  yurik * Returned to 1.20 * * Revision 1.20  2001/07/01 02:45:01  yurik * WinCE compiler wants implicit cast to format * * Revision 1.19  2001/05/04 09:38:07  robertj * Fixed problem with some WAV files having small WAVEFORMATEX chunk. * * Revision 1.18  2001/04/10 00:51:11  robertj * Fixed bug in using incorrect function to delete event handle, thanks Victor H. * * Revision 1.17  2001/03/15 23:39:29  robertj * Fixed bug with trying to write block larger than one buffer, thanks Norbert Oertel * * Revision 1.16  2001/02/07 04:45:54  robertj * Added functions to get current sound channel format parameters. * * Revision 1.15  2000/07/04 04:30:47  robertj * Fixed shutdown issues with buffers in use, again. * * Revision 1.14  2000/07/01 09:39:31  robertj * Fixed shutdown issues with buffers in use. * * Revision 1.13  2000/06/29 00:39:29  robertj * Fixed bug when PWaveFormat is assigned to itself. * * Revision 1.12  2000/05/22 07:17:50  robertj * Fixed missing initialisation of format data block in Win32 PSound::Load(). * * Revision 1.11  2000/05/01 05:59:11  robertj * Added mutex to PSoundChannel buffer structure. * * Revision 1.10  2000/03/04 10:15:32  robertj * Added simple play functions for sound files. * * Revision 1.9  2000/02/17 11:33:33  robertj * Changed PSoundChannel::Write so blocks instead of error if no buffers available. * * Revision 1.8  1999/10/09 01:22:07  robertj * Fixed error display for sound channels. * * Revision 1.7  1999/09/23 04:28:44  robertj * Allowed some Win32 only access to wave format in sound channel * * Revision 1.6  1999/07/08 08:39:53  robertj * Fixed bug when breaking block by closing the PSoundChannel in other thread. * * Revision 1.5  1999/06/24 14:01:25  robertj * Fixed bug in not returning correct default recorder (waveIn) device. * * Revision 1.4  1999/06/07 01:36:28  robertj * Fixed incorrect;ly set block alignment in sound structure. * * Revision 1.3  1999/05/28 14:04:51  robertj * Added function to get default audio device. * * Revision 1.2  1999/02/22 10:15:15  robertj * Sound driver interface implementation to Linux OSS specification. * * Revision 1.1  1999/02/16 06:02:07  robertj * Major implementation to Linux OSS model * */#define P_FORCE_STATIC_PLUGIN#include <ptlib.h>#if defined(_WIN32) && !defined(P_FORCE_STATIC_PLUGIN)#error "sound_win32.cxx must be compiled without precompiled headers"#endif#include <process.h>#include <ptlib/plugin.h>#include <ptlib/msos/ptlib/sound_win32.h>#ifndef _WIN32_WCE#pragma comment(lib, "winmm.lib")#endifclass PSound;PCREATE_SOUND_PLUGIN(WindowsMultimedia, PSoundChannelWin32);class PMultiMediaFile{  public:    PMultiMediaFile();    ~PMultiMediaFile();    BOOL CreateWaveFile(const PFilePath & filename,                        const PWaveFormat & waveFormat,                        DWORD dataSize);    BOOL OpenWaveFile(const PFilePath & filename,                      PWaveFormat & waveFormat,                      DWORD & dataSize);    BOOL Open(const PFilePath & filename, DWORD dwOpenFlags, LPMMIOINFO lpmmioinfo = NULL);    BOOL Close(UINT wFlags = 0);    BOOL Ascend(MMCKINFO & ckinfo, UINT wFlags = 0);    BOOL Descend(UINT wFlags, MMCKINFO & ckinfo, LPMMCKINFO lpckParent = NULL);    BOOL Read(void * data, PINDEX len);    BOOL CreateChunk(MMCKINFO & ckinfo, UINT wFlags = 0);    BOOL Write(const void * data, PINDEX len);    DWORD GetLastError() const { return dwLastError; }  protected:    HMMIO hmmio;    DWORD dwLastError;};#define new PNEW///////////////////////////////////////////////////////////////////////////////PMultiMediaFile::PMultiMediaFile(){  hmmio = NULL;}PMultiMediaFile::~PMultiMediaFile(){  Close();}BOOL PMultiMediaFile::CreateWaveFile(const PFilePath & filename,                                     const PWaveFormat & waveFormat,                                     DWORD dataSize){  if (!Open(filename, MMIO_CREATE|MMIO_WRITE))    return FALSE;  MMCKINFO mmChunk;  mmChunk.fccType = mmioFOURCC('W', 'A', 'V', 'E');  mmChunk.cksize = 4 + // Form type                   4 + sizeof(DWORD) + waveFormat.GetSize() + // fmt chunk                   4 + sizeof(DWORD) + dataSize;              // data chunk  // Create a RIFF chunk  if (!CreateChunk(mmChunk, MMIO_CREATERIFF))    return FALSE;  // Save the format sub-chunk  mmChunk.ckid = mmioFOURCC('f', 'm', 't', ' ');  mmChunk.cksize = waveFormat.GetSize();  if (!CreateChunk(mmChunk))    return FALSE;  if (!Write(waveFormat, waveFormat.GetSize()))    return FALSE;  // Save the data sub-chunk  mmChunk.ckid = mmioFOURCC('d', 'a', 't', 'a');  mmChunk.cksize = dataSize;  return CreateChunk(mmChunk);}BOOL PMultiMediaFile::OpenWaveFile(const PFilePath & filename,                                   PWaveFormat  & waveFormat,                                   DWORD & dataSize){  // Open wave file  if (!Open(filename, MMIO_READ | MMIO_ALLOCBUF))    return FALSE;  MMCKINFO mmParentChunk, mmSubChunk;  dwLastError = MMSYSERR_NOERROR;  // Locate a 'RIFF' chunk with a 'WAVE' form type  mmParentChunk.fccType = mmioFOURCC('W', 'A', 'V', 'E');  if (!Descend(MMIO_FINDRIFF, mmParentChunk))    return FALSE;  // Find the format chunk  mmSubChunk.ckid = mmioFOURCC('f', 'm', 't', ' ');  if (!Descend(MMIO_FINDCHUNK, mmSubChunk, &mmParentChunk))    return FALSE;  // Get the size of the format chunk, allocate memory for it  if (!waveFormat.SetSize(mmSubChunk.cksize))    return FALSE;  // Read the format chunk  if (!Read(waveFormat.GetPointer(), waveFormat.GetSize()))    return FALSE;  // Ascend out of the format subchunk  Ascend(mmSubChunk);  // Find the data subchunk  mmSubChunk.ckid = mmioFOURCC('d', 'a', 't', 'a');  if (!Descend(MMIO_FINDCHUNK, mmSubChunk, &mmParentChunk))    return FALSE;  // Get the size of the data subchunk  if (mmSubChunk.cksize == 0) {    dwLastError = MMSYSERR_INVALPARAM;    return FALSE;  }  dataSize = mmSubChunk.cksize;  return TRUE;}BOOL PMultiMediaFile::Open(const PFilePath & filename,                          DWORD dwOpenFlags,                          LPMMIOINFO lpmmioinfo){  MMIOINFO local_mmioinfo;  if (lpmmioinfo == NULL) {    lpmmioinfo = &local_mmioinfo;    memset(lpmmioinfo, 0, sizeof(local_mmioinfo));  }  hmmio = mmioOpen((char *)(const char *)filename, lpmmioinfo, dwOpenFlags);  dwLastError = lpmmioinfo->wErrorRet;  return hmmio != NULL;}BOOL PMultiMediaFile::Close(UINT wFlags){  if (hmmio == NULL)    return FALSE;  mmioClose(hmmio, wFlags);  hmmio = NULL;  return TRUE;}BOOL PMultiMediaFile::Ascend(MMCKINFO & ckinfo, UINT wFlags){  dwLastError = mmioAscend(hmmio, &ckinfo, wFlags);  return dwLastError == MMSYSERR_NOERROR;}BOOL PMultiMediaFile::Descend(UINT wFlags, MMCKINFO & ckinfo, LPMMCKINFO lpckParent){  dwLastError = mmioDescend(hmmio, &ckinfo, lpckParent, wFlags);  return dwLastError == MMSYSERR_NOERROR;}BOOL PMultiMediaFile::Read(void * data, PINDEX len){  return mmioRead(hmmio, (char *)data, len) == len;}BOOL PMultiMediaFile::CreateChunk(MMCKINFO & ckinfo, UINT wFlags){  dwLastError = mmioCreateChunk(hmmio, &ckinfo, wFlags);  return dwLastError == MMSYSERR_NOERROR;}BOOL PMultiMediaFile::Write(const void * data, PINDEX len){  return mmioWrite(hmmio, (char *)data, len) == len;}///////////////////////////////////////////////////////////////////////////////PWaveFormat::PWaveFormat(){  size = 0;  waveFormat = NULL;}PWaveFormat::~PWaveFormat(){  if (waveFormat != NULL)    free(waveFormat);}PWaveFormat::PWaveFormat(const PWaveFormat & fmt){  size = fmt.size;  waveFormat = (WAVEFORMATEX *)malloc(size);  PAssert(waveFormat != NULL, POutOfMemory);  memcpy(waveFormat, fmt.waveFormat, size);}PWaveFormat & PWaveFormat::operator=(const PWaveFormat & fmt){  if (this == &fmt)    return *this;  if (waveFormat != NULL)    free(waveFormat);  size = fmt.size;  waveFormat = (WAVEFORMATEX *)malloc(size);  PAssert(waveFormat != NULL, POutOfMemory);  memcpy(waveFormat, fmt.waveFormat, size);  return *this;}void PWaveFormat::PrintOn(ostream & out) const{  if (waveFormat == NULL)    out << "<null>";  else {    out << waveFormat->wFormatTag << ','        << waveFormat->nChannels << ','        << waveFormat->nSamplesPerSec << ','        << waveFormat->nAvgBytesPerSec << ','        << waveFormat->nBlockAlign << ','        << waveFormat->wBitsPerSample;    if (waveFormat->cbSize > 0) {      out << hex << setfill('0');      const BYTE * ptr = (const BYTE *)&waveFormat[1];      for (PINDEX i = 0; i < waveFormat->cbSize; i++)        out << ',' << setw(2) << (unsigned)*ptr++;      out << dec << setfill(' ');    }  }}void PWaveFormat::ReadFrom(istream &){}void PWaveFormat::SetFormat(unsigned numChannels,                            unsigned sampleRate,                            unsigned bitsPerSample){  PAssert(numChannels == 1 || numChannels == 2, PInvalidParameter);  PAssert(bitsPerSample == 8 || bitsPerSample == 16, PInvalidParameter);  if (waveFormat != NULL)    free(waveFormat);  size = sizeof(WAVEFORMATEX);  waveFormat = (WAVEFORMATEX *)malloc(sizeof(WAVEFORMATEX));  PAssert(waveFormat != NULL, POutOfMemory);  waveFormat->wFormatTag = WAVE_FORMAT_PCM;  waveFormat->nChannels = (WORD)numChannels;  waveFormat->nSamplesPerSec = sampleRate;  waveFormat->wBitsPerSample = (WORD)bitsPerSample;  waveFormat->nBlockAlign = (WORD)(numChannels*(bitsPerSample+7)/8);  waveFormat->nAvgBytesPerSec = waveFormat->nSamplesPerSec*waveFormat->nBlockAlign;  waveFormat->cbSize = 0;}void PWaveFormat::SetFormat(const void * data, PINDEX size){  SetSize(size);  memcpy(waveFormat, data, size);}BOOL PWaveFormat::SetSize(PINDEX sz){  if (waveFormat != NULL)    free(waveFormat);  size = sz;  if (sz == 0)    waveFormat = NULL;  else {    if (sz < sizeof(WAVEFORMATEX))      sz = sizeof(WAVEFORMATEX);    waveFormat = (WAVEFORMATEX *)calloc(sz, 1);    waveFormat->cbSize = (WORD)(sz - sizeof(WAVEFORMATEX));  }  return waveFormat != NULL;}///////////////////////////////////////////////////////////////////////////////PSound::PSound(unsigned channels,               unsigned samplesPerSecond,               unsigned bitsPerSample,               PINDEX   bufferSize,               const BYTE * buffer){  encoding = 0;  numChannels = channels;  sampleRate = samplesPerSecond;  sampleSize = bitsPerSample;  SetSize(bufferSize);  if (buffer != NULL)    memcpy(GetPointer(), buffer, bufferSize);}PSound::PSound(const PFilePath & filename){  encoding = 0;  numChannels = 1;  sampleRate = 8000;  sampleSize = 16;  Load(filename);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -