diff --git a/sflphone-common/src/audio/audioloop.h b/sflphone-common/src/audio/audioloop.h index b68a139d86882a17df59645b5803ffb2c8c91637..2eb1c7bc4e86c1e6e366250529888dedad5d8a78 100644 --- a/sflphone-common/src/audio/audioloop.h +++ b/sflphone-common/src/audio/audioloop.h @@ -84,7 +84,7 @@ class AudioLoop /** The data buffer */ SFLDataFormat* _buffer; - /** Number of int16 inside the buffer, not the delay */ + /** Number of samples inside the buffer */ int _size; /** current position, set to 0, when initialize */ diff --git a/sflphone-common/src/audio/sound/audiofile.cpp b/sflphone-common/src/audio/sound/audiofile.cpp index f5e8ecdf6cc4aed2c51fed21fcdc690ab34f47df..1c78ab490e5e07bfb32c911279e69dbedd7b9797 100644 --- a/sflphone-common/src/audio/sound/audiofile.cpp +++ b/sflphone-common/src/audio/sound/audiofile.cpp @@ -1,7 +1,4 @@ -/* - - if(_dbus) - _dbus * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc. +/** Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc. * Author: Yan Morin <yan.morin@savoirfairelinux.com> * * Inspired by tonegenerator of @@ -46,25 +43,10 @@ #include "manager.h" -RawFile::RawFile() : audioCodec (NULL) -{ - AudioFile::_start = false; -} - -RawFile::~RawFile() -{ -} - // load file in mono format -void RawFile::loadFile (const std::string& name, sfl::AudioCodec* codec, unsigned int sampleRate = 8000) throw(AudioFileException) +RawFile::RawFile(const std::string& name, sfl::AudioCodec* codec, unsigned int sampleRate) + : audioCodec (codec) { - audioCodec = codec; - - // if the filename was already load, with the same samplerate - // we do nothing - if (filepath == name && _sampleRate == sampleRate) - return; - filepath = name; // no filename to load @@ -159,80 +141,28 @@ void RawFile::loadFile (const std::string& name, sfl::AudioCodec* codec, unsigne } - - -WaveFile::WaveFile () : byteCounter (0) - , nbChannels (1) - , fileLength (0) - , dataOffset (0) - , channels (0) - , dataType (0) - , fileRate (0) -{ - AudioFile::_start = false; -} - - -WaveFile::~WaveFile() -{ - _debug ("WaveFile: Destructor Called!"); -} - - - -void WaveFile::openFile (const std::string& fileName, unsigned int audioSamplingRate) throw(AudioFileException) -{ - try { - - if (isFileExist (fileName)) { - openExistingWaveFile (fileName, audioSamplingRate); - } - } - catch(AudioFileException &e) { - throw; - } -} - - -bool WaveFile::isFileExist (const std::string& fileName) +WaveFile::WaveFile (const std::string& fileName, unsigned int audioSamplingRate) { std::fstream fs (fileName.c_str(), std::ios_base::in); + if (!fs) + throw AudioFileException("File " + fileName + " doesn't exist"); - if (!fs) { - _debug ("WaveFile: file \"%s\" doesn't exist", fileName.c_str()); - return false; - } - - _debug ("WaveFile: File \"%s\" exists", fileName.c_str()); - return true; -} - - -void WaveFile::openExistingWaveFile (const std::string& fileName, unsigned int audioSamplingRate) throw(AudioFileException) -{ - - int maxIteration = 0; - - _debug ("WaveFile: Opening %s", fileName.c_str()); filepath = fileName; - + std::fstream fileStream; fileStream.open (fileName.c_str(), std::ios::in | std::ios::binary); - char riff[4] = {}; + char riff[4] = { 0, 0, 0, 0 }; fileStream.read (riff, 4); - if (strncmp ("RIFF", riff, 4) != 0) { + if (strncmp ("RIFF", riff, 4) != 0) throw AudioFileException("File is not of RIFF format"); - } - char fmt[4] = {}; - maxIteration = 10; - while ((maxIteration > 0) && strncmp ("fmt ", fmt, 4)) { + char fmt[4] = { 0, 0, 0, 0 }; + int maxIteration = 10; + while (maxIteration-- && strncmp ("fmt ", fmt, 4)) fileStream.read (fmt, 4); - maxIteration--; - } - if(maxIteration == 0) { + + if(maxIteration == 0) throw AudioFileException("Could not find \"fmt \" chunk"); - } SINT32 chunk_size; // fmt chunk size unsigned short formatTag; // data compression tag @@ -240,185 +170,95 @@ void WaveFile::openExistingWaveFile (const std::string& fileName, unsigned int a fileStream.read ( (char*) &chunk_size, 4); // Read fmt chunk size. fileStream.read ( (char*) &formatTag, 2); - _debug ("WaveFile: Chunk size: %d", chunk_size); - _debug ("WaveFile: Format tag: %d", formatTag); - - if (formatTag != 1) { // PCM = 1, FLOAT = 3 + if (formatTag != 1) // PCM = 1, FLOAT = 3 throw AudioFileException("File contains an unsupported data format type"); - } // Get number of channels from the header. SINT16 chan; fileStream.read ( (char*) &chan, 2); - channels = chan; - _debug ("WaveFile: Channel %d", channels); + if(chan > 2) + throw AudioFileException("WaveFile: unsupported number of channels"); // Get file sample rate from the header. SINT32 srate; fileStream.read ( (char*) &srate, 4); - fileRate = (double) srate; - _debug ("WaveFile: Sampling rate %d", srate); SINT32 avgb; fileStream.read ( (char*) &avgb, 4); - _debug ("WaveFile: Average byte %d", avgb);\ SINT16 blockal; fileStream.read ( (char*) &blockal, 2); - _debug ("WaveFile: Block alignment %d", blockal); - // Determine the data type - dataType = 0; + SOUND_FORMAT dataType; SINT16 dt; fileStream.read ( (char*) &dt, 2); - _debug ("WaveFile: dt %d", dt); - if (formatTag == 1) { - if (dt == 8) - dataType = 1; // SINT8; - else if (dt == 16) - dataType = 2; // SINT16; - else if (dt == 32) - dataType = 3; // SINT32; - } - else { - throw AudioFileException("File's bits per sample with is not supported"); - } + if (dt == 8) + dataType = 1; // SINT8; + else if (dt == 16) + dataType = 2; // SINT16; + else if (dt == 32) + dataType = 3; // SINT32; + else { + throw AudioFileException("File's bits per sample with is not supported"); + } // Find the "data" chunk - char data[4] = {}; + char data[4] = { 0, 0, 0, 0 }; maxIteration = 10; - while ((maxIteration > 0) && strncmp ("data", data, 4)) { + while (maxIteration-- && strncmp ("data", data, 4)) fileStream.read (data, 4); - maxIteration--; - } - // Sample rate converter initialized with 88200 sample long int converterSamples = (srate > audioSamplingRate) ? srate : audioSamplingRate; SamplerateConverter _converter (converterSamples, 2000); - int nbSampleMax = 512; - // Get length of data from the header. SINT32 bytes; fileStream.read ( (char*) &bytes, 4); - _debug ("WaveFile: data size in byte %d", bytes); - fileLength = 8 * bytes / dt / channels; // sample frames - _debug ("WaveFile: data size in frame %ld", fileLength); + unsigned long nbSamples = 8 * bytes / dt / chan; // sample frames + + _debug ("WaveFile: frame size %ld, data size %d align %d rate %d avgbyte %d chunk size %d dt %d", + nbSamples, bytes, blockal, srate, avgb, chunk_size, dt); // Should not be longer than a minute - if (fileLength > (unsigned int) (60*srate)) - fileLength = 60*srate; + if (nbSamples > (unsigned int) (60*srate)) + nbSamples = 60*srate; - SFLDataFormat *tempBuffer = new SFLDataFormat[fileLength]; - if (!tempBuffer) { + SFLDataFormat *tempBuffer = new SFLDataFormat[nbSamples]; + if (!tempBuffer) throw AudioFileException("Could not allocate temporary buffer"); - } - - SFLDataFormat *tempBufferRsmpl = NULL; - fileStream.read ( (char *) tempBuffer, fileLength*sizeof (SFLDataFormat)); + fileStream.read ( (char *) tempBuffer, nbSamples*sizeof (SFLDataFormat)); // mix two channels together if stereo - if(channels == 2) { - int tmp = 0; - unsigned j = 0; - for(unsigned int i = 0; i < fileLength-1; i+=2) { - tmp = (tempBuffer[i] + tempBuffer[i+1]) / 2; - // saturate - if(tmp > SHRT_MAX) { - tmp = SHRT_MAX; - } - tempBuffer[j++] = (SFLDataFormat)tmp; - } - - fileLength /= 2; + if(chan == 2) { + for(unsigned int i = 0; i < nbSamples-1; i+=2) + tempBuffer[i/2] = (tempBuffer[i] + tempBuffer[i+1]) / 2; + nbSamples /= 2; } - else if(channels > 2) { - delete [] tempBuffer; - throw AudioFileException("WaveFile: unsupported number of channels"); - } - - // compute size of final buffer - int nbSample; - - if (srate != audioSamplingRate) { - nbSample = (int) ( (float) fileLength * ( (float) audioSamplingRate / (float) srate)); - } else { - nbSample = fileLength; - } - - int totalprocessed = 0; - // require resampling if (srate != audioSamplingRate) { + nbSamples = (int) ( (float) nbSamples * ( (float) audioSamplingRate / (float) srate)); - // initialize remaining samples to process - int remainingSamples = fileLength; - - tempBufferRsmpl = new SFLDataFormat[nbSample]; - if (!tempBufferRsmpl) { - throw AudioFileException("Could not allocate temporary buffer for ressampling"); - } - - SFLDataFormat *in = tempBuffer; - SFLDataFormat *out = tempBufferRsmpl; + _buffer = new SFLDataFormat[nbSamples]; + if (_buffer == NULL) { + delete[] tempBuffer; + throw AudioFileException("Could not allocate buffer for audio"); + } - while (remainingSamples > 0) { + if (srate < audioSamplingRate) + _converter.upsampleData (tempBuffer, _buffer, srate, audioSamplingRate, nbSamples); + else if (srate > audioSamplingRate) + _converter.downsampleData (tempBuffer, _buffer, audioSamplingRate, srate, nbSamples); - int toProcess = remainingSamples > nbSampleMax ? nbSampleMax : remainingSamples; - - if (srate < audioSamplingRate) { - _converter.upsampleData (in, out, srate, audioSamplingRate, toProcess); - } else if (srate > audioSamplingRate) { - _converter.downsampleData (in, out, audioSamplingRate, srate, toProcess); - } - - // nbSamplesConverted = nbSamplesConverted*2; - - in += toProcess; - out += toProcess; - remainingSamples -= toProcess; - totalprocessed += toProcess; - } - } - - // Init audio loop buffer info - _buffer = new SFLDataFormat[nbSample]; - if (_buffer == NULL) { - throw AudioFileException("Could not allocate buffer for audio"); + delete[] tempBuffer; + } else { + _buffer = tempBuffer; } - _size = nbSample; + _size = nbSamples; _sampleRate = audioSamplingRate; - - // Copy audio into audioloopi - if (srate != audioSamplingRate) { - memcpy ( (void *) _buffer, (void *) tempBufferRsmpl, nbSample*sizeof (SFLDataFormat)); - } - else { - memcpy ( (void *) _buffer, (void *) tempBuffer, nbSample*sizeof (SFLDataFormat)); - } - - _debug ("WaveFile: file successfully opened"); - - delete[] tempBuffer; - - if (tempBufferRsmpl) { - delete[] tempBufferRsmpl; - } -} - - -void WaveFile::loadFile (const std::string& name, sfl::AudioCodec * /*codec*/, unsigned int sampleRate) throw(AudioFileException) -{ - try { - openFile (name, sampleRate); - } - catch(AudioFileException &e) { - throw; - } } diff --git a/sflphone-common/src/audio/sound/audiofile.h b/sflphone-common/src/audio/sound/audiofile.h index 0e6de14abad9cc1a8f3fc9d9ec90649fa9d32124..a51f84d91899aff435b90cbf518c26930f466eb3 100644 --- a/sflphone-common/src/audio/sound/audiofile.h +++ b/sflphone-common/src/audio/sound/audiofile.h @@ -56,52 +56,13 @@ public: class AudioFile : public AudioLoop { public: - - /** - * Load a sound file in memory - * - * @param filename The absolute path to the file - * @param codec The codec to decode and encode it - * @param sampleRate The sample rate to read it - * @return bool True on success - */ - virtual void loadFile (const std::string &, sfl::AudioCodec *, unsigned int) throw(AudioFileException) = 0; - - std::string getFilePath(void) { - return filepath; - } - - /** - * Start the sound file - */ - void start() { - _start = true; - } - - /** - * Stop the sound file - */ - void stop() { - _start = false; - } - - /** - * Tells whether or not the file is playing - * @return bool True if yes - * false otherwise - */ - bool isStarted() { - return _start; + const std::string &getFilePath(void) const{ + return filepath; } protected: - - /** start or not */ - bool _start; - /** The absolute path to the sound file */ std::string filepath; - }; @@ -117,22 +78,7 @@ class RawFile : public AudioFile /** * Constructor */ - RawFile(); - - /** - * Destructor - */ - ~RawFile(); - - - /** - * Load a sound file in memory - * @param filename The absolute path to the file - * @param codec The codec to decode and encode it - * @param sampleRate The sample rate to read it - * @return bool True on success - */ - virtual void loadFile (const std::string&, sfl::AudioCodec *, unsigned int sampleRate) throw(AudioFileException); + RawFile(const std::string& name, sfl::AudioCodec* codec, unsigned int sampleRate = 8000); private: // Copy Constructor @@ -149,89 +95,12 @@ class WaveFile : public AudioFile { public: - - WaveFile(); - - ~WaveFile(); - - /** - * Open a file give a file name - * - * @param A reference to a string containing the filename - * @param The internal sampling rate, file will be resampled - * if it's sampling rate does not correspond to internal one - */ - void openFile (const std::string&, unsigned int) throw(AudioFileException); - - /** - * Test if the specified file already exist - */ - bool isFileExist (const std::string&); - - /** - * Load a sound file in memory - * @param filename The absolute path to the file - * @param codec The codec to decode and encode it - * @param sampleRate The sample rate to read it - * @return bool True on success - */ - virtual void loadFile (const std::string&, sfl::AudioCodec *, unsigned int) throw(AudioFileException); - - private: - - /** - * Open an existing wave file - * @param File name - * @param Audio sampling rate - */ - void openExistingWaveFile (const std::string&, unsigned int) throw(AudioFileException); - - /** - * Sound format for this file (16/32 bits) - */ - SOUND_FORMAT sndFormat; - - /** - * Nb of bytes for this file - */ - long byteCounter; - - /** - * Number of channels for this file - */ - int nbChannels; - - /** - * Total file length - */ - unsigned long fileLength; - - /** - * Audio data start offset in bytes - */ - unsigned long dataOffset; - - /** - * Channels - */ - SINT16 channels; - - /** - * Data type - */ - SOUND_FORMAT dataType; - - /** - * File sampling rate - */ - double fileRate; - - /** - * File stream - */ - std::fstream fileStream; - + /** + * Load a sound file in memory + * @param filename The absolute path to the file + * @param sampleRate The sample rate to read it + */ + WaveFile(const std::string&, unsigned int); }; #endif - diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index abdb61db6bcbbdc6bc5911d3818524cd34f082f9..4c3566dcddd37bdf1db4054c186543d97f383b27 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -2316,11 +2316,9 @@ void ManagerImpl::stopTone () } if (_audiofile) { - std::string filepath = _audiofile->getFilePath(); - _dbus->getCallManager()->recordPlaybackStoped(filepath); - _audiofile->stop(); - delete _audiofile; - _audiofile = NULL; + std::string filepath = _audiofile->getFilePath(); + _dbus->getCallManager()->recordPlaybackStoped(filepath); + delete _audiofile; } _toneMutex.leaveMutex(); @@ -2365,90 +2363,64 @@ void ManagerImpl::ringback () */ void ManagerImpl::ringtone (const std::string& accountID) { - std::string ringchoice; - sfl::AudioCodec *codecForTone; - int samplerate; - - _debug ("Manager: Ringtone"); - Account *account = getAccount (accountID); - if (!account) { _warn ("Manager: Warning: invalid account in ringtone"); return; } - if (account->getRingtoneEnabled()) { - - _debug ("Manager: Tone is enabled"); - //TODO Comment this because it makes the daemon crashes since the main thread - //synchronizes the ringtone thread. - - ringchoice = account->getRingtonePath(); - //if there is no / inside the path - - if (ringchoice.find (DIR_SEPARATOR_CH) == std::string::npos) { - // check inside global share directory - ringchoice = std::string (PROGSHAREDIR) + DIR_SEPARATOR_STR - + RINGDIR + DIR_SEPARATOR_STR + ringchoice; - } - - audioLayerMutexLock(); - - - if (!_audiodriver) { - _error ("Manager: Error: no audio layer in ringtone"); - audioLayerMutexUnlock(); - return; - } + if (!account->getRingtoneEnabled()) { + ringback(); + return; + } - samplerate = _audiodriver->getSampleRate(); - codecForTone = static_cast<sfl::AudioCodec *>(_audioCodecFactory.getFirstCodecAvailable()); + std::string ringchoice = account->getRingtonePath(); + if (ringchoice.find (DIR_SEPARATOR_CH) == std::string::npos) { + // check inside global share directory + ringchoice = std::string (PROGSHAREDIR) + DIR_SEPARATOR_STR + + RINGDIR + DIR_SEPARATOR_STR + ringchoice; + } - audioLayerMutexUnlock(); + audioLayerMutexLock(); - _toneMutex.enterMutex(); + if (!_audiodriver) { + _error ("Manager: Error: no audio layer in ringtone"); + audioLayerMutexUnlock(); + return; + } - if (_audiofile) { - if(_dbus) { - std::string filepath = _audiofile->getFilePath(); - _dbus->getCallManager()->recordPlaybackStoped(filepath); - } - delete _audiofile; - _audiofile = NULL; - } + int samplerate = _audiodriver->getSampleRate(); - std::string wave (".wav"); - size_t found = ringchoice.find (wave); + audioLayerMutexUnlock(); - try { + _toneMutex.enterMutex(); - if (found != std::string::npos) { - _audiofile = static_cast<AudioFile *> (new WaveFile()); - } - else { - _audiofile = static_cast<AudioFile *> (new RawFile()); - } - - _debug ("Manager: ringChoice: %s, codecForTone: %d, samplerate %d", ringchoice.c_str(), codecForTone->getPayloadType(), samplerate); + if (_audiofile) { + if(_dbus) + _dbus->getCallManager()->recordPlaybackStoped(_audiofile->getFilePath()); + delete _audiofile; + _audiofile = NULL; + } - _audiofile->loadFile (ringchoice, codecForTone, samplerate); - } - catch (AudioFileException &e) { - _error("Manager: Exception: %s", e.what()); - } - - _audiofile->start(); - _toneMutex.leaveMutex(); + try { + if (ringchoice.find (".wav") != std::string::npos) { + _audiofile = new WaveFile(ringchoice, samplerate); + } + else { + sfl::AudioCodec *codecForTone = static_cast<sfl::AudioCodec *>(_audioCodecFactory.getFirstCodecAvailable()); + _audiofile = new RawFile(ringchoice, codecForTone, samplerate); + } + } + catch (AudioFileException &e) { + _error("Manager: Exception: %s", e.what()); + } - audioLayerMutexLock(); - // start audio if not started AND flush all buffers (main and urgent) - _audiodriver->startStream(); - audioLayerMutexUnlock(); + _toneMutex.leaveMutex(); - } else { - ringback(); - } + audioLayerMutexLock(); + // start audio if not started AND flush all buffers (main and urgent) + _audiodriver->startStream(); + audioLayerMutexUnlock(); } AudioLoop* @@ -2467,15 +2439,7 @@ ManagerImpl::getTelephoneFile () { ost::MutexLock m (_toneMutex); - if (!_audiofile) { - return NULL; - } - - if (_audiofile->isStarted()) { - return _audiofile; - } else { - return NULL; - } + return _audiofile; } void ManagerImpl::notificationIncomingCall (void) @@ -3000,16 +2964,9 @@ void ManagerImpl::setRecordingCall (const std::string& id) bool ManagerImpl::isRecording (const std::string& id) { - std::string accountid = getAccountFromCall (id); Recordable* rec = (Recordable*) getAccountLink (accountid)->getCall (id); - - bool ret = false; - - if (rec) - ret = rec->isRecording(); - - return ret; + return rec && rec->isRecording(); } bool ManagerImpl::startRecordedFilePlayback(const std::string& filepath) @@ -3031,25 +2988,19 @@ bool ManagerImpl::startRecordedFilePlayback(const std::string& filepath) _toneMutex.enterMutex(); if(_audiofile) { - if(_dbus) { - std::string file = _audiofile->getFilePath(); - _dbus->getCallManager()->recordPlaybackStoped(file); - } - delete _audiofile; - _audiofile = NULL; + if(_dbus) + _dbus->getCallManager()->recordPlaybackStoped(_audiofile->getFilePath()); + delete _audiofile; + _audiofile = NULL; } try { - _audiofile = static_cast<AudioFile *>(new WaveFile()); - - _audiofile->loadFile(filepath, NULL, sampleRate); + _audiofile = new WaveFile(filepath, sampleRate); } - catch(AudioFileException &e) { + catch(const AudioFileException &e) { _error("Manager: Exception: %s", e.what()); } - _audiofile->start(); - _toneMutex.leaveMutex(); audioLayerMutexLock(); @@ -3069,11 +3020,8 @@ void ManagerImpl::stopRecordedFilePlayback(const std::string& filepath) audioLayerMutexUnlock(); _toneMutex.enterMutex(); - if(_audiofile != NULL) { - _audiofile->stop(); - delete _audiofile; + delete _audiofile; _audiofile = NULL; - } _toneMutex.leaveMutex(); }