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

📄 oss.cxx

📁 mgcp协议源代码。支持多种编码:g711
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * sound.cxx * * Sound driver implementation. * * 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): Loopback feature: Philip Edelbrock <phil@netroedge.com>. * * $Log: oss.cxx,v $ * Revision 1.22  2000/07/04 20:34:16  rogerh * Only use ioctl SNDCTL_DSP_SETDUPLEX is Linux. It is not defined in FreeBSD * In NetBSD and OpenBSD (using liboss), the ioctl returns EINVAL. * * Revision 1.21  2000/07/02 14:18:27  craigs * Fixed various problems with buffer handling * * Revision 1.20  2000/07/02 05:49:43  craigs * Really fixed race condition in OSS open * * Revision 1.19  2000/07/02 04:55:18  craigs * Fixed stupid mistake with fix for OSS race condition * * Revision 1.18  2000/07/02 04:50:44  craigs * Fixed potential race condition in OSS initialise * * Revision 1.17  2000/05/11 02:05:54  craigs * Fixed problem with PLayFile not recognizing wait flag * * Revision 1.16  2000/05/10 02:10:44  craigs * Added implementation for PlayFile command * * Revision 1.15  2000/05/02 08:30:26  craigs * Removed "memory leaks" caused by brain-dead GNU linker * * Revision 1.14  2000/04/09 18:19:23  rogerh * Add my changes for NetBSD support. * * Revision 1.13  2000/03/08 12:17:09  rogerh * Add OpenBSD support * * Revision 1.12  2000/03/04 13:02:28  robertj * Added simple play functions for sound files. * * Revision 1.11  2000/02/15 23:11:34  robertj * Audio support for FreeBSD, thanks Roger Hardiman. * * Revision 1.10  2000/01/08 06:41:08  craigs * Fixed problem whereby failure to open sound device returns TRUE * * Revision 1.9  1999/08/24 13:40:26  craigs * Fixed problem with EINTR causing sound channel reads and write to fail * Thanks to phil@netroedge.com! * * Revision 1.8  1999/08/17 09:42:22  robertj * Fixed close of sound channel in loopback mode closing stdin! * * Revision 1.7  1999/08/17 09:28:47  robertj * Added audio loopback psuedo-device (thanks Philip Edelbrock) * * Revision 1.6  1999/07/19 01:31:49  craigs * Major rewrite to assure ioctls are all done in the correct order as OSS seems *    to be incredibly sensitive to this. * * Revision 1.5  1999/07/11 13:42:13  craigs * pthreads support for Linux * * Revision 1.4  1999/06/30 13:49:26  craigs * Added code to allow full duplex audio * * Revision 1.3  1999/05/28 14:14:29  robertj * Added function to get default audio device. * * Revision 1.2  1999/05/22 12:49:05  craigs * Finished implementation for Linux OSS interface * * Revision 1.1  1999/02/25 03:45:00  robertj * Sound driver implementation changes for various unix platforms. * * Revision 1.1  1999/02/22 13:24:47  robertj * Added first cut sound implmentation. * */#pragma implementation "sound.h"#include <ptlib.h>#ifdef P_LINUX#include <sys/soundcard.h>#include <sys/time.h>#endif#ifdef P_FREEBSD#include <machine/soundcard.h>#endif#if defined(P_OPENBSD) || defined(P_NETBSD)#include <soundcard.h>#endif///////////////////////////////////////////////////////////////////////////////// declare type for sound handle dictionaryclass SoundHandleEntry : public PObject {  PCLASSINFO(SoundHandleEntry, PObject)  public:    SoundHandleEntry();    int handle;    int direction;    unsigned numChannels;    unsigned sampleRate;    unsigned bitsPerSample;    unsigned fragmentValue;    BOOL isInitialised;};PDICTIONARY(SoundHandleDict, PString, SoundHandleEntry);#define LOOPBACK_BUFFER_SIZE 5000#define BYTESINBUF ((startptr<endptr)?(endptr-startptr):(LOOPBACK_BUFFER_SIZE+endptr-startptr))static char buffer[LOOPBACK_BUFFER_SIZE];static int  startptr, endptr;PMutex PSoundChannel::dictMutex;static SoundHandleDict & handleDict(){  static SoundHandleDict dict;  return dict;}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);}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*/){  return FALSE;}BOOL PSound::Save(const PFilePath & /*filename*/){  return FALSE;}BOOL PSound::Play(){  PSoundChannel channel(PSoundChannel::GetDefaultDevice(PSoundChannel::Player),                        PSoundChannel::Player);  if (!channel.IsOpen())    return FALSE;  return channel.PlaySound(*this, TRUE);}BOOL PSound::PlayFile(const PFilePath & file, BOOL wait){  PSoundChannel channel(PSoundChannel::GetDefaultDevice(PSoundChannel::Player),                        PSoundChannel::Player);  if (!channel.IsOpen())    return FALSE;  return channel.PlayFile(file, wait);}///////////////////////////////////////////////////////////////////////////////SoundHandleEntry::SoundHandleEntry(){  handle    = -1;  direction = 0;}///////////////////////////////////////////////////////////////////////////////PSoundChannel::PSoundChannel(){  Construct();}PSoundChannel::PSoundChannel(const PString & device,                             Directions dir,                             unsigned numChannels,                             unsigned sampleRate,                             unsigned bitsPerSample){  Construct();  Open(device, dir, numChannels, sampleRate, bitsPerSample);}void PSoundChannel::Construct(){  os_handle = -1;}PSoundChannel::~PSoundChannel(){  Close();}PStringArray PSoundChannel::GetDeviceNames(Directions /*dir*/){  static const char * const devices[] = {    "/dev/audio",    "/dev/dsp",    "/dev/dspW",    "loopback"  };  return PStringArray(PARRAYSIZE(devices), devices);}PString PSoundChannel::GetDefaultDevice(Directions /*dir*/){  return "/dev/dsp";}BOOL PSoundChannel::Open(const PString & _device,                              Directions _dir,                                unsigned _numChannels,                                unsigned _sampleRate,                                unsigned _bitsPerSample){  Close();  // lock the dictionary  PWaitAndSignal mutex(dictMutex);  // make the direction value 1 or 2  int dir = _dir + 1;  // if this device in in the dictionary  if (handleDict().Contains(_device)) {    PTRACE(6, "OSS\tOpen occured for existing entry");    SoundHandleEntry & entry = handleDict()[_device];    // see if the sound channel is already open in this direction    if ((entry.direction & dir) != 0)       return FALSE;    // flag this entry as open in this direction    entry.direction |= dir;    os_handle = entry.handle;  } else {    PTRACE(6, "OSS\tOpen occured for new entry");    // this is the first time this device has been used    // open the device in read/write mode always    if (_device == "loopback") {      startptr = endptr = 0;      os_handle = 0; // Use os_handle value 0 to indicate loopback, cannot ever be stdin!    }    else if (!ConvertOSError(os_handle = ::open((const char *)_device, O_RDWR)))       return FALSE;    // add the device to the dictionary    SoundHandleEntry * entry = PNEW SoundHandleEntry;    handleDict().SetAt(_device, entry);     // save the information into the dictionary entry    entry->handle        = os_handle;    entry->direction     = dir;    entry->numChannels   = _numChannels;    entry->sampleRate    = _sampleRate;    entry->bitsPerSample = _bitsPerSample;    entry->isInitialised = FALSE;    entry->fragmentValue = 0x7fff0008;  }     // save the direction and device  direction     = _dir;  device        = _device;  isInitialised = FALSE;  return TRUE;}BOOL PSoundChannel::Setup(){  PWaitAndSignal mutex(dictMutex);  if (os_handle < 0) {    PTRACE(6, "OSS\tSkipping setup of " << device << " as not open");    return FALSE;  }  if (isInitialised) {    PTRACE(6, "OSS\tSkipping setup of " << device << " as instance already initialised");    return TRUE;  }  // the device must always be in the dictionary  PAssertOS(handleDict().Contains(device));  // get record for the device  SoundHandleEntry & entry = handleDict()[device];  // set default return status  BOOL stat = TRUE;  // do not re-initialise initialised devices  if (entry.isInitialised || (device == "loopback")) {    PTRACE(6, "OSS\tSkipping setup for " << device << " as already initialised");  } else {    PTRACE(6, "OSS\tInitialising " << device << "(" << (void *)(&entry) << ")");#if defined(P_LINUX)    // enable full duplex (maybe).    ::ioctl(os_handle, SNDCTL_DSP_SETDUPLEX, 0);#endif    stat = FALSE;  // must always set paramaters in the following order:  //   buffer paramaters  //   sample format (number of bits)  //   number of channels (mon/stereo)  //   speed (sampling rate)    int arg, val;    // reset the device first so it will accept the new parms    if (ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_RESET, &arg))) {      // set the write fragment size (applies to sound output only)      arg = val = entry.fragmentValue;      ::ioctl(os_handle, SNDCTL_DSP_SETFRAGMENT, &arg);       audio_buf_info info;      ::ioctl(os_handle, SNDCTL_DSP_GETOSPACE, &info);      PTRACE(6, "OSS\tOutput: fragments = " << info.fragments                     << ", total frags = " << info.fragstotal                     << ", frag size   = " << info.fragsize                     << ", bytes       = " << info.bytes);      ::ioctl(os_handle, SNDCTL_DSP_GETISPACE, &info);      PTRACE(6, "OSS\tInput: fragments = " << info.fragments                     << ", total frags = " << info.fragstotal                     << ", frag size   = " << info.fragsize                     << ", bytes       = " << info.bytes);      arg = val = (entry.bitsPerSample == 16) ? AFMT_S16_LE : AFMT_S8;      if (ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_SETFMT, &arg)) || (arg != val)) {

⌨️ 快捷键说明

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