Commit fa57bac5 authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

use sampling frequency and frame size from the user config

Sampling rate values are no more hardcoded. The sampling rate of the audio layer
 and the frame size can be set in the user config file. The clock rate of the codec we use
in the rtp session is set with his actual value, but can be changed by modifying
the available codec in the user config file (only G711 for now)
parent 9c76e463
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
* Copyright (C) 2005 Savoir-Faire Linux inc. * Copyright (C) 2005 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Yan Morin <yan.morin@savoirfairelinux.com>
* Author: Jerome Oufella <jerome.oufella@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 * 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 * 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. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
...@@ -108,13 +109,15 @@ AudioLayer::hasStream(void) { ...@@ -108,13 +109,15 @@ AudioLayer::hasStream(void) {
void void
AudioLayer::openDevice (int indexIn, int indexOut, int sampleRate) AudioLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize)
{ {
closeStream(); closeStream();
_sampleRate = sampleRate; _sampleRate = sampleRate;
_frameSize = frameSize;
int portaudioFramePerBuffer = FRAME_PER_BUFFER; //=FRAME_PER_BUFFER; //= paFramesPerBufferUnspecified; int portaudioFramePerBuffer = FRAME_PER_BUFFER; //=FRAME_PER_BUFFER; //= paFramesPerBufferUnspecified;
//int portaudioFramePerBuffer = (int) (8000 * frameSize / 1000);
//= paFramesPerBufferUnspecified;
int nbDevice = getDeviceCount(); int nbDevice = getDeviceCount();
if (nbDevice == 0) { if (nbDevice == 0) {
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
* Copyright (C) 2004-2005 Savoir-Faire Linux inc. * Copyright (C) 2004-2005 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Yan Morin <yan.morin@savoirfairelinux.com>
* Author: Jerome Oufella <jerome.oufella@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 * 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 * 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. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
...@@ -35,96 +36,103 @@ class RingBuffer; ...@@ -35,96 +36,103 @@ class RingBuffer;
class ManagerImpl; class ManagerImpl;
class AudioLayer { class AudioLayer {
public: public:
AudioLayer(ManagerImpl* manager); AudioLayer(ManagerImpl* manager);
~AudioLayer(void); ~AudioLayer(void);
/* /*
* @param indexIn * @param indexIn
* @param indexOut * @param indexOut
* @param sampleRate * @param sampleRate
*/ * @param frameSize
void openDevice(int, int, int); */
void startStream(void); void openDevice(int, int, int, int);
void stopStream(void); void startStream(void);
void sleep(int); void stopStream(void);
bool hasStream(void); void sleep(int);
bool isStreamActive(void); bool hasStream(void);
bool isStreamStopped(void); bool isStreamActive(void);
bool isStreamStopped(void);
void flushMain();
int putMain(void* buffer, int toCopy); void flushMain();
int putUrgent(void* buffer, int toCopy); int putMain(void* buffer, int toCopy);
int canGetMic(); int putUrgent(void* buffer, int toCopy);
int getMic(void *, int); int canGetMic();
void flushMic(); int getMic(void *, int);
void flushMic();
int audioCallback (const void *, void *, unsigned long,
const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags); int audioCallback (const void *, void *, unsigned long,
int miniAudioCallback (const void *, void *, unsigned long, const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags);
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; } void setErrorMessage(const std::string& error) { _errorMessage = error; }
std::string getErrorMessage() { return _errorMessage; }
/**
* Get the sample rate of audiolayer /**
* accessor only * Get the sample rate of audiolayer
*/ * accessor only
unsigned int getSampleRate() { return _sampleRate; } */
unsigned int getSampleRate() { return _sampleRate; }
int getDeviceCount(); unsigned int getFrameSize() { return _frameSize; }
AudioDevice* getAudioDeviceInfo(int index, int ioDeviceMask); int getDeviceCount();
AudioDevice* getAudioDeviceInfo(int index, int ioDeviceMask);
enum IODEVICE {InputDevice=0x01, OutputDevice=0x02 };
enum IODEVICE {InputDevice=0x01, OutputDevice=0x02 };
/**
* Toggle echo testing on/off /**
*/ * Toggle echo testing on/off
void toggleEchoTesting(); */
void toggleEchoTesting();
private:
void closeStream (void); private:
RingBuffer _urgentRingBuffer; void closeStream (void);
RingBuffer _mainSndRingBuffer; RingBuffer _urgentRingBuffer;
RingBuffer _micRingBuffer; RingBuffer _mainSndRingBuffer;
ManagerImpl* _manager; // augment coupling, reduce indirect access RingBuffer _micRingBuffer;
// a audiolayer can't live without manager ManagerImpl* _manager; // augment coupling, reduce indirect access
// a audiolayer can't live without manager
portaudio::MemFunCallbackStream<AudioLayer> *_stream;
portaudio::MemFunCallbackStream<AudioLayer> *_stream;
/**
* Sample Rate of SFLphone : should be 8000 for 8khz /**
* Added because we could change it in the futur * 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; */
unsigned int _sampleRate;
/**
* Input channel (mic) should be 1 mono /**
*/ * Length of the sound frame we capture or read in ms
unsigned int _inChannel; // mic * The value can be set in the user config file - now: 20ms
*/
/** unsigned int _frameSize;
* Output channel (stereo) should be 1 mono
*/ /**
unsigned int _outChannel; // speaker * Input channel (mic) should be 1 mono
*/
/** unsigned int _inChannel; // mic
* Default volume for incoming RTP and Urgent sounds.
*/ /**
unsigned short _defaultVolume; // 100 * Output channel (stereo) should be 1 mono
*/
/** unsigned int _outChannel; // speaker
* Echo testing or not
*/ /**
bool _echoTesting; * Default volume for incoming RTP and Urgent sounds.
*/
std::string _errorMessage; unsigned short _defaultVolume; // 100
ost::Mutex _mutex;
/**
float *table_; * Echo testing or not
int tableSize_; */
int leftPhase_; bool _echoTesting;
std::string _errorMessage;
ost::Mutex _mutex;
float *table_;
int tableSize_;
int leftPhase_;
}; };
#endif // _AUDIO_LAYER_H_ #endif // _AUDIO_LAYER_H_
......
This diff is collapsed.
/* /*
* Copyright (C) 2004-2007 Savoir-Faire Linux inc. * Copyright (C) 2004-2007 Savoir-Faire Linux inc.
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
* Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
* Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Yan Morin <yan.morin@savoirfairelinux.com>
* Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * 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. * (at your option) any later version.
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
...@@ -33,81 +34,108 @@ ...@@ -33,81 +34,108 @@
#include "../global.h" #include "../global.h"
/** maximum bytes inside an incoming packet #define UP_SAMPLING 0
* 8000 sampling/s * 20s/1000 = 160 #define DOWN_SAMPLING 1
*/
#define RTP_20S_8KHZ_MAX 160
#define RTP_20S_48KHZ_MAX 960
class SIPCall; class SIPCall;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Two pair of sockets // Two pair of sockets
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class AudioRtpRTX : public ost::Thread, public ost::TimerPort { class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
public: public:
AudioRtpRTX (SIPCall *, bool); AudioRtpRTX (SIPCall *, bool);
~AudioRtpRTX(); ~AudioRtpRTX();
ost::Time *time; // For incoming call notification ost::Time *time; // For incoming call notification
virtual void run (); virtual void run ();
private: private:
SIPCall* _ca; SIPCall* _ca;
ost::RTPSession *_sessionSend; ost::RTPSession *_sessionSend;
ost::RTPSession *_sessionRecv; ost::RTPSession *_sessionRecv;
ost::SymmetricRTPSession *_session; ost::SymmetricRTPSession *_session;
ost::Semaphore _start; ost::Semaphore _start;
bool _sym; bool _sym;
/** When we receive data, we decode it inside this buffer */ /** When we receive data, we decode it inside this buffer */
int16* _receiveDataDecoded; int16* _receiveDataDecoded;
/** When we send data, we encode it inside this buffer*/ /** Buffers used for send data from the mic */
unsigned char* _sendDataEncoded; 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 */ /** After that we send the data inside this buffer if there is a format conversion or rate conversion */
SFLDataFormat* _dataAudioLayer; /** Also use for getting mic-ringbuffer data */
SFLDataFormat* _dataAudioLayer;
/** Buffer for 8000hz samples in conversion */
float32* _floatBuffer8000; /** Buffers used for sample rate conversion */
/** Buffer for 48000hz samples in conversion */ float32* _floatBufferDown;
float32* _floatBuffer48000; float32* _floatBufferUp;
/** Buffer for 8000Hz samples for mic conversion */ /** Debugging output file */
int16* _intBuffer8000; //std::ofstream _fstream;
/** Debugging output file */ /** libsamplerate converter for incoming voice */
//std::ofstream _fstream; SRC_STATE* _src_state_spkr;
/** libsamplerate converter for outgoing voice */
/** libsamplerate converter for incoming voice */ SRC_STATE* _src_state_mic;
SRC_STATE* _src_state_spkr; /** libsamplerate error */
int _src_err;
/** libsamplerate converter for outgoing voice */
SRC_STATE* _src_state_mic; // Variables to process audio stream
int _layerSampleRate; // sample rate for playing sound (typically 44100HZ)
/** libsamplerate error */ int _codecSampleRate; // sample rate of the codec we use to encode and decode (most of time 8000HZ)
int _src_err; int _layerFrameSize; // length of the sound frame we capture in ms(typically 20ms)
void initAudioRtpSession(void); void initAudioRtpSession(void);
void sendSessionFromMic(int); /**
void receiveSessionForSpkr(int&); * 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 // Main class rtp
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class AudioRtp { class AudioRtp {
public: public:
AudioRtp(); AudioRtp();
~AudioRtp(); ~AudioRtp();
int createNewSession (SIPCall *); int createNewSession (SIPCall *);
void closeRtpSession (); void closeRtpSession ();
private: private:
AudioRtpRTX* _RTXThread; AudioRtpRTX* _RTXThread;
bool _symmetric; bool _symmetric;
ost::Mutex _threadMutex; ost::Mutex _threadMutex;
}; };
#endif // __AUDIO_RTP_H__ #endif // __AUDIO_RTP_H__
...@@ -1050,7 +1050,8 @@ ManagerImpl::initConfigFile (void) ...@@ -1050,7 +1050,8 @@ ManagerImpl::initConfigFile (void)
//fill_config_int(DRIVER_NAME, DFT_DRIVER_STR); //fill_config_int(DRIVER_NAME, DFT_DRIVER_STR);
fill_config_int(DRIVER_NAME_IN, 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_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(CODEC1, DFT_CODEC);
fill_config_str(CODEC2, DFT_CODEC); fill_config_str(CODEC2, DFT_CODEC);
fill_config_str(CODEC3, DFT_CODEC); fill_config_str(CODEC3, DFT_CODEC);
...@@ -1118,6 +1119,7 @@ ManagerImpl::selectAudioDriver (void) ...@@ -1118,6 +1119,7 @@ ManagerImpl::selectAudioDriver (void)
if (sampleRate <=0 || sampleRate > 48000) { if (sampleRate <=0 || sampleRate > 48000) {
sampleRate = 8000; sampleRate = 8000;
} }
int frameSize = getConfigInt(AUDIO, DRIVER_FRAME_SIZE);
// this is when no audio device in/out are set // this is when no audio device in/out are set
// or the audio device in/out are set to 0 // or the audio device in/out are set to 0
...@@ -1128,7 +1130,7 @@ ManagerImpl::selectAudioDriver (void) ...@@ -1128,7 +1130,7 @@ ManagerImpl::selectAudioDriver (void)
//} //}
_debugInit(" AudioLayer Opening Device"); _debugInit(" AudioLayer Opening Device");
_audiodriver->setErrorMessage(""); _audiodriver->setErrorMessage("");
_audiodriver->openDevice(noDeviceIn, noDeviceOut, sampleRate); _audiodriver->openDevice(noDeviceIn, noDeviceOut, sampleRate, frameSize);
} }
/** /**
...@@ -1787,10 +1789,11 @@ ManagerImpl::removeAccount(const AccountID& accountID) ...@@ -1787,10 +1789,11 @@ ManagerImpl::removeAccount(const AccountID& accountID)
std::string std::string
ManagerImpl::getDefaultAccount() ManagerImpl::getDefaultAccount()
{ {
std::string id; std::string id;
id = getConfigString(PREFERENCES, "DefaultAccount"); id = getConfigString(PREFERENCES, "DefaultAccount");
_debug("Default Account = %s\n",id.c_str()); _debug("Default Account = %s\n",id.c_str());
return id; return id;
} }
void void
......
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
#define DRIVER_NAME_IN "Drivers.driverNameIn" #define DRIVER_NAME_IN "Drivers.driverNameIn"
#define DRIVER_NAME_OUT "Drivers.driverNameOut" #define DRIVER_NAME_OUT "Drivers.driverNameOut"
#define DRIVER_SAMPLE_RATE "Drivers.sampleRate" #define DRIVER_SAMPLE_RATE "Drivers.sampleRate"
#define DRIVER_SAMPLE_RATE_DEFAULT "8000" #define DRIVER_FRAME_SIZE "Drivers.framesize"
#define NB_CODEC "Codecs.nbCodec" #define NB_CODEC "Codecs.nbCodec"
#define CODEC1 "Codecs.codec1" #define CODEC1 "Codecs.codec1"
#define CODEC2 "Codecs.codec2" #define CODEC2 "Codecs.codec2"
...@@ -102,6 +102,8 @@ ...@@ -102,6 +102,8 @@
#define DFT_SKIN "metal" #define DFT_SKIN "metal"
#define DFT_ZONE "North America" #define DFT_ZONE "North America"
#define DFT_VOICEMAIL "888" #define DFT_VOICEMAIL "888"
#define DFT_FRAME_SIZE "20"
#define DFT_SAMPLE_RATE "44100"
// zeroconfig default value // zeroconfig default value
#ifdef USE_ZEROCONF #ifdef USE_ZEROCONF
#define CONFIG_ZEROCONF_DEFAULT_STR "1" #define CONFIG_ZEROCONF_DEFAULT_STR "1"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment