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

📄 soundcarddevice.cxx

📁 SIP(Session Initiation Protocol)是由IETF定义
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/* ==================================================================== * The Vovida Software License, Version 1.0  *  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. *  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. *  * 3. The names "VOCAL", "Vovida Open Communication Application Library", *    and "Vovida Open Communication Application Library (VOCAL)" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written *    permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor *    may "VOCAL" appear in their name, without prior written *    permission of Vovida Networks, Inc. *  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *  * ==================================================================== *  * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc.  For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */#include "global.h"/* stdlib */#include <iostream>#include <fstream>#include <cstdio>#include <unistd.h>#include <sys/ioctl.h>#include <csignal>#ifdef WIN32#include <io.h>#endif/* sockets */#include <sys/types.h>#include <sys/socket.h>#include <fcntl.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#ifndef WIN32#include <sys/soundcard.h>#endif#include "VTime.hxx"#include "Rtp.hxx"#include "codec/g711.h"#include "VCondition.h"#include "SoundCardDevice.hxx"#include "UaDeviceEvent.hxx"#include "UaConfiguration.hxx"using namespace Vocal;#define RESID_RTP_RATE 160      // 320 byte packet size#define NETWORK_RTP_RATE 160    // 160 byte packet size#define FLASH_TIMEOUT 1000000extern "C"{    unsigned char linear2ulaw( int pcm_val );    int ulaw2linear( unsigned char u_val );}//***************************************************************************// SoundCardDevice::SoundCardDevice// description:  Constructor.  opens the PhoneCARD device.  initialize the//               hookstate.  resets the device to get it ready.//***************************************************************************void SoundCardDevice::testSoundFile(){    cpLog(LOG_ERR,"Start test");    int cc = 0;    int len;    int inFile_fd;    unsigned char audio_buffer[480];    inFile_fd = open( "ULAW", O_RDONLY, 0 );    reopenAudioHardware();    while( ( len = read( inFile_fd, audio_buffer, 160 ) ) != -1 )    {        cc += len;        if( cc > 20000 ) break;        write( myFD, (char*)audio_buffer, 160 );    }#ifndef WIN32    if( ioctl( myFD, SNDCTL_DSP_SYNC, 0 ) == -1 )    {        perror("SNDCTL_DSP_SYNC");    }#endif    cpLog(LOG_ERR,"Stop test");}SoundCardDevice::SoundCardDevice( const char* deviceName,                                  Sptr < Fifo < Sptr<SipProxyEvent> > > inputQ,                                  Sptr < Fifo < Sptr<SipProxyEvent> > > outputQ )    : ResGwDevice( deviceName, inputQ, outputQ ),      audioStack( 0 ),      inRtpPkt( 0 ),      ringbackFd( -1 ){    // initialize queues    sessionQ = outputQ;    myQ = inputQ;    // initialize states    hookStateOffhook = false;    playDialTone = false;    sendRingback = false;    // open audio hardware device    if( ( myFD = openAudioHardware( deviceName ) ) == -1 )    {        cpLog( LOG_ERR, "Failed to open %s", deviceName );        exit( -1 );    }    // store the device name    myDeviceName = deviceName;#ifndef WIN32    // enable single keypresses without pressing <enter> in terminal    stdinFD = fileno( stdin );    tcgetattr( stdinFD, &initialTerm );    struct termios newTerm = initialTerm;    newTerm.c_lflag &= ~ICANON;    newTerm.c_cc[VMIN] = 0;    newTerm.c_cc[VTIME] = 0;    if( tcsetattr( stdinFD, TCSANOW, &newTerm ) != 0 )    {        cpLog( LOG_ERR, "Unable to set new terminal mode" );        exit( -1 );    }#endif} // end SoundCardDevice::SoundCardDevice()//***************************************************************************// SoundCardDevice::~SoundCardDevice// description:  Destructor//***************************************************************************SoundCardDevice::~SoundCardDevice(){    closeAudioHardware();#ifndef WIN32    tcsetattr( stdinFD, TCSANOW, &initialTerm );#endif} // end SoundCardDevice::~SoundCardDevice()//***************************************************************************// SoundCardDevice::openAudioHardware// description:  open audio hardware device//***************************************************************************int SoundCardDevice::openAudioHardware( const char* pname ){    deviceMutex.lock();    cpLog(LOG_DEBUG, "Opening audio hardware" );    int audioFD;    // open audio device    assert(pname);#ifndef WIN32    if( ( audioFD = open( pname, O_RDWR, 0 ) ) == -1 )    {        perror("Open failed:");		deviceMutex.unlock();        return -1;    }#else    if (waveInGetNumDevs() <= 0)     {        cpLog(LOG_DEBUG, "could not get any devices");        deviceMutex.unlock();        return -1;    }    if (!m_aSoundCardWinOut.Open(SoundOut))     {        perror("Open openAudioHardware failed (not found input sound card device) : ");        deviceMutex.unlock();        return -1;    }    if (!m_aSoundCardWinIn.Open(SoundIn))     {#ifndef _DEBUG        //AND:Need for run 2 exemplars program on one computer (debug version)        m_aSoundCardWinOut.Close();        perror("Open openAudioHardware failed (not found output sound card device) : ");        deviceMutex.unlock();        return -1;#endif    }    audioFD = 1;#endif#ifndef WIN32    // query audio formats    int ioctlParam = -1;    if( ioctl( audioFD, SNDCTL_DSP_GETFMTS, &ioctlParam ) == -1 )    {        perror("SNDCTL_DSP_GETFMTS");        deviceMutex.unlock();        return -1;    }    // choose codec    if( ioctlParam & AFMT_MU_LAW )    {        //cpLog(LOG_DEBUG,"Setting sound card to ulaw");        ioctlParam = AFMT_MU_LAW;        apiCodec = rtpPayloadPCMU;    }    else if( ioctlParam & AFMT_S16_LE )    {        //cpLog(LOG_DEBUG,"Setting sound card to linear16");        ioctlParam = AFMT_S16_LE;        apiCodec = rtpPayloadL16_mono;    }    else    {        cpLog(LOG_ERR,"Sound card doesn't support any known encodings");        printf("Sound card supports the following (Mask:%d:)\n", ioctlParam);        if( ioctlParam & AFMT_MU_LAW )     printf("  AFMT_MU_LAW\n");        if( ioctlParam & AFMT_A_LAW )      printf("  AFMT_A_LAW\n");        if( ioctlParam & AFMT_IMA_ADPCM )  printf("  AFMT_IMA_ADPCM\n");        if( ioctlParam & AFMT_U8 )         printf("  AFMT_U8\n");        if( ioctlParam & AFMT_S16_LE )     printf("  AFMT_S16_LE\n");        if( ioctlParam & AFMT_S16_BE )     printf("  AFMT_S16_BE\n");        if( ioctlParam & AFMT_S8 )         printf("  AFMT_S8\n");        if( ioctlParam & AFMT_U16_LE )     printf("  AFMT_U16_LE\n");        if( ioctlParam & AFMT_U16_BE )     printf("  AFMT_U16_BE\n");        if( ioctlParam & AFMT_MPEG )       printf("  AFMT_MPEG\n");        deviceMutex.unlock();        return -1;    }    // setting audio device parameters    //ioctlParam = AFMT_MU_LAW;  //test setting to ulaw    int ioctlParamSave = ioctlParam;    if( ioctl( audioFD, SNDCTL_DSP_SETFMT, &ioctlParam ) == -1 )    {           perror("SNDCTL_DSP_SETFMT");        deviceMutex.unlock();        return -1;    }    if( ioctlParam != ioctlParamSave )    {           perror("Failed to set DSP Format, sound card returned format");        deviceMutex.unlock();        return -1;    }    ioctlParam = 1;    // set the number of channels to 1.  if this is an error, it    // should probably not be a major failure.    if( ioctl( audioFD, SNDCTL_DSP_CHANNELS, &ioctlParam ) == -1 )    {        perror("SNDCTL_DSP_CHANNELS");        deviceMutex.unlock();        return -1;    }    if( ioctlParam != 1)    {        cout << "warning:  unable to set audio output to mono,"             << " may cause problems later\n";    }    ioctlParam = 8000;    if( ioctl( audioFD, SNDCTL_DSP_SPEED, &ioctlParam ) == -1 )    {        perror("SNDCTL_DSP_SPEED");        deviceMutex.unlock();        return -1;    }    if( ioctlParam != 8000 )    {        perror("Failed to set sample rate");        deviceMutex.unlock();        return -1;    }#else    apiCodec = rtpPayloadL16_mono;#endif    deviceMutex.unlock();    return audioFD;}//***************************************************************************// SoundCardDevice::closeAudioHardware// description://***************************************************************************int SoundCardDevice::closeAudioHardware(){    deviceMutex.lock();    cpLog(LOG_DEBUG, "Closing audio hardware" );#ifndef WIN32    if( ioctl( myFD, SNDCTL_DSP_RESET, 0 ) == -1 )     {        perror("SNDCTL_DSP_RESET");    }#else    m_aSoundCardWinOut.Close();    m_aSoundCardWinIn.Close();#endif    deviceMutex.unlock();#ifndef WIN32    close( myFD );#endif    return 1;}//***************************************************************************// SoundCardDevice::reopenAudioHardware// description://***************************************************************************int SoundCardDevice::reopenAudioHardware( ){    // close audio device    if( closeAudioHardware() == -1 )    {        cpLog(LOG_ERR, "Fail to close %s during reopen", myDeviceName);        return -1;    }    // open audio device    if( ( myFD = openAudioHardware( myDeviceName ) ) == -1 )    {        cpLog(LOG_ERR, "Fail to open %s during reopen", myDeviceName);        return -1;    }    return 1;}//***************************************************************************// SoundCardDevice::writeToSoundCard// description://***************************************************************************void SoundCardDevice::writeToSoundCard ( const unsigned char* data,                                         const int samples ){    char* dspData = 0;    int cc = 0;    int p = 0;     // check codec encodings    switch( apiCodec )    {    case rtpPayloadPCMU:        // no conversion needed        cc = samples;        dspData = (char*)data;        break;            case rtpPayloadL16_mono:        // convert sound sample from ULAW to Linear16        cc = samples;        for(p = 0; p < cc; p++ )            longdataBuffer[p]  = ulaw2linear( data[p] );        cc *= 2;        dspData = (char*)longdataBuffer;        break;    default:        cpLog(LOG_ERR,"Failed to provide correct codec encoding");        return;    }#ifndef WIN32    write( myFD, dspData, cc );#else    m_aSoundCardWinOut.Write(dspData, cc);#endif    return;}int SoundCardDevice::readFromSoundCard( unsigned char* data,                                        const int samples ){    int cc = -1;    int p = 0;    //check codec encodings    switch( apiCodec )    {#ifndef WIN32    case rtpPayloadPCMU:        // no conversion needed        cc = 0;        cc = read( myFD, data, samples );        break;#endif    case rtpPayloadL16_mono:        // convert sound sample from Liner16 to ULAW#ifndef WIN32        cc = read( myFD, (char*)longdataBuffer, samples * 2 );#else        cc = m_aSoundCardWinIn.Read( (char*)longdataBuffer, samples * 2 );#endif        for(; p < cc; p++ )        {            data[p]  = linear2ulaw( longdataBuffer[p] );        }        cc /= 2;        break;    default:        cpLog(LOG_DEBUG,"Failed to provide correct encoding");        break;    }#ifndef WIN32    if( samples != cc )    {        cpLog(LOG_DEBUG,"Incomplete read from Sound Card (%d)", cc);    }#else    // AND:prevent - many garbage on screen (when run 2 programs and    // input from sound card already use one from him) :-/    if( m_aSoundCardWinIn.IsOpen() && samples != cc )    {        cpLog(LOG_ERR,"Incomplete read from Sound Card (%d)", cc);    }#endif    return cc;}//***************************************************************************// SoundCardDevice::hardwareMain// description:  main processing loop of the hardware//***************************************************************************void*SoundCardDevice::hardwareMain( void* parms ){#ifndef WIN32    // process forever on behalf of SoundCardDevice hardware    fd_set readfds;    struct timeval tv;    int retval;    int maxFd = 128;  // should be 0 then increment as needed when addToFdSet    // reset file descriptor    FD_ZERO( &readfds );    addToFdSet( &readfds );    // block on select for asyncronous events, but poll to process    // audio and signal requests from endpoints in message queue    tv.tv_sec = 0;    tv.tv_usec = 300;    if( ( retval = select( maxFd, &readfds, 0, 0, &tv ) ) < 0 )    {        cpLog( LOG_ERR, "select() returned error %d", retval );    }    else    {        if( process( &readfds ) < 0 )        {            cpLog( LOG_ERR, "Hardware encountered an error" );            assert( 0 );        }    }#else    HANDLE handles [1];    handles[0] = GetStdHandle(STD_INPUT_HANDLE);    DWORD dwd = WaitForMultipleObjects(1, handles, false, 300);     fd_set* ptr = NULL;    if (dwd == WAIT_OBJECT_0)

⌨️ 快捷键说明

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