diff --git a/src/audio/audiolayer.cpp b/src/audio/audiolayer.cpp index 7754a34c737b78f3a2c396197d839b1d13e53e51..45924b2c5c39212be8f48abfc66462e3ee729a4a 100644 --- a/src/audio/audiolayer.cpp +++ b/src/audio/audiolayer.cpp @@ -2,10 +2,11 @@ * Copyright (C) 2005 Savoir-Faire Linux inc. * Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Jerome Oufella <jerome.oufella@savoirfairelinux.com> + * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -108,13 +109,15 @@ AudioLayer::hasStream(void) { void -AudioLayer::openDevice (int indexIn, int indexOut, int sampleRate) +AudioLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize) { closeStream(); _sampleRate = sampleRate; - + _frameSize = frameSize; int portaudioFramePerBuffer = FRAME_PER_BUFFER; //=FRAME_PER_BUFFER; //= paFramesPerBufferUnspecified; + //int portaudioFramePerBuffer = (int) (8000 * frameSize / 1000); +//= paFramesPerBufferUnspecified; int nbDevice = getDeviceCount(); if (nbDevice == 0) { diff --git a/src/audio/audiolayer.h b/src/audio/audiolayer.h index 3c45ed0bb8e71bd7ee082d87cc4b55c21d89e6ff..548ef197930a17bc7b7bccf6ea2744fe26eff3b4 100644 --- a/src/audio/audiolayer.h +++ b/src/audio/audiolayer.h @@ -2,10 +2,11 @@ * Copyright (C) 2004-2005 Savoir-Faire Linux inc. * Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Jerome Oufella <jerome.oufella@savoirfairelinux.com> + * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -35,96 +36,103 @@ class RingBuffer; class ManagerImpl; class AudioLayer { -public: - AudioLayer(ManagerImpl* manager); - ~AudioLayer(void); - - /* - * @param indexIn - * @param indexOut - * @param sampleRate - */ - void openDevice(int, int, int); - void startStream(void); - void stopStream(void); - void sleep(int); - bool hasStream(void); - bool isStreamActive(void); - bool isStreamStopped(void); - - void flushMain(); - int putMain(void* buffer, int toCopy); - int putUrgent(void* buffer, int toCopy); - int canGetMic(); - int getMic(void *, int); - void flushMic(); - - int audioCallback (const void *, void *, unsigned long, - const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags); - int miniAudioCallback (const void *, void *, unsigned long, - const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags); - - void setErrorMessage(const std::string& error) { _errorMessage = error; } - std::string getErrorMessage() { return _errorMessage; } - - /** - * Get the sample rate of audiolayer - * accessor only - */ - unsigned int getSampleRate() { return _sampleRate; } - - int getDeviceCount(); - AudioDevice* getAudioDeviceInfo(int index, int ioDeviceMask); - - enum IODEVICE {InputDevice=0x01, OutputDevice=0x02 }; - - /** - * Toggle echo testing on/off - */ - void toggleEchoTesting(); - -private: - void closeStream (void); - RingBuffer _urgentRingBuffer; - RingBuffer _mainSndRingBuffer; - RingBuffer _micRingBuffer; - ManagerImpl* _manager; // augment coupling, reduce indirect access - // a audiolayer can't live without manager - - portaudio::MemFunCallbackStream<AudioLayer> *_stream; - - /** - * Sample Rate of SFLphone : should be 8000 for 8khz - * Added because we could change it in the futur - */ - unsigned int _sampleRate; - - /** - * Input channel (mic) should be 1 mono - */ - unsigned int _inChannel; // mic - - /** - * Output channel (stereo) should be 1 mono - */ - unsigned int _outChannel; // speaker - - /** - * Default volume for incoming RTP and Urgent sounds. - */ - unsigned short _defaultVolume; // 100 - - /** - * Echo testing or not - */ - bool _echoTesting; - - std::string _errorMessage; - ost::Mutex _mutex; - - float *table_; - int tableSize_; - int leftPhase_; + public: + AudioLayer(ManagerImpl* manager); + ~AudioLayer(void); + + /* + * @param indexIn + * @param indexOut + * @param sampleRate + * @param frameSize + */ + void openDevice(int, int, int, int); + void startStream(void); + void stopStream(void); + void sleep(int); + bool hasStream(void); + bool isStreamActive(void); + bool isStreamStopped(void); + + void flushMain(); + int putMain(void* buffer, int toCopy); + int putUrgent(void* buffer, int toCopy); + int canGetMic(); + int getMic(void *, int); + void flushMic(); + + int audioCallback (const void *, void *, unsigned long, + const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags); + int miniAudioCallback (const void *, void *, unsigned long, + const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags); + + void setErrorMessage(const std::string& error) { _errorMessage = error; } + std::string getErrorMessage() { return _errorMessage; } + + /** + * Get the sample rate of audiolayer + * accessor only + */ + unsigned int getSampleRate() { return _sampleRate; } + unsigned int getFrameSize() { return _frameSize; } + int getDeviceCount(); + AudioDevice* getAudioDeviceInfo(int index, int ioDeviceMask); + + enum IODEVICE {InputDevice=0x01, OutputDevice=0x02 }; + + /** + * Toggle echo testing on/off + */ + void toggleEchoTesting(); + + private: + void closeStream (void); + RingBuffer _urgentRingBuffer; + RingBuffer _mainSndRingBuffer; + RingBuffer _micRingBuffer; + ManagerImpl* _manager; // augment coupling, reduce indirect access + // a audiolayer can't live without manager + + portaudio::MemFunCallbackStream<AudioLayer> *_stream; + + /** + * Sample Rate SFLphone should send sound data to the sound card + * The value can be set in the user config file- now: 44100HZ + */ + unsigned int _sampleRate; + + /** + * Length of the sound frame we capture or read in ms + * The value can be set in the user config file - now: 20ms + */ + unsigned int _frameSize; + + /** + * Input channel (mic) should be 1 mono + */ + unsigned int _inChannel; // mic + + /** + * Output channel (stereo) should be 1 mono + */ + unsigned int _outChannel; // speaker + + /** + * Default volume for incoming RTP and Urgent sounds. + */ + unsigned short _defaultVolume; // 100 + + /** + * Echo testing or not + */ + bool _echoTesting; + + std::string _errorMessage; + ost::Mutex _mutex; + + float *table_; + int tableSize_; + int leftPhase_; }; #endif // _AUDIO_LAYER_H_ diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp index fe6f0833a0d255cee8befe522f04861f1c0ca64b..53efa0962dd9fa11271441c6e17d01c71eb8f304 100644 --- a/src/audio/audiortp.cpp +++ b/src/audio/audiortp.cpp @@ -1,12 +1,13 @@ /* * Copyright (C) 2004-2007 Savoir-Faire Linux inc. + * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> * Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -44,476 +45,478 @@ //////////////////////////////////////////////////////////////////////////////// AudioRtp::AudioRtp () { - _RTXThread = 0; + _RTXThread = 0; } AudioRtp::~AudioRtp (void) { - delete _RTXThread; _RTXThread = 0; + delete _RTXThread; _RTXThread = 0; } int AudioRtp::createNewSession (SIPCall *ca) { - ost::MutexLock m(_threadMutex); - - // something should stop the thread before... - if ( _RTXThread != 0 ) { - _debug("! ARTP Failure: Thread already exists..., stopping it\n"); - delete _RTXThread; _RTXThread = 0; - //return -1; - } - - // Start RTP Send/Receive threads - _symmetric = Manager::instance().getConfigInt(SIGNALISATION,SYMMETRIC) ? true : false; - _RTXThread = new AudioRtpRTX (ca, _symmetric); - - try { - if (_RTXThread->start() != 0) { - _debug("! ARTP Failure: unable to start RTX Thread\n"); - return -1; - } - } catch(...) { - _debugException("! ARTP Failure: when trying to start a thread"); - throw; - } - return 0; + ost::MutexLock m(_threadMutex); + + // something should stop the thread before... + if ( _RTXThread != 0 ) { + _debug("! ARTP Failure: Thread already exists..., stopping it\n"); + delete _RTXThread; _RTXThread = 0; + //return -1; + } + + // Start RTP Send/Receive threads + _symmetric = Manager::instance().getConfigInt(SIGNALISATION,SYMMETRIC) ? true : false; + _RTXThread = new AudioRtpRTX (ca, _symmetric); + + try { + if (_RTXThread->start() != 0) { + _debug("! ARTP Failure: unable to start RTX Thread\n"); + return -1; + } + } catch(...) { + _debugException("! ARTP Failure: when trying to start a thread"); + throw; + } + return 0; } - + void AudioRtp::closeRtpSession () { - ost::MutexLock m(_threadMutex); - // This will make RTP threads finish. - // _debug("Stopping AudioRTP\n"); - try { - delete _RTXThread; _RTXThread = 0; - } catch(...) { - _debugException("! ARTP Exception: when stopping audiortp\n"); - throw; - } + ost::MutexLock m(_threadMutex); + // This will make RTP threads finish. + // _debug("Stopping AudioRTP\n"); + try { + delete _RTXThread; _RTXThread = 0; + } catch(...) { + _debugException("! ARTP Exception: when stopping audiortp\n"); + throw; + } } //////////////////////////////////////////////////////////////////////////////// // AudioRtpRTX Class // //////////////////////////////////////////////////////////////////////////////// AudioRtpRTX::AudioRtpRTX (SIPCall *sipcall, bool sym) - // : _fstream("/tmp/audio.dat", std::ofstream::binary) - { - setCancel(cancelDeferred); - time = new ost::Time(); - _ca = sipcall; - _sym = sym; - // AudioRtpRTX should be close if we change sample rate - - _receiveDataDecoded = new int16[RTP_20S_48KHZ_MAX]; - _sendDataEncoded = new unsigned char[RTP_20S_8KHZ_MAX]; - - // we estimate that the number of format after a conversion 8000->48000 is expanded to 6 times - _dataAudioLayer = new SFLDataFormat[RTP_20S_48KHZ_MAX]; - _floatBuffer8000 = new float32[RTP_20S_8KHZ_MAX]; - _floatBuffer48000 = new float32[RTP_20S_48KHZ_MAX]; - _intBuffer8000 = new int16[RTP_20S_8KHZ_MAX]; - - // TODO: Change bind address according to user settings. - // TODO: this should be the local ip not the external (router) IP - std::string localipConfig = _ca->getLocalIp(); // _ca->getLocalIp(); - ost::InetHostAddress local_ip(localipConfig.c_str()); - - if (!_sym) { - _sessionRecv = new ost::RTPSession(local_ip, _ca->getLocalAudioPort()); - _sessionSend = new ost::RTPSession(local_ip, _ca->getLocalAudioPort()); - _session = NULL; - } else { - _session = new ost::SymmetricRTPSession (local_ip, _ca->getLocalAudioPort()); - _sessionRecv = NULL; - _sessionSend = NULL; - } - - // libsamplerate-related - _src_state_mic = src_new(SRC_SINC_BEST_QUALITY, 1, &_src_err); - _src_state_spkr = src_new(SRC_SINC_BEST_QUALITY, 1, &_src_err); - + // : _fstream("/tmp/audio.dat", std::ofstream::binary) +{ + setCancel(cancelDeferred); + time = new ost::Time(); + _ca = sipcall; + _sym = sym; + // AudioRtpRTX should be close if we change sample rate + + _codecSampleRate = _ca->getAudioCodec()->getClockRate(); + + // TODO: Change bind address according to user settings. + // TODO: this should be the local ip not the external (router) IP + std::string localipConfig = _ca->getLocalIp(); // _ca->getLocalIp(); + ost::InetHostAddress local_ip(localipConfig.c_str()); + + if (!_sym) { + _sessionRecv = new ost::RTPSession(local_ip, _ca->getLocalAudioPort()); + _sessionSend = new ost::RTPSession(local_ip, _ca->getLocalAudioPort()); + _session = NULL; + } else { + _session = new ost::SymmetricRTPSession (local_ip, _ca->getLocalAudioPort()); + _sessionRecv = NULL; + _sessionSend = NULL; + } + + // libsamplerate-related + // Set the converter type for the upsampling and the downsampling + // interpolator SRC_SINC_BEST_QUALITY + _src_state_mic = src_new(SRC_SINC_BEST_QUALITY, 1, &_src_err); + _src_state_spkr = src_new(SRC_SINC_BEST_QUALITY, 1, &_src_err); + } AudioRtpRTX::~AudioRtpRTX () { - _start.wait(); - - try { - this->terminate(); - } catch(...) { - _debugException("! ARTP: Thread destructor didn't terminate correctly"); - throw; - } - //_debug("terminate audiortprtx ended...\n"); - _ca = 0; - - if (!_sym) { - delete _sessionRecv; _sessionRecv = NULL; - delete _sessionSend; _sessionSend = NULL; - } else { - delete _session; _session = NULL; - } - - delete [] _intBuffer8000; _intBuffer8000 = NULL; - delete [] _floatBuffer48000; _floatBuffer48000 = NULL; - delete [] _floatBuffer8000; _floatBuffer8000 = NULL; - delete [] _dataAudioLayer; _dataAudioLayer = NULL; - - delete [] _sendDataEncoded; _sendDataEncoded = NULL; - delete [] _receiveDataDecoded; _receiveDataDecoded = NULL; - - delete time; time = NULL; - - // libsamplerate-related - _src_state_mic = src_delete(_src_state_mic); - _src_state_spkr = src_delete(_src_state_spkr); + _start.wait(); + + try { + this->terminate(); + } catch(...) { + _debugException("! ARTP: Thread destructor didn't terminate correctly"); + throw; + } + //_debug("terminate audiortprtx ended...\n"); + _ca = 0; + + if (!_sym) { + delete _sessionRecv; _sessionRecv = NULL; + delete _sessionSend; _sessionSend = NULL; + } else { + delete _session; _session = NULL; + } + + delete [] _intBufferDown; _intBufferDown = NULL; + delete [] _floatBufferUp; _floatBufferUp = NULL; + delete [] _floatBufferDown; _floatBufferDown = NULL; + delete [] _dataAudioLayer; _dataAudioLayer = NULL; + + delete [] _sendDataEncoded; _sendDataEncoded = NULL; + delete [] _receiveDataDecoded; _receiveDataDecoded = NULL; + + delete time; time = NULL; + + // libsamplerate-related + _src_state_mic = src_delete(_src_state_mic); + _src_state_spkr = src_delete(_src_state_spkr); } -void -AudioRtpRTX::initAudioRtpSession (void) + void +AudioRtpRTX::initBuffers() { - try { - if (_ca == 0) { return; } - - //_debug("Init audio RTP session\n"); - ost::InetHostAddress remote_ip(_ca->getRemoteIp().c_str()); - if (!remote_ip) { - _debug("! ARTP Thread Error: Target IP address [%s] is not correct!\n", _ca->getRemoteIp().data()); - return; - } - - // Initialization - if (!_sym) { - _sessionRecv->setSchedulingTimeout (10000); - _sessionRecv->setExpireTimeout(1000000); - - _sessionSend->setSchedulingTimeout(10000); - _sessionSend->setExpireTimeout(1000000); - } else { - _session->setSchedulingTimeout(10000); - _session->setExpireTimeout(1000000); - } - - if (!_sym) { - if ( !_sessionRecv->addDestination(remote_ip, (unsigned short) _ca->getRemoteAudioPort()) ) { - _debug("AudioRTP Thread Error: could not connect to port %d\n", _ca->getRemoteAudioPort()); - return; - } - if (!_sessionSend->addDestination (remote_ip, (unsigned short) _ca->getRemoteAudioPort())) { - _debug("! ARTP Thread Error: could not connect to port %d\n", _ca->getRemoteAudioPort()); - return; - } - - AudioCodec* audiocodec = _ca->getAudioCodec(); - bool payloadIsSet = false; - if (audiocodec) { - if (audiocodec->hasDynamicPayload()) { - payloadIsSet = _sessionRecv->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec->getPayload(), audiocodec->getClockRate())); - } else { - payloadIsSet= _sessionRecv->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload())); - payloadIsSet = _sessionSend->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload())); - } - } - _sessionSend->setMark(true); - } else { - - //_debug("AudioRTP Thread: Added session destination %s:%d\n", remote_ip.getHostname(), (unsigned short) _ca->getRemoteSdpAudioPort()); - - if (!_session->addDestination (remote_ip, (unsigned short) _ca->getRemoteAudioPort())) { - return; - } - - AudioCodec* audiocodec = _ca->getAudioCodec(); - bool payloadIsSet = false; - if (audiocodec) { - if (audiocodec->hasDynamicPayload()) { - payloadIsSet = _session->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec->getPayload(), audiocodec->getClockRate())); - } else { - payloadIsSet = _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload())); - } - } - } - } catch(...) { - _debugException("! ARTP Failure: initialisation failed"); - throw; - } + int nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000); + _dataAudioLayer = new SFLDataFormat[nbSamplesMax]; + _receiveDataDecoded = new int16[nbSamplesMax]; + _floatBufferDown = new float32[nbSamplesMax]; + _floatBufferUp = new float32[nbSamplesMax]; + _sendDataEncoded = new unsigned char[nbSamplesMax]; + _intBufferDown = new int16[nbSamplesMax]; } + void +AudioRtpRTX::initAudioRtpSession (void) +{ + try { + if (_ca == 0) { return; } + + //_debug("Init audio RTP session\n"); + ost::InetHostAddress remote_ip(_ca->getRemoteIp().c_str()); + if (!remote_ip) { + _debug("! ARTP Thread Error: Target IP address [%s] is not correct!\n", _ca->getRemoteIp().data()); + return; + } + + // Initialization + if (!_sym) { + _sessionRecv->setSchedulingTimeout (10000); + _sessionRecv->setExpireTimeout(1000000); + + _sessionSend->setSchedulingTimeout(10000); + _sessionSend->setExpireTimeout(1000000); + } else { + _session->setSchedulingTimeout(10000); + _session->setExpireTimeout(1000000); + } + + if (!_sym) { + if ( !_sessionRecv->addDestination(remote_ip, (unsigned short) _ca->getRemoteAudioPort()) ) { + _debug("AudioRTP Thread Error: could not connect to port %d\n", _ca->getRemoteAudioPort()); + return; + } + if (!_sessionSend->addDestination (remote_ip, (unsigned short) _ca->getRemoteAudioPort())) { + _debug("! ARTP Thread Error: could not connect to port %d\n", _ca->getRemoteAudioPort()); + return; + } + + AudioCodec* audiocodec = _ca->getAudioCodec(); + bool payloadIsSet = false; + if (audiocodec) { + if (audiocodec->hasDynamicPayload()) { + payloadIsSet = _sessionRecv->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec->getPayload(), audiocodec->getClockRate())); + } else { + payloadIsSet= _sessionRecv->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload())); + payloadIsSet = _sessionSend->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload())); + } + } + _sessionSend->setMark(true); + } else { + + //_debug("AudioRTP Thread: Added session destination %s:%d\n", remote_ip.getHostname(), (unsigned short) _ca->getRemoteSdpAudioPort()); + + if (!_session->addDestination (remote_ip, (unsigned short) _ca->getRemoteAudioPort())) { + return; + } + + AudioCodec* audiocodec = _ca->getAudioCodec(); + bool payloadIsSet = false; + if (audiocodec) { + if (audiocodec->hasDynamicPayload()) { + payloadIsSet = _session->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec->getPayload(), audiocodec->getClockRate())); + } else { + payloadIsSet = _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload())); + } + } + } + } catch(...) { + _debugException("! ARTP Failure: initialisation failed"); + throw; + } +} + void AudioRtpRTX::sendSessionFromMic(int timestamp) { - // STEP: - // 1. get data from mic - // 2. convert it to int16 - good sample, good rate - // 3. encode it - // 4. send it - try { - timestamp += time->getSecond(); - if (_ca==0) { _debug(" !ARTP: No call associated (mic)\n"); return; } // no call, so we do nothing - AudioLayer* audiolayer = Manager::instance().getAudioDriver(); - if (!audiolayer) { _debug(" !ARTP: No audiolayer available for mic\n"); return; } - - AudioCodec* audiocodec = _ca->getAudioCodec(); - if (!audiocodec) { _debug(" !ARTP: No audiocodec available for mic\n"); return; } - - // we have to get 20ms of data from the mic *20/1000 = /50 - // rate/50 shall be lower than RTP_20S_48KHZ_MAX - int maxBytesToGet = audiolayer->getSampleRate()/50*sizeof(SFLDataFormat); - - // available bytes inside ringbuffer - int availBytesFromMic = audiolayer->canGetMic(); - - // take the lowest - int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet; - //_debug("available = %d, maxBytesToGet = %d\n", availBytesFromMic, maxBytesToGet); - - // Get bytes from micRingBuffer to data_from_mic - int nbSample = audiolayer->getMic(_dataAudioLayer, bytesAvail) / sizeof(SFLDataFormat); - - int16* toSIP = NULL; - if (audiolayer->getSampleRate() != audiocodec->getClockRate() && nbSample) { - SRC_DATA src_data; - #ifdef DATAFORMAT_IS_FLOAT - src_data.data_in = _dataAudioLayer; - #else - src_short_to_float_array(_dataAudioLayer, _floatBuffer48000, nbSample); - src_data.data_in = _floatBuffer48000; - #endif - - double factord = (double) audiocodec->getClockRate() / audiolayer->getSampleRate(); - - src_data.src_ratio = factord; - src_data.input_frames = nbSample; - src_data.output_frames = (int) floor(factord * nbSample); - src_data.data_out = _floatBuffer8000; - src_data.end_of_input = 0; /* More data to come */ - - src_process(_src_state_mic, &src_data); - - nbSample = src_data.output_frames_gen; - - /* WRITE IN A FILE FOR DEBUG */ - //_fstream.write((char *) _floatBuffer48000, src_data.output_frames_gen * sizeof(float)); - //_fstream.flush(); - - - //if (nbSample > RTP_20S_8KHZ_MAX) { _debug("Alert from mic, nbSample %d is bigger than expected %d\n", nbSample, RTP_20S_8KHZ_MAX); } - - src_float_to_short_array (_floatBuffer8000, _intBuffer8000, nbSample); - toSIP = _intBuffer8000; - } else { - #ifdef DATAFORMAT_IS_FLOAT - // convert _receiveDataDecoded to float inside _receiveData - src_float_to_short_array(_dataAudioLayer, _intBuffer8000, nbSample); - toSIP = _intBuffer8000; - //if (nbSample > RTP_20S_8KHZ_MAX) { _debug("Alert from mic, nbSample %d is bigger than expected %d\n", nbSample, RTP_20S_8KHZ_MAX); } - #else - toSIP = _dataAudioLayer; // int to int - #endif - } - - if ( nbSample < (RTP_20S_8KHZ_MAX - 10) ) { // if only 10 is missing, it's ok - // fill end with 0... - //_debug("begin: %p, nbSample: %d\n", toSIP, nbSample); - //_debug("has to fill: %d chars at %p\n", (RTP_20S_8KHZ_MAX-nbSample)*sizeof(int16), toSIP + nbSample); - memset(toSIP + nbSample, 0, (RTP_20S_8KHZ_MAX-nbSample)*sizeof(int16)); - nbSample = RTP_20S_8KHZ_MAX; - } - //_debug("AR: Nb sample: %d int, [0]=%d [1]=%d [2]=%d\n", nbSample, toSIP[0], toSIP[1], toSIP[2]); - - // for the mono: range = 0 to RTP_FRAME2SEND * sizeof(int16) - // codecEncode(char *dest, int16* src, size in bytes of the src) - int compSize = audiocodec->codecEncode(_sendDataEncoded, toSIP, nbSample*sizeof(int16)); - - // encode divise by two - // Send encoded audio sample over the network - if (compSize > RTP_20S_8KHZ_MAX) { _debug("! ARTP: %d should be %d\n", compSize, RTP_20S_8KHZ_MAX);} - if (!_sym) { - _sessionSend->putData(timestamp, _sendDataEncoded, compSize); - } else { - _session->putData(timestamp, _sendDataEncoded, compSize); - } - toSIP = NULL; - } catch(...) { - _debugException("! ARTP: sending failed"); - throw; - } + // STEP: + // 1. get data from mic + // 2. convert it to int16 - good sample, good rate + // 3. encode it + // 4. send it + try { + int16* toSIP = NULL; + + timestamp += time->getSecond(); + if (_ca==0) { _debug(" !ARTP: No call associated (mic)\n"); return; } // no call, so we do nothing + AudioLayer* audiolayer = Manager::instance().getAudioDriver(); + if (!audiolayer) { _debug(" !ARTP: No audiolayer available for mic\n"); return; } + + AudioCodec* audiocodec = _ca->getAudioCodec(); + if (!audiocodec) { _debug(" !ARTP: No audiocodec available for mic\n"); return; } + + // we have to get 20ms of data from the mic *20/1000 = /50 + int maxBytesToGet = _layerSampleRate * _layerFrameSize * sizeof(SFLDataFormat) / 1000; + + // available bytes inside ringbuffer + int availBytesFromMic = audiolayer->canGetMic(); + + // take the lowest + int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet; + + // Get bytes from micRingBuffer to data_from_mic + int nbSample = audiolayer->getMic(_dataAudioLayer, bytesAvail) / sizeof(SFLDataFormat); + int nb_sample_up = nbSample; + int nbSamplesMax = _layerFrameSize * audiocodec->getClockRate() / 1000; + + nbSample = reSampleData(audiocodec->getClockRate(), nb_sample_up, DOWN_SAMPLING); + + toSIP = _intBufferDown; + + if ( nbSample < nbSamplesMax - 10 ) { // if only 10 is missing, it's ok + // fill end with 0... + //_debug("begin: %p, nbSample: %d\n", toSIP, nbSample); + memset(toSIP + nbSample, 0, (nbSamplesMax-nbSample)*sizeof(int16)); + nbSample = nbSamplesMax; + } + //_debug("AR: Nb sample: %d int, [0]=%d [1]=%d [2]=%d\n", nbSample, toSIP[0], toSIP[1], toSIP[2]); + + // for the mono: range = 0 to RTP_FRAME2SEND * sizeof(int16) + // codecEncode(char *dest, int16* src, size in bytes of the src) + int compSize = audiocodec->codecEncode(_sendDataEncoded, toSIP, nbSample*sizeof(int16)); + + // encode divise by two + // Send encoded audio sample over the network + if (compSize > nbSamplesMax) { _debug("! ARTP: %d should be %d\n", compSize, nbSamplesMax);} + if (!_sym) { + _sessionSend->putData(timestamp, _sendDataEncoded, compSize); + } else { + _session->putData(timestamp, _sendDataEncoded, compSize); + } + toSIP = NULL; + } catch(...) { + _debugException("! ARTP: sending failed"); + throw; + } } -void + + + void AudioRtpRTX::receiveSessionForSpkr (int& countTime) { - if (_ca == 0) { return; } - try { - AudioLayer* audiolayer = Manager::instance().getAudioDriver(); - if (!audiolayer) { return; } - - const ost::AppDataUnit* adu = NULL; - // Get audio data stream - - if (!_sym) { - adu = _sessionRecv->getData(_sessionRecv->getFirstTimestamp()); - } else { - adu = _session->getData(_session->getFirstTimestamp()); - } - if (adu == NULL) { - return; - } - - int payload = adu->getType(); // codec type - unsigned char* data = (unsigned char*)adu->getData(); // data in char - unsigned int size = adu->getSize(); // size in char - - if ( size > RTP_20S_8KHZ_MAX ) { - _debug("We have received from RTP a packet larger than expected: %s VS %s\n", size, RTP_20S_8KHZ_MAX); - _debug("The packet size has been cropped\n"); - size=RTP_20S_8KHZ_MAX; - } - - // NOTE: L'audio rendu ici (dans data/size) est parfait. - - // Decode data with relevant codec - AudioCodec* audiocodec = _ca->getCodecMap().getCodec((CodecType)payload); - if (audiocodec != NULL) { - // codecDecode(int16 *dest, char* src, size in bytes of the src) - // decode multiply by two, so the number of byte should be double - // size shall be RTP_FRAME2SEND or lower - int expandedSize = audiocodec->codecDecode(_receiveDataDecoded, data, size); - int nbInt16 = expandedSize / sizeof(int16); - if (nbInt16 > RTP_20S_8KHZ_MAX) { - _debug("We have decoded an RTP packet larger than expected: %s VS %s. Cropping.\n", nbInt16, RTP_20S_8KHZ_MAX); - nbInt16=RTP_20S_8KHZ_MAX; - } - - // NOTE: l'audio arrivé ici (dans _receiveDataDecoded/expandedSize) est parfait. - - SFLDataFormat* toAudioLayer; - int nbSample = nbInt16; - // 48000 / 8000 = 6, the number of samples for the maximum rate conversion. - int nbSampleMaxRate = nbInt16 * 6; // TODO: change it - - // We assume over here that we pass from a lower rate to a higher one. Bad bad. - if ( audiolayer->getSampleRate() != audiocodec->getClockRate() && nbSample) { - // Do sample rate conversion - - double factord = (double) audiolayer->getSampleRate() / audiocodec->getClockRate(); - - // SRC_DATA from samplerate.h - SRC_DATA src_data; - src_data.data_in = _floatBuffer8000; - src_data.data_out = _floatBuffer48000; - src_data.input_frames = nbSample; - src_data.output_frames = (int) floor(factord * nbSample); - src_data.src_ratio = factord; - src_data.end_of_input = 0; /* More data will come */ - src_short_to_float_array(_receiveDataDecoded, _floatBuffer8000, nbSample); - - // NOTE: L'audio arrivé ici (dans _floatBuffer8000/nbSample*sizeof(float) est parfait. - - src_process(_src_state_spkr, &src_data); - - // Truncate number of samples if too high (ouch!) - nbSample = ( src_data.output_frames_gen > RTP_20S_48KHZ_MAX) ? RTP_20S_48KHZ_MAX : src_data.output_frames_gen; - - #ifdef DATAFORMAT_IS_FLOAT - toAudioLayer = _floatBuffer48000; - #else - src_float_to_short_array(_floatBuffer48000, _dataAudioLayer, nbSample); - toAudioLayer = _dataAudioLayer; - #endif + if (_ca == 0) { return; } + try { + AudioLayer* audiolayer = Manager::instance().getAudioDriver(); + if (!audiolayer) { return; } + + const ost::AppDataUnit* adu = NULL; + // Get audio data stream + + if (!_sym) { + adu = _sessionRecv->getData(_sessionRecv->getFirstTimestamp()); + } else { + adu = _session->getData(_session->getFirstTimestamp()); + } + if (adu == NULL) { + return; + } + + int payload = adu->getType(); // codec type + unsigned char* data = (unsigned char*)adu->getData(); // data in char + unsigned int size = adu->getSize(); // size in char + + + // Decode data with relevant codec + AudioCodec* audiocodec = _ca->getCodecMap().getCodec((CodecType)payload); + _codecSampleRate = audiocodec->getClockRate(); + int max = (int)(_codecSampleRate * _layerFrameSize); + + if ( size > max ) { + _debug("We have received from RTP a packet larger than expected: %s VS %s\n", size, max); + _debug("The packet size has been cropped\n"); + size=max; + } + + + if (audiocodec != NULL) { + int expandedSize = audiocodec->codecDecode(_receiveDataDecoded, data, size); + //buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes + int nbInt16 = expandedSize / sizeof(int16); + //nbInt16 represents the number of samples we just decoded + if (nbInt16 > max) { + _debug("We have decoded an RTP packet larger than expected: %s VS %s. Cropping.\n", nbInt16, max); + nbInt16=max; + } + + SFLDataFormat* toAudioLayer; + int nbSample = nbInt16; + + // Do sample rate conversion + int nb_sample_down = nbSample; + nbSample = reSampleData(_codecSampleRate , nb_sample_down, UP_SAMPLING); +#ifdef DATAFORMAT_IS_FLOAT + toAudioLayer = _floatBufferUp; +#else + toAudioLayer = _dataAudioLayer; +#endif + + + audiolayer->putMain(toAudioLayer, nbSample * sizeof(SFLDataFormat)); + + // Notify (with a beep) an incoming call when there is already a call + countTime += time->getSecond(); + if (Manager::instance().incomingCallWaiting() > 0) { + countTime = countTime % 500; // more often... + if (countTime == 0) { + Manager::instance().notificationIncomingCall(); + } + } + + } else { + countTime += time->getSecond(); + } + + delete adu; adu = NULL; + } catch(...) { + _debugException("! ARTP: receiving failed"); + throw; + } +} - - } else { - nbSample = nbInt16; - #ifdef DATAFORMAT_IS_FLOAT - // convert _receiveDataDecoded to float inside _receiveData - src_short_to_float_array(_receiveDataDecoded, _floatBuffer8000, nbSample); - toAudioLayer = _floatBuffer8000; - #else - toAudioLayer = _receiveDataDecoded; // int to int - #endif - } - - audiolayer->putMain(toAudioLayer, nbSample * sizeof(SFLDataFormat)); - //_debug("ARTP: %d\n", nbSample * sizeof(SFLDataFormat)); - - // Notify (with a beep) an incoming call when there is already a call - countTime += time->getSecond(); - if (Manager::instance().incomingCallWaiting() > 0) { - countTime = countTime % 500; // more often... - if (countTime == 0) { - Manager::instance().notificationIncomingCall(); - } - } - - } else { - countTime += time->getSecond(); - } - - delete adu; adu = NULL; - } catch(...) { - _debugException("! ARTP: receiving failed"); - throw; - } +int +AudioRtpRTX::reSampleData(int sampleRate_codec, int nbSamples, int status) +{ + if(status==UP_SAMPLING) + return upSampleData(sampleRate_codec, nbSamples); + else if(status==DOWN_SAMPLING) + return downSampleData(sampleRate_codec, nbSamples); + else + return 0; } +//////////////////////////////////////////////////////////////////// +//////////// RESAMPLING FUNCTIONS ///////////////////////////////// +////////////////////////////////////////////////////////////////// + + int +AudioRtpRTX::upSampleData(int sampleRate_codec, int nbSamples) +{ + double upsampleFactor = (double) _layerSampleRate / sampleRate_codec; + int nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000); + if( upsampleFactor != 1 ) + { + SRC_DATA src_data; + src_data.data_in = _floatBufferDown; + src_data.data_out = _floatBufferUp; + src_data.input_frames = nbSamples; + src_data.output_frames = (int) floor(upsampleFactor * nbSamples); + src_data.src_ratio = upsampleFactor; + src_data.end_of_input = 0; // More data will come + src_short_to_float_array(_receiveDataDecoded, _floatBufferDown, nbSamples); + src_process(_src_state_spkr, &src_data); + nbSamples = ( src_data.output_frames_gen > nbSamplesMax) ? nbSamplesMax : src_data.output_frames_gen; + src_float_to_short_array(_floatBufferUp, _dataAudioLayer, nbSamples); + } + + return nbSamples; +} + + int +AudioRtpRTX::downSampleData(int sampleRate_codec, int nbSamples) +{ + double downsampleFactor = (double) sampleRate_codec / _layerSampleRate; + int nbSamplesMax = (int) (sampleRate_codec * _layerFrameSize / 1000); + if ( downsampleFactor != 1) + { + SRC_DATA src_data; + src_data.data_in = _floatBufferUp; + src_data.data_out = _floatBufferDown; + src_data.input_frames = nbSamples; + src_data.output_frames = (int) floor(downsampleFactor * nbSamples); + src_data.src_ratio = downsampleFactor; + src_data.end_of_input = 0; // More data will come + src_short_to_float_array(_dataAudioLayer, _floatBufferUp, nbSamples); + src_process(_src_state_mic, &src_data); + nbSamples = ( src_data.output_frames_gen > nbSamplesMax) ? nbSamplesMax : src_data.output_frames_gen; + src_float_to_short_array(_floatBufferDown, _intBufferDown, nbSamples); + } + return nbSamples; + +} + +//////////////////////// END RESAMPLING ////////////////////////////////////////////////////// + void AudioRtpRTX::run () { - //mic, we receive from soundcard in stereo, and we send encoded - //encoding before sending - AudioLayer *audiolayer = Manager::instance().getAudioDriver(); - - try { - // Init the session - initAudioRtpSession(); - - // start running the packet queue scheduler. - //_debug("AudioRTP Thread started\n"); - if (!_sym) { - _sessionRecv->startRunning(); - _sessionSend->startRunning(); - } else { - _session->startRunning(); - //_debug("Session is now: %d active\n", _session->isActive()); - } - - int timestamp = 0; // for mic - int countTime = 0; // for receive - // TODO: get frameSize from user config - int frameSize = 20; // 20ms frames - TimerPort::setTimer(frameSize); - - audiolayer->flushMic(); - audiolayer->startStream(); - _start.post(); - _debug("- ARTP Action: Start\n"); - while (!testCancel()) { - //////////////////////////// - // Send session - //////////////////////////// - sendSessionFromMic(timestamp); - timestamp += RTP_20S_8KHZ_MAX; - - //////////////////////////// - // Recv session - //////////////////////////// - receiveSessionForSpkr(countTime); - - // Let's wait for the next transmit cycle - Thread::sleep(TimerPort::getTimer()); - TimerPort::incTimer(frameSize); // 'frameSize' ms - } - //_debug("stop stream for audiortp loop\n"); - audiolayer->stopStream(); - } catch(std::exception &e) { - _start.post(); - _debug("! ARTP: Stop %s\n", e.what()); - throw; - } catch(...) { - _start.post(); - _debugException("* ARTP Action: Stop"); - throw; - } + //mic, we receive from soundcard in stereo, and we send encoded + //encoding before sending + AudioLayer *audiolayer = Manager::instance().getAudioDriver(); + + _layerFrameSize = audiolayer->getFrameSize(); // en ms + _layerSampleRate = audiolayer->getSampleRate(); + initBuffers(); + int step = (int)(_layerFrameSize * _codecSampleRate / 1000); + + try { + // Init the session + initAudioRtpSession(); + + // start running the packet queue scheduler. + //_debug("AudioRTP Thread started\n"); + if (!_sym) { + _sessionRecv->startRunning(); + _sessionSend->startRunning(); + } else { + _session->startRunning(); + //_debug("Session is now: %d active\n", _session->isActive()); + } + + int timestamp = 0; // for mic + int countTime = 0; // for receive + TimerPort::setTimer(_layerFrameSize); + + audiolayer->flushMic(); + audiolayer->startStream(); + _start.post(); + _debug("- ARTP Action: Start\n"); + while (!testCancel()) { + //////////////////////////// + // Send session + //////////////////////////// + sendSessionFromMic(timestamp); + timestamp += step; + //////////////////////////// + // Recv session + //////////////////////////// + receiveSessionForSpkr(countTime); + + // Let's wait for the next transmit cycle + Thread::sleep(TimerPort::getTimer()); + TimerPort::incTimer(_layerFrameSize); // 'frameSize' ms + } + //_debug("stop stream for audiortp loop\n"); + audiolayer->stopStream(); + } catch(std::exception &e) { + _start.post(); + _debug("! ARTP: Stop %s\n", e.what()); + throw; + } catch(...) { + _start.post(); + _debugException("* ARTP Action: Stop"); + throw; + } } diff --git a/src/audio/audiortp.h b/src/audio/audiortp.h index 4b018276929b5a2c63d95bcb79027a1ffc3c8580..2444be567611e17b4858ef8321baed96a7c91500 100644 --- a/src/audio/audiortp.h +++ b/src/audio/audiortp.h @@ -1,12 +1,13 @@ /* * Copyright (C) 2004-2007 Savoir-Faire Linux inc. + * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> * Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -33,81 +34,108 @@ #include "../global.h" -/** maximum bytes inside an incoming packet - * 8000 sampling/s * 20s/1000 = 160 - */ -#define RTP_20S_8KHZ_MAX 160 -#define RTP_20S_48KHZ_MAX 960 +#define UP_SAMPLING 0 +#define DOWN_SAMPLING 1 + + class SIPCall; /////////////////////////////////////////////////////////////////////////////// // Two pair of sockets /////////////////////////////////////////////////////////////////////////////// class AudioRtpRTX : public ost::Thread, public ost::TimerPort { -public: - AudioRtpRTX (SIPCall *, bool); - ~AudioRtpRTX(); - - ost::Time *time; // For incoming call notification - virtual void run (); - -private: - SIPCall* _ca; - ost::RTPSession *_sessionSend; - ost::RTPSession *_sessionRecv; - ost::SymmetricRTPSession *_session; - ost::Semaphore _start; - bool _sym; - - /** When we receive data, we decode it inside this buffer */ - int16* _receiveDataDecoded; - /** When we send data, we encode it inside this buffer*/ - unsigned char* _sendDataEncoded; - - /** After that we send the data inside this buffer if there is a format conversion or rate conversion */ - /** Also use for getting mic-ringbuffer data */ - SFLDataFormat* _dataAudioLayer; - - /** Buffer for 8000hz samples in conversion */ - float32* _floatBuffer8000; - /** Buffer for 48000hz samples in conversion */ - float32* _floatBuffer48000; - - /** Buffer for 8000Hz samples for mic conversion */ - int16* _intBuffer8000; - - /** Debugging output file */ - //std::ofstream _fstream; - - /** libsamplerate converter for incoming voice */ - SRC_STATE* _src_state_spkr; - - /** libsamplerate converter for outgoing voice */ - SRC_STATE* _src_state_mic; - - /** libsamplerate error */ - int _src_err; - - void initAudioRtpSession(void); - void sendSessionFromMic(int); - void receiveSessionForSpkr(int&); + public: + AudioRtpRTX (SIPCall *, bool); + ~AudioRtpRTX(); + + ost::Time *time; // For incoming call notification + virtual void run (); + + private: + SIPCall* _ca; + ost::RTPSession *_sessionSend; + ost::RTPSession *_sessionRecv; + ost::SymmetricRTPSession *_session; + ost::Semaphore _start; + bool _sym; + + /** When we receive data, we decode it inside this buffer */ + int16* _receiveDataDecoded; + /** Buffers used for send data from the mic */ + unsigned char* _sendDataEncoded; + int16* _intBufferDown; + + /** After that we send the data inside this buffer if there is a format conversion or rate conversion */ + /** Also use for getting mic-ringbuffer data */ + SFLDataFormat* _dataAudioLayer; + + /** Buffers used for sample rate conversion */ + float32* _floatBufferDown; + float32* _floatBufferUp; + + /** Debugging output file */ + //std::ofstream _fstream; + + /** libsamplerate converter for incoming voice */ + SRC_STATE* _src_state_spkr; + /** libsamplerate converter for outgoing voice */ + SRC_STATE* _src_state_mic; + /** libsamplerate error */ + int _src_err; + + // Variables to process audio stream + int _layerSampleRate; // sample rate for playing sound (typically 44100HZ) + int _codecSampleRate; // sample rate of the codec we use to encode and decode (most of time 8000HZ) + int _layerFrameSize; // length of the sound frame we capture in ms(typically 20ms) + + void initAudioRtpSession(void); + /** + * Get the data from the mic, encode it and send it through the RTP session + */ + void sendSessionFromMic(int); + /** + * Get the data from the RTP packets, decode it and send it to the sound card + */ + void receiveSessionForSpkr(int&); + /** + * Init the buffers used for processing sound data + */ + void initBuffers(void); + /** + * Call the appropriate function, up or downsampling + */ + int reSampleData(int, int ,int); + /** + * Upsample the data from the clock rate of the codec to the sample rate of the layer + * @param int The clock rate of the codec + * @param int The number of samples we have in the buffer + * @return int The number of samples after the operation + */ + int upSampleData(int, int); + /** + * Downsample the data from the sample rate of the layer to the clock rate of the codec + * @param int The clock rate of the codec + * @param int The number of samples we have in the buffer + * @return int The number of samples after the operation + */ + int downSampleData(int, int); }; /////////////////////////////////////////////////////////////////////////////// // Main class rtp /////////////////////////////////////////////////////////////////////////////// class AudioRtp { -public: - AudioRtp(); - ~AudioRtp(); + public: + AudioRtp(); + ~AudioRtp(); - int createNewSession (SIPCall *); - void closeRtpSession (); + int createNewSession (SIPCall *); + void closeRtpSession (); -private: - AudioRtpRTX* _RTXThread; - bool _symmetric; - ost::Mutex _threadMutex; + private: + AudioRtpRTX* _RTXThread; + bool _symmetric; + ost::Mutex _threadMutex; }; #endif // __AUDIO_RTP_H__ diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp index 0e92c0c9711f5953afcf2e193ad1e8def3230385..de29ed38b9968313c6eb80652b8edb6338132156 100644 --- a/src/managerimpl.cpp +++ b/src/managerimpl.cpp @@ -1050,7 +1050,8 @@ ManagerImpl::initConfigFile (void) //fill_config_int(DRIVER_NAME, DFT_DRIVER_STR); fill_config_int(DRIVER_NAME_IN, DFT_DRIVER_STR); fill_config_int(DRIVER_NAME_OUT, DFT_DRIVER_STR); - fill_config_int(DRIVER_SAMPLE_RATE, DRIVER_SAMPLE_RATE_DEFAULT); + fill_config_int(DRIVER_SAMPLE_RATE, DFT_SAMPLE_RATE); + fill_config_int(DRIVER_FRAME_SIZE, DFT_FRAME_SIZE); fill_config_str(CODEC1, DFT_CODEC); fill_config_str(CODEC2, DFT_CODEC); fill_config_str(CODEC3, DFT_CODEC); @@ -1118,6 +1119,7 @@ ManagerImpl::selectAudioDriver (void) if (sampleRate <=0 || sampleRate > 48000) { sampleRate = 8000; } + int frameSize = getConfigInt(AUDIO, DRIVER_FRAME_SIZE); // this is when no audio device in/out are set // or the audio device in/out are set to 0 @@ -1128,7 +1130,7 @@ ManagerImpl::selectAudioDriver (void) //} _debugInit(" AudioLayer Opening Device"); _audiodriver->setErrorMessage(""); - _audiodriver->openDevice(noDeviceIn, noDeviceOut, sampleRate); + _audiodriver->openDevice(noDeviceIn, noDeviceOut, sampleRate, frameSize); } /** @@ -1787,10 +1789,11 @@ ManagerImpl::removeAccount(const AccountID& accountID) std::string ManagerImpl::getDefaultAccount() { + std::string id; id = getConfigString(PREFERENCES, "DefaultAccount"); _debug("Default Account = %s\n",id.c_str()); - return id; + return id; } void diff --git a/src/user_cfg.h b/src/user_cfg.h index 0d9319d12b616a73abd31e8d5ff1594370a9219d..53e51cdd561df403ad334ae85bf76c3eb9f62b0a 100644 --- a/src/user_cfg.h +++ b/src/user_cfg.h @@ -62,7 +62,7 @@ #define DRIVER_NAME_IN "Drivers.driverNameIn" #define DRIVER_NAME_OUT "Drivers.driverNameOut" #define DRIVER_SAMPLE_RATE "Drivers.sampleRate" -#define DRIVER_SAMPLE_RATE_DEFAULT "8000" +#define DRIVER_FRAME_SIZE "Drivers.framesize" #define NB_CODEC "Codecs.nbCodec" #define CODEC1 "Codecs.codec1" #define CODEC2 "Codecs.codec2" @@ -102,6 +102,8 @@ #define DFT_SKIN "metal" #define DFT_ZONE "North America" #define DFT_VOICEMAIL "888" +#define DFT_FRAME_SIZE "20" +#define DFT_SAMPLE_RATE "44100" // zeroconfig default value #ifdef USE_ZEROCONF #define CONFIG_ZEROCONF_DEFAULT_STR "1"