audirix.cpp
Upload User: zhongxx05
Upload Date: 2007-06-06
Package Size: 33641k
Code Size: 12k
Category:

Symbian

Development Platform:

C/C++

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