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

📄 pa_unix_solaris.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
字号:
/* * PortAudio Portable Real-Time Audio Library * Latest Version at: http://www.portaudio.com * Linux OSS Implementation by douglas repetto and Phil Burk * * Copyright (c) 1999-2000 Phil Burk * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * *//* Modification history:   20020621: Initial cut at Solaris modifications jointly by Sam Bayer             and Augustus Saunders.   20030206 - Martin Rohrbach - various mods for Solaris */#define __solaris_native__#include "pa_unix.h"/* SAM 6/2/02: Docs say we should include sys/audio.h, but   that doesn't exist pre Solaris 2.8. These headers work fine. */#include <sys/audioio.h>#include <sys/stropts.h>/********************************************************************* * Try to open the named device. * If it opens, try to set various rates and formats and fill in * the device info structure. */PaError Pa_QueryDevice( const char *deviceName, internalPortAudioDevice *pad ){    int result = paHostError;    int tempDevHandle;    int numChannels, maxNumChannels;    int numSampleRates;    int sampleRate;    int numRatesToTry;    int ratesToTry[9] = {96000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000};    int i;    audio_info_t solaris_info;    audio_device_t device_info;    /* douglas:     we have to do this querying in a slightly different order. apparently     some sound cards will give you different info based on their settins.     e.g. a card might give you stereo at 22kHz but only mono at 44kHz.     the correct order for OSS is: format, channels, sample rate    */	/*	 to check a device for it's capabilities, it's probably better to use the	 equivalent "-ctl"-descriptor - MR	*/    char devname[strlen(deviceName) + 4];    if ( (tempDevHandle = open(strcat(strcpy(devname, deviceName), "ctl"), O_WRONLY|O_NONBLOCK))  == -1 )    {        DBUG(("Pa_QueryDevice: could not open %s\n", deviceName ));        return paHostError;    }    /*  Ask OSS what formats are supported by the hardware. */    pad->pad_Info.nativeSampleFormats = 0;    AUDIO_INITINFO(&solaris_info);    /* SAM 12/31/01: Sparc native does mulaw, alaw and PCM.       I think PCM is signed. */    for (i = 8; i <= 32; i += 8) {      solaris_info.play.precision = i;      solaris_info.play.encoding = AUDIO_ENCODING_LINEAR;      /* If there are no errors, add the format. */      if (ioctl(tempDevHandle, AUDIO_SETINFO, &solaris_info) > -1) {	switch (i) {	case 8:	  pad->pad_Info.nativeSampleFormats |= paInt8;	  break;	case 16:	  pad->pad_Info.nativeSampleFormats |= paInt16;	  break;	case 24:	  pad->pad_Info.nativeSampleFormats |= paInt24;	  break;	case 32:	  pad->pad_Info.nativeSampleFormats |= paInt32;	  break;	}      }    }    maxNumChannels = 0;    for( numChannels = 1; numChannels <= 16; numChannels++ )      {	int temp = numChannels;	DBUG(("Pa_QueryDevice: use SNDCTL_DSP_CHANNELS, numChannels = %d\n", numChannels ))	  AUDIO_INITINFO(&solaris_info);	solaris_info.play.channels = temp;	if (ioctl(tempDevHandle, AUDIO_SETINFO, &solaris_info) < 0)	  {	    /* ioctl() failed so bail out if we already have stereo */	    if( numChannels > 2 ) break;	  }	else	  {	    /* ioctl() worked but bail out if it does not support numChannels.	     * We don't want to leave gaps in the numChannels supported.	     */	    if( (numChannels > 2) && (temp != numChannels) ) break;	    DBUG(("Pa_QueryDevice: temp = %d\n", temp ))	      if( temp > maxNumChannels ) maxNumChannels = temp; /* Save maximum. */	  }      }    pad->pad_Info.maxOutputChannels = maxNumChannels;    DBUG(("Pa_QueryDevice: maxNumChannels = %d\n", maxNumChannels))    /* FIXME - for now, assume maxInputChannels = maxOutputChannels.     *    Eventually do separate queries for O_WRONLY and O_RDONLY    */    pad->pad_Info.maxInputChannels = pad->pad_Info.maxOutputChannels;    DBUG(("Pa_QueryDevice: maxInputChannels = %d\n",          pad->pad_Info.maxInputChannels))    /* Determine available sample rates by trying each one and seeing result.     */    numSampleRates = 0;    AUDIO_INITINFO(&solaris_info);    numRatesToTry = sizeof(ratesToTry)/sizeof(int);    for (i = 0; i < numRatesToTry; i++)    {        sampleRate = ratesToTry[i];	solaris_info.play.sample_rate = sampleRate; /* AS: We opened for Write, so set play */        if (ioctl(tempDevHandle, AUDIO_SETINFO, &solaris_info) >= 0 ) /* PLB20010817 */        {            if (sampleRate == ratesToTry[i])            {                DBUG(("Pa_QueryDevice: got sample rate: %d\n", sampleRate))                pad->pad_SampleRates[numSampleRates] = (float)ratesToTry[i];                numSampleRates++;            }        }    }    DBUG(("Pa_QueryDevice: final numSampleRates = %d\n", numSampleRates))    if (numSampleRates==0)   /* HP20010922 */    {        ERR_RPT(("Pa_QueryDevice: no supported sample rate (or SNDCTL_DSP_SPEED ioctl call failed).\n" ));        goto error;    }    pad->pad_Info.numSampleRates = numSampleRates;    pad->pad_Info.sampleRates = pad->pad_SampleRates;    /* query for the device name instead of using the filesystem-device - MR */	if (ioctl(tempDevHandle, AUDIO_GETDEV, &device_info) == -1) {      pad->pad_Info.name = deviceName;    } else {      char *pt = (char *)PaHost_AllocateFastMemory(strlen(device_info.name));      strcpy(pt, device_info.name);      pad->pad_Info.name = pt;    }    result = paNoError;error:    /* We MUST close the handle here or we won't be able to reopen it later!!!  */    close(tempDevHandle);    return result;}/*******************************************************************************************/PaError Pa_SetupInputDeviceFormat( int devHandle, int numChannels, int sampleRate ){    audio_info_t solaris_info;    AUDIO_INITINFO(&solaris_info);    /* Sam Bayer/Bryan George 1/10/02: Various folks have       reported that on Solaris Ultra II, the not-right thing       happens on read unless you make sure the audio device is       flushed. The folks who wrote the Robust Audio Tool say:       + XXX driver issue - on Ultra II's if you don't drain       * the device before reading commences then the device       * reads in blocks of 500ms irrespective of the       * blocksize set. After a minute or so it flips into the       * correct mode, but obviously this is too late to be + * useful for most apps. grrr.       */    /* AS: And the Solaris man audio pages say you should flush before changing formats       anyway.  So there you go. */    if (Pa_FlushStream(devHandle) != paNoError)      return paHostError;    solaris_info.record.encoding = AUDIO_ENCODING_LINEAR;    solaris_info.record.sample_rate = sampleRate;    solaris_info.record.precision = 16;    solaris_info.record.channels = numChannels;    if (ioctl(devHandle, AUDIO_SETINFO, &solaris_info) == -1)      {        ERR_RPT(("Pa_SetupDeviceFormat: could not set audio info\n" ));        return paHostError;      }    return paNoError;}PaError Pa_SetupOutputDeviceFormat( int devHandle, int numChannels, int sampleRate ){    audio_info_t solaris_info;    AUDIO_INITINFO(&solaris_info);    /* Sam Bayer/Bryan George 1/10/02: Various folks have       reported that on Solaris Ultra II, the not-right thing       happens on read unless you make sure the audio device is       flushed. The folks who wrote the Robust Audio Tool say:       + XXX driver issue - on Ultra II's if you don't drain       * the device before reading commences then the device       * reads in blocks of 500ms irrespective of the       * blocksize set. After a minute or so it flips into the       * correct mode, but obviously this is too late to be + * useful for most apps. grrr.       */    /* AS: And the Solaris man audio pages say you should flush before changing formats       anyway.  So there you go. */    if (Pa_FlushStream(devHandle) != paNoError)      return paHostError;    solaris_info.play.encoding = AUDIO_ENCODING_LINEAR;    solaris_info.play.sample_rate = sampleRate;    solaris_info.play.precision = 16;    solaris_info.play.channels = numChannels;    if (ioctl(devHandle, AUDIO_SETINFO, &solaris_info) == -1)      {        ERR_RPT(("Pa_SetupDeviceFormat: could not set audio info\n" ));        return paHostError;      }    return paNoError;}PaError Pa_SetupDeviceFormat( int devHandle, int numChannels, int sampleRate ){        PaError result = paNoError;	result = Pa_SetupOutputDeviceFormat(devHandle, numChannels, sampleRate);	if (result != paNoError)	  return result;	return Pa_SetupInputDeviceFormat(devHandle, numChannels, sampleRate);}/********************************************************************************************* Set number of fragments and size of fragments to achieve desired latency.*/static PaError Pa_Unpause(int devHandle);static PaError Pa_PauseAndFlush(int devHandle);void Pa_SetLatency( int devHandle, int numBuffers, int framesPerBuffer, int channelsPerFrame  ){  int     bufferSize;  audio_info_t solaris_info;  /* Increase size of buffers and reduce number of buffers to reduce latency inside driver. */  while( numBuffers > 8 )    {      numBuffers = (numBuffers + 1) >> 1;      framesPerBuffer = framesPerBuffer << 1;    }  /* calculate size of buffers in bytes */  bufferSize = framesPerBuffer * channelsPerFrame * sizeof(short); /* FIXME - other sizes? */  DBUG(("Pa_SetLatency: numBuffers = %d, framesPerBuffer = %d\n",	numBuffers, framesPerBuffer));  /* SAM 6/6/02: Documentation says to pause and flush before     changing buffer size. */  if (Pa_PauseAndFlush(devHandle) != paNoError) {    ERR_RPT(("Pa_SetLatency: could not pause audio\n" ));    return;  }  AUDIO_INITINFO(&solaris_info);  /* AS: Doesn't look like solaris has multiple buffers,     so I'm being conservative and     making one buffer.  Might not be what we want... */  solaris_info.play.buffer_size = solaris_info.record.buffer_size = bufferSize;  if (ioctl(devHandle, AUDIO_SETINFO, &solaris_info) == -1)    {      ERR_RPT(("Pa_SetLatency: could not set audio info\n" ));    }  Pa_Unpause(devHandle);}/***********************************************************************/PaTimestamp Pa_StreamTime( PortAudioStream *stream ){    internalPortAudioStream *past = (internalPortAudioStream *) stream;    PaHostSoundControl *pahsc;    audio_info_t solaris_info;    if( past == NULL ) return paBadStreamPtr;    pahsc = (PaHostSoundControl *) past->past_DeviceData;    ioctl(pahsc->pahsc_OutputHandle, AUDIO_GETINFO, &solaris_info);    return solaris_info.play.samples;}void Pa_UpdateStreamTime(PaHostSoundControl *pahsc){  /* AS: Don't need to do anytying for this under Solaris.*/}static PaError Pa_PauseAndFlush(int devHandle){  audio_info_t solaris_info;  AUDIO_INITINFO(&solaris_info);  solaris_info.play.pause = solaris_info.record.pause = 1;  if (ioctl(devHandle, AUDIO_SETINFO, &solaris_info) == -1)    {      ERR_RPT(("Pa_FlushStream failed.\n"));      return paHostError;    }  if (ioctl(devHandle, I_FLUSH, FLUSHRW) == -1)    {      ERR_RPT(("Pa_FlushStream failed.\n"));      /* Unpause! */      AUDIO_INITINFO(&solaris_info);      solaris_info.play.pause = solaris_info.record.pause = 0;      ioctl(devHandle, AUDIO_SETINFO, &solaris_info);      return paHostError;    }  return paNoError;}static PaError Pa_Unpause(int devHandle){  audio_info_t solaris_info;  AUDIO_INITINFO(&solaris_info);  solaris_info.play.pause = solaris_info.record.pause = 0;  if (ioctl(devHandle, AUDIO_SETINFO, &solaris_info) == -1)    {      ERR_RPT(("Pa_FlushStream failed.\n"));      return paHostError;    }  return paNoError;}PaError Pa_FlushStream(int devHandle){  PaError res = Pa_PauseAndFlush(devHandle);  if (res == paNoError)    return Pa_Unpause(devHandle);  else return res;}

⌨️ 快捷键说明

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