audirix.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:13k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: audirix.cpp,v 1.1.1.1.50.1 2004/07/09 02:01:42 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "audirix.h"
  50. #include "ihxpckts.h"
  51. #include <unistd.h>
  52. #include <fcntl.h>
  53. #include <stdlib.h>
  54. #include <errno.h>
  55. #include <stdio.h> 
  56. #include <math.h> 
  57. //------------------------------------------
  58. // Ctors and Dtors.
  59. //------------------------------------------
  60. CAudioOutIrix::CAudioOutIrix() :
  61.     CAudioOutUNIX(),
  62.     m_pALPort(NULL),
  63.     m_nDevID(NO_FILE_DESCRIPTOR),
  64.     m_nMixerID(NO_FILE_DESCRIPTOR)
  65. {
  66. };
  67. CAudioOutIrix::~CAudioOutIrix()
  68. {
  69. };
  70. //-------------------------------------------------------
  71. // These Device Specific methods must be implemented 
  72. // by the platform specific sub-classes.
  73. //-------------------------------------------------------
  74. INT16 CAudioOutIrix::_Imp_GetAudioFd(void)
  75. {
  76.     return m_nDevID;
  77. }
  78. //Devic specific method to set the audio device characteristics. Sample rate,
  79. //bits-per-sample, etc.
  80. //Method *must* set member vars. m_unSampleRate and m_unNumChannels.
  81. HX_RESULT CAudioOutIrix::_SetDeviceConfig( const HXAudioFormat* pFormat )
  82. {
  83.     if ( m_nDevID < 0 )
  84.         return RA_AOE_DEVNOTOPEN;
  85.     m_wBlockSize = m_ulBytesPerGran;
  86.     //Now set the format. Either 8-bit or 16-bit audio is supported.
  87.     int      nSampleWidth  = pFormat->uBitsPerSample;
  88.     ULONG32  nSampleRate   = pFormat->ulSamplesPerSec;
  89.     int      numChannels   = pFormat->uChannels;
  90.     m_unNumChannels        = numChannels;
  91.     m_uSampFrameSize       = nSampleWidth / 8;
  92.     m_unSampleRate         = nSampleRate;
  93.     //Get a new alConfig so we can set the port.
  94.     ALconfig pALConfig = ALnewconfig();
  95.     if( !pALConfig )
  96.     {
  97. #ifdef _DEBUG
  98.         fprintf( stderr, "Can't Alloc new Config.n");
  99. #endif
  100.        return (  m_wLastError = RA_AOE_NOTENABLED );
  101.     }
  102.  
  103.     //Set the format to PCM two compliment integer data.
  104.     ALsetsampfmt( pALConfig, AL_SAMPFMT_TWOSCOMP );
  105.  
  106.     if( nSampleWidth == 16)
  107.     {
  108.         ALsetwidth( pALConfig, AL_SAMPLE_16 );
  109.     }
  110.     else
  111.     {
  112.         ALsetwidth( pALConfig, AL_SAMPLE_8 );
  113.     }
  114.     
  115.     if(ALsetchannels( pALConfig, numChannels) < 0 )
  116.     {
  117. #ifdef _DEBUG
  118.         fprintf( stderr, "Can't set number of channels.n");
  119. #endif
  120.        return (  m_wLastError = RA_AOE_NOTENABLED );
  121.     }
  122.     //Set sample rate. For now we are assuming that they
  123.     //are using the default analog out device.
  124.     //XXXgfw we should query for the active output device
  125.     //       and use that one instead.
  126.     //Now let do the rate.
  127.     long params[4];
  128.     params[0] = AL_OUTPUT_RATE;
  129.     params[1] = nSampleRate;
  130. #ifdef _DEBUG
  131.     fprintf( stderr, "Trying to set a rate of: %dn", nSampleRate );
  132. #endif
  133.     if( ALsetparams( AL_DEFAULT_DEVICE, params, 2 ) < 0 )
  134.     {
  135. #ifdef _DEBUG
  136.         fprintf( stderr, "alSetParams has failed: %d n", errno);
  137. #endif
  138.        return (  m_wLastError = RA_AOE_NOTENABLED );
  139.     }
  140.     if( params[1] != nSampleRate )
  141.     {
  142. #ifdef _DEBUG
  143.         fprintf( stderr, "Invalid rate specified.n");
  144. #endif
  145.        return (  m_wLastError = RA_AOE_NOTENABLED );
  146.     }
  147.     //In Irix we can pick our own buffer size. Yeah!
  148.     //For now, however, lets just leave the defualt which
  149.     //is 50,000 samples big.
  150.     int nTmp = ALgetqueuesize( pALConfig );
  151.     ALsetqueuesize( pALConfig, nTmp );
  152. #ifdef _DEBUG
  153.     fprintf( stderr, "Irix is using: %d sample frames to buffer.n", nTmp );
  154. #endif
  155.     m_ulDeviceBufferSize = nTmp*m_uSampFrameSize*m_unNumChannels;
  156.     //Now set the ports configuration.
  157.     ALcloseport( m_pALPort );
  158.     m_pALPort = ALopenport( "RealPlayer", "w", pALConfig );
  159. //    if ( ALsetconfig( m_pALPort, pALConfig ) == -1 )
  160. //    {
  161. //#ifdef _DEBUG
  162. //        fprintf( stderr, "Can not set the ports configuration.n" );
  163. //        fprintf( stderr, "errno: %d.n", oserror() );
  164. //#endif
  165. //        return ( m_wLastError = RA_AOE_NOTENABLED );
  166. //    } 
  167.     //XXXgfw
  168.     ALfreeconfig( pALConfig );
  169.     
  170. #ifdef _DEBUG
  171.     fprintf( stderr, "Device Configured:n");
  172.     fprintf( stderr, "      Sample Rate: %dn", m_unSampleRate);
  173.     fprintf( stderr, "     Sample Width: %dn", nSampleWidth);
  174.     fprintf( stderr, "     Num channels: %dn", m_unNumChannels);
  175.     fprintf( stderr, " Device buff size: %lun", m_ulDeviceBufferSize);
  176. #endif
  177.     return RA_AOE_NOERR;
  178. }
  179. //Device specific method to write bytes out to the audiodevice and return a
  180. //count of bytes written. 
  181. HX_RESULT CAudioOutIrix::_WriteBytes( UCHAR* buffer, ULONG32 ulBuffLength, LONG32& lCount )
  182. {
  183.     HX_RESULT retCode = RA_AOE_NOERR;
  184.     if( m_nDevID < 0 )
  185.     {
  186.         retCode = RA_AOE_DEVNOTOPEN;
  187.     }
  188.     else
  189.     {
  190.         lCount = ulBuffLength;
  191.         int nFrameCount = ulBuffLength/m_uSampFrameSize;
  192.         ALwritesamps( m_pALPort, buffer, nFrameCount );
  193.     }
  194.     return retCode;
  195. }
  196. //Device specific methods to open/close the mixer and audio devices.
  197. HX_RESULT CAudioOutIrix::_OpenAudio()
  198. {
  199.     HX_RESULT retCode = RA_AOE_NOERR;
  200.     // Open the audio device if it isn't already open
  201.     if ( m_nDevID < 0 )
  202.     {
  203.         //Open an audio port and set the config later.
  204.         m_pALPort = ALopenport( "RealPlayer", "w", 0 );
  205.         if( m_pALPort == 0 )
  206.         {
  207. #ifdef _DEBUG
  208.             fprintf( stderr, "Can't open port. oserror is: %dn",
  209.                      oserror() );
  210. #endif
  211.         }
  212. #ifdef _DEBUG
  213.         fprintf( stderr, "Got a port: %pn", m_pALPort );
  214. #endif
  215.             
  216.         //Grab a file descriptor so we can select on it.
  217.         if( NULL != m_pALPort )
  218.             m_nDevID = ALgetfd( m_pALPort );
  219.     }
  220.     
  221.     if ( m_nDevID < 0 || NULL == m_pALPort )
  222.     {
  223. #ifdef _DEBUG        
  224.         fprintf( stderr, "Failed to open audio!!!!!!! Code is: %d  errno: %dn",
  225.                  m_nDevID, errno );
  226. #endif        
  227.         
  228.         //Error opening device.
  229.         retCode = RA_AOE_BADOPEN;
  230.     }
  231.     
  232.     m_wLastError = retCode;
  233.     return m_wLastError;
  234. }
  235. HX_RESULT CAudioOutIrix::_CloseAudio()
  236. {
  237.     HX_RESULT retCode = RA_AOE_NOERR;
  238.     
  239.     if( m_nDevID >= 0 )
  240.     {
  241.         ALcloseport( m_pALPort );
  242.         m_pALPort = NULL;
  243.         m_nDevID  = NO_FILE_DESCRIPTOR;
  244.     }
  245.     else
  246.     {
  247.         retCode = RA_AOE_DEVNOTOPEN;
  248.     }
  249.     m_wLastError = retCode;
  250.     return m_wLastError;
  251. }
  252. HX_RESULT CAudioOutIrix::_OpenMixer()
  253. {
  254.     HX_RESULT retCode = RA_AOE_NOERR;
  255.     //We always have a mixer on Irix.
  256.     m_bMixerPresent = 1;
  257.     _Imp_GetVolume();
  258.     m_wLastError = retCode;
  259.     return m_wLastError;
  260. }
  261. HX_RESULT CAudioOutIrix::_CloseMixer()
  262. {
  263.     HX_RESULT retCode = RA_AOE_NOERR;
  264.     m_wLastError = retCode;
  265.     return m_wLastError;
  266. }
  267. //Device specific method to reset device and return it to a state that it 
  268. //can accept new sample rates, num channels, etc.
  269. HX_RESULT CAudioOutIrix::_Reset()
  270. {
  271.     HX_RESULT retCode = RA_AOE_NOERR;
  272.     
  273.     if ( m_nDevID < 0 )
  274.     {
  275.         retCode = RA_AOE_DEVNOTOPEN;
  276.     }
  277.     else
  278.     {
  279.         //Throw away all frames in the audio buffer.
  280.         //XXXgfw this isn't available on Irix 6.2 
  281.         //alDiscardFrames(m_pALPort, m_ulDeviceBufferSize/m_uSampFrameSize/m_unNumChannels );
  282.     }
  283.     m_wLastError = retCode;
  284.     return m_wLastError;
  285. }
  286. //Device specific method to get/set the devices current volume.
  287. UINT16 CAudioOutIrix::_GetVolume() const
  288. {  
  289.     float newVolume = 0;
  290.     long buf[4] = {
  291.                     AL_LEFT_SPEAKER_GAIN, 128,
  292.                     AL_RIGHT_SPEAKER_GAIN, 128
  293.                   };
  294.     ALgetparams(AL_DEFAULT_DEVICE, buf, 4);
  295.     //Map volume to [0..100] which is what the core needs.
  296.     //We are doing a logrythmic conversion.
  297.     if( buf[1] != 0 )
  298.       newVolume = 18.1*logf((float)buf[1]);
  299.     //Round up or down.
  300.     newVolume = trunc( newVolume+0.5 );
  301.     if( newVolume<0 )  newVolume=0;
  302.     if( newVolume>255) newVolume=255;
  303. #ifdef _DEBUG
  304.     //fprintf( stderr, "Got a volume of: %f calculated from %lun", newVolume, buf[1] );
  305. #endif
  306.     return (UINT16)newVolume; 
  307. }
  308. HX_RESULT CAudioOutIrix::_SetVolume(UINT16 unVolume)
  309.     float     newVolume = 0;
  310.     HX_RESULT retCode   = RA_AOE_NOERR;
  311.     long buf[4] = {
  312.                     AL_LEFT_SPEAKER_GAIN, 128,
  313.                     AL_RIGHT_SPEAKER_GAIN, 128
  314.                   };
  315.    //Map incoming volume from [0..100] to [0..255]
  316.    //Volume appears to be logrythmic.
  317.    if( unVolume != 0 )
  318.       newVolume = expf((float)unVolume/18.1);
  319.    //Round up or down.
  320.    newVolume = trunc( newVolume+0.5 );
  321.    if( newVolume>255 ) 
  322.       newVolume=255;
  323.    if( newVolume<0 )
  324.       newVolume=0;
  325. #ifdef _DEBUG
  326.    //fprintf( stderr, "Setting volume to %f calculated from %lun", newVolume, unVolume );
  327. #endif
  328.    buf[1] = newVolume;
  329.    buf[3] = newVolume;
  330.    ALsetparams(AL_DEFAULT_DEVICE, buf, 4);
  331.    m_wLastError = retCode;
  332.    return m_wLastError;
  333. }
  334. //Device specific method to drain a device. This should play the remaining
  335. //bytes in the devices buffer and then return.
  336. HX_RESULT CAudioOutIrix::_Drain()
  337. {
  338.     HX_RESULT retCode = RA_AOE_NOERR;
  339.     
  340.     if ( m_nDevID < 0 )
  341.     {
  342.         retCode = RA_AOE_DEVNOTOPEN;
  343.     }
  344.     m_wLastError = retCode;
  345.     return m_wLastError;
  346. }
  347. ULONG32 CAudioOutIrix::_GetBytesActualyPlayed(void) const
  348. {
  349.     /* Get current playback position in device DMA. */
  350.     int     bytes2 = 0;
  351.     ULONG32 ulTheAnswer = 0;
  352.     //Ask for the number of frames yet to be played in the
  353.     //audio buffer and convert to bytes.
  354.     bytes2 = ALgetfilled( m_pALPort );
  355.     if( bytes2 >= 0)
  356.     {
  357.         //Convert frames to bytes.
  358.         bytes2 = bytes2*m_uSampFrameSize*m_unNumChannels;
  359.         ulTheAnswer = (ULONG32)(m_ulTotalWritten - bytes2 );
  360.     }
  361.     return  ulTheAnswer;
  362. }
  363. //this must return the number of bytes that can be written without blocking.
  364. //Don't use SNDCTL_DSP_GETODELAY here as it can't compute that amount
  365. //correctly.
  366. HX_RESULT CAudioOutIrix::_GetRoomOnDevice(ULONG32& ulBytes) const
  367. {
  368.     HX_RESULT retCode     = RA_AOE_NOERR;
  369.     //Get the number of frames we can write without blocking 
  370.     //and convert it to bytes.
  371.     int nFrames = ALgetfillable( m_pALPort );
  372.     ulBytes = nFrames*m_uSampFrameSize*m_unNumChannels;
  373.     
  374.     m_wLastError = retCode;
  375.     return m_wLastError;
  376. }
  377. HX_RESULT CAudioOutIrix::_CheckSampleRate( ULONG32 ulSampleRate )
  378. {
  379.     //Still need to do this one.
  380. #ifdef _DEBUG
  381.     fprintf( stderr, "_CheckSampleRate not support yet.n" );
  382. #endif
  383.     m_wLastError = RA_AOE_NOERR;
  384.     return m_wLastError;
  385. }