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

📄 sound_win32.cxx

📁 pwlib源码库
💻 CXX
📖 第 1 页 / 共 3 页
字号:
PSound & PSound::operator=(const PBYTEArray & data){  PBYTEArray::operator=(data);  return *this;}void PSound::SetFormat(unsigned channels,                       unsigned samplesPerSecond,                       unsigned bitsPerSample){  encoding = 0;  numChannels = channels;  sampleRate = samplesPerSecond;  sampleSize = bitsPerSample;  formatInfo.SetSize(0);}BOOL PSound::Load(const PFilePath & filename){  // Open wave file  PMultiMediaFile mmio;  PWaveFormat waveFormat;  DWORD dataSize;  if (!mmio.OpenWaveFile(filename, waveFormat, dataSize)) {    dwLastError = mmio.GetLastError();    return FALSE;  }  encoding = waveFormat->wFormatTag;  numChannels = waveFormat->nChannels;  sampleRate = waveFormat->nSamplesPerSec;  sampleSize = waveFormat->wBitsPerSample;  if (encoding != 0) {    PINDEX formatSize = waveFormat->cbSize + sizeof(WAVEFORMATEX);    memcpy(formatInfo.GetPointer(formatSize), waveFormat, formatSize);  }  // Allocate and lock memory for the waveform data.  if (!SetSize(dataSize)) {    dwLastError = MMSYSERR_NOMEM;    return FALSE;  }  // Read the waveform data subchunk  if (!mmio.Read(GetPointer(), GetSize())) {    dwLastError = mmio.GetLastError();    return FALSE;  }  return TRUE;}BOOL PSound::Save(const PFilePath & filename){  PWaveFormat waveFormat;  if (encoding == 0)    waveFormat.SetFormat(numChannels, sampleRate, sampleSize);  else {    waveFormat.SetSize(GetFormatInfoSize());    memcpy(waveFormat.GetPointer(), GetFormatInfoData(), GetFormatInfoSize());  }  // Open wave file  PMultiMediaFile mmio;  if (!mmio.CreateWaveFile(filename, waveFormat, GetSize())) {    dwLastError = mmio.GetLastError();    return FALSE;  }  if (!mmio.Write(GetPointer(), GetSize())) {    dwLastError = mmio.GetLastError();    return FALSE;  }  return TRUE;}BOOL PSound::Play(){  PSoundChannel channel(PSoundChannel::GetDefaultDevice(PSoundChannel::Player),                        PSoundChannel::Player);  if (!channel.IsOpen())    return FALSE;  return channel.PlaySound(*this, TRUE);}BOOL PSound::Play(const PString & device){  PSoundChannel channel(device,                       PSoundChannel::Player);  if (!channel.IsOpen())    return FALSE;  return channel.PlaySound(*this, TRUE);}BOOL PSound::PlayFile(const PFilePath & file, BOOL wait){  return ::PlaySound(file, NULL, SND_FILENAME|(wait ? SND_SYNC : SND_ASYNC));}///////////////////////////////////////////////////////////////////////////////PWaveBuffer::PWaveBuffer(PINDEX sz) : PBYTEArray(sz){  hWaveOut = NULL;  hWaveIn = NULL;  header.dwFlags = WHDR_DONE;}PWaveBuffer::~PWaveBuffer(){  Release();}PWaveBuffer & PWaveBuffer::operator=(const PSound & sound){  PBYTEArray::operator=(sound);  return *this;}void PWaveBuffer::PrepareCommon(PINDEX count){  Release();  memset(&header, 0, sizeof(header));  header.lpData = (char *)GetPointer();  header.dwBufferLength = count;  header.dwUser = (DWORD)this;}DWORD PWaveBuffer::Prepare(HWAVEOUT hOut, PINDEX & count){  // Set up WAVEHDR structure and prepare it to be written to wave device  if (count > GetSize())    count = GetSize();  PrepareCommon(count);  hWaveOut = hOut;  return waveOutPrepareHeader(hWaveOut, &header, sizeof(header));}DWORD PWaveBuffer::Prepare(HWAVEIN hIn){  // Set up WAVEHDR structure and prepare it to be read from wave device  PrepareCommon(GetSize());  hWaveIn = hIn;  return waveInPrepareHeader(hWaveIn, &header, sizeof(header));}DWORD PWaveBuffer::Release(){  DWORD err = MMSYSERR_NOERROR;  // There seems to be some pathalogical cases where on an Abort() call the buffers  // still are "in use", even though waveOutReset() was called. So wait until the  // sound driver has finished with the buffer before releasing it.  if (hWaveOut != NULL) {    if ((err = waveOutUnprepareHeader(hWaveOut, &header, sizeof(header))) == WAVERR_STILLPLAYING)      return err;    hWaveOut = NULL;  }  if (hWaveIn != NULL) {    if ((err = waveInUnprepareHeader(hWaveIn, &header, sizeof(header))) == WAVERR_STILLPLAYING)      return err;    hWaveIn = NULL;  }  header.dwFlags |= WHDR_DONE;  return err;}///////////////////////////////////////////////////////////////////////////////PSoundChannelWin32::PSoundChannelWin32(){  Construct();}PSoundChannelWin32::PSoundChannelWin32(const PString & device,                             Directions dir,                             unsigned numChannels,                             unsigned sampleRate,                             unsigned bitsPerSample){  Construct();  Open(device, dir, numChannels, sampleRate, bitsPerSample);}void PSoundChannelWin32::Construct(){  direction = Player;  hWaveOut = NULL;  hWaveIn = NULL;  hEventDone = CreateEvent(NULL, FALSE, FALSE, NULL);  waveFormat.SetFormat(1, 8000, 16);  bufferByteOffset = P_MAX_INDEX;  SetBuffers(32768, 3);}PSoundChannelWin32::~PSoundChannelWin32(){  Close();  if (hEventDone != NULL)    CloseHandle(hEventDone);}PString PSoundChannelWin32::GetName() const{  return deviceName;}PStringArray PSoundChannelWin32::GetDeviceNames(Directions dir){  PStringArray array;  unsigned numDevs, id;  switch (dir) {    case Player :      numDevs = waveOutGetNumDevs();      for (id = 0; id < numDevs; id++) {        WAVEOUTCAPS caps;        if (waveOutGetDevCaps(id, &caps, sizeof(caps)) == 0)          array[array.GetSize()] = caps.szPname;      }      break;    case Recorder :      numDevs = waveInGetNumDevs();      for (id = 0; id < numDevs; id++) {        WAVEINCAPS caps;        if (waveInGetDevCaps(id, &caps, sizeof(caps)) == 0)          array[array.GetSize()] = caps.szPname;      }      break;  }  return array;}PString PSoundChannelWin32::GetDefaultDevice(Directions dir){  RegistryKey registry("HKEY_CURRENT_USER\\Software\\Microsoft\\Multimedia\\Sound Mapper",                       RegistryKey::ReadOnly);  PString str;  if (dir == Player) {    if (!registry.QueryValue("Playback", str)) {      WAVEOUTCAPS caps;      if (waveOutGetDevCaps(0, &caps, sizeof(caps)) == 0)        str = caps.szPname;    }  }  else {    if (!registry.QueryValue("Record", str)) {      WAVEINCAPS caps;      if (waveInGetDevCaps(0, &caps, sizeof(caps)) == 0)        str = caps.szPname;    }  }  return str;}BOOL PSoundChannelWin32::GetDeviceID(const PString & device, Directions dir, unsigned& id){  BOOL bad = TRUE;  if (device[0] == '#') {    id = device.Mid(1).AsUnsigned();    switch (dir) {      case Player :        if (id < waveOutGetNumDevs()) {          WAVEOUTCAPS caps;          if (waveOutGetDevCaps(id, &caps, sizeof(caps)) == 0) {            deviceName = caps.szPname;            bad = FALSE;          }        }        break;      case Recorder :        if (id < waveInGetNumDevs()) {          WAVEINCAPS caps;          if (waveInGetDevCaps(id, &caps, sizeof(caps)) == 0) {            deviceName = caps.szPname;            bad = FALSE;          }        }        break;    }  }  else {    switch (dir) {      case Player :        for (id = 0; id < waveOutGetNumDevs(); id++) {          WAVEOUTCAPS caps;          if (waveOutGetDevCaps(id, &caps, sizeof(caps)) == 0 &&              stricmp(caps.szPname, device) == 0) {            deviceName = caps.szPname;            bad = FALSE;            break;          }        }        break;      case Recorder :        for (id = 0; id < waveInGetNumDevs(); id++) {          WAVEINCAPS caps;          if (waveInGetDevCaps(id, &caps, sizeof(caps)) == 0 &&              stricmp(caps.szPname, device) == 0) {            deviceName = caps.szPname;            bad = FALSE;            break;          }        }        break;    }  }  if (bad)    return SetErrorValues(NotFound, MMSYSERR_BADDEVICEID|PWIN32ErrorFlag);  return TRUE;}BOOL PSoundChannelWin32::Open(const PString & device,                         Directions dir,                         unsigned numChannels,                         unsigned sampleRate,                         unsigned bitsPerSample){  Close();  unsigned id = 0;	  if( !GetDeviceID(device, dir, id) )	  return FALSE;  waveFormat.SetFormat(numChannels, sampleRate, bitsPerSample);  direction = dir;  return OpenDevice(id);}BOOL PSoundChannelWin32::Open(const PString & device,                         Directions dir,						 const PWaveFormat& format){  Close();  unsigned id = 0;	  if( !GetDeviceID(device, dir, id) )	  return FALSE;  waveFormat = format;  direction = dir;  return OpenDevice(id);}BOOL PSoundChannelWin32::OpenDevice(unsigned id){  Close();  PWaitAndSignal mutex(bufferMutex);  bufferByteOffset = P_MAX_INDEX;  bufferIndex = 0;  WAVEFORMATEX* format = (WAVEFORMATEX*) waveFormat;  DWORD osError = MMSYSERR_BADDEVICEID;  switch (direction) {    case Player :      osError = waveOutOpen(&hWaveOut, id, format,                            (DWORD)hEventDone, 0, CALLBACK_EVENT);      break;    case Recorder :      osError = waveInOpen(&hWaveIn, id, format,                           (DWORD)hEventDone, 0, CALLBACK_EVENT);      break;  }  if (osError != MMSYSERR_NOERROR)    return SetErrorValues(NotFound, osError|PWIN32ErrorFlag);  os_handle = id;  return TRUE;}BOOL PSoundChannelWin32::IsOpen() const{   return os_handle >= 0;}BOOL PSoundChannelWin32::SetFormat(unsigned numChannels,                              unsigned sampleRate,                              unsigned bitsPerSample){  Abort();  waveFormat.SetFormat(numChannels, sampleRate, bitsPerSample);  return OpenDevice(os_handle);}BOOL PSoundChannelWin32::SetFormat(const PWaveFormat & format){  Abort();  waveFormat = format;  return OpenDevice(os_handle);}unsigned PSoundChannelWin32::GetChannels() const{  return waveFormat->nChannels;}unsigned PSoundChannelWin32::GetSampleRate() const{  return waveFormat->nSamplesPerSec;}unsigned PSoundChannelWin32::GetSampleSize() const{  return waveFormat->wBitsPerSample;}BOOL PSoundChannelWin32::Close(){  if (!IsOpen())    return SetErrorValues(NotOpen, EBADF);  Abort();  if (hWaveOut != NULL) {    while (waveOutClose(hWaveOut) == WAVERR_STILLPLAYING)      waveOutReset(hWaveOut);    hWaveOut = NULL;  }  if (hWaveIn != NULL) {    while (waveInClose(hWaveIn) == WAVERR_STILLPLAYING)      waveInReset(hWaveIn);    hWaveIn = NULL;  }  Abort();  os_handle = -1;  return TRUE;}BOOL PSoundChannelWin32::SetBuffers(PINDEX size, PINDEX count){  Abort();  PAssert(size > 0 && count > 0, PInvalidParameter);  BOOL ok = TRUE;  PWaitAndSignal mutex(bufferMutex);  if (!buffers.SetSize(count))    ok = FALSE;  else {    for (PINDEX i = 0; i < count; i++) {      if (buffers.GetAt(i) == NULL)        buffers.SetAt(i, new PWaveBuffer(size));      if (!buffers[i].SetSize(size))        ok = FALSE;    }  }  bufferByteOffset = P_MAX_INDEX;  bufferIndex = 0;  return ok;}BOOL PSoundChannelWin32::GetBuffers(PINDEX & size, PINDEX & count){  PWaitAndSignal mutex(bufferMutex);  count = buffers.GetSize();  if (count == 0)    size = 0;  else    size = buffers[0].GetSize();  return TRUE;}

⌨️ 快捷键说明

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