diff --git a/daemon/src/audio/audiobuffer.cpp b/daemon/src/audio/audiobuffer.cpp index 13042d25f77a827245b9f654eadd19f3d464c5e2..9918a93438a525bb8af5f17c6de324187fb72d7a 100644 --- a/daemon/src/audio/audiobuffer.cpp +++ b/daemon/src/audio/audiobuffer.cpp @@ -160,18 +160,21 @@ void AudioBuffer::fromInterleaved(const SFLAudioSample* in, size_t sample_num, u } } -size_t AudioBuffer::mix(const AudioBuffer& other) +size_t AudioBuffer::mix(const AudioBuffer& other, bool up /* = true */) { + const bool upmix = up && (other.channels_ < channels_); const size_t samp_num = std::min(sampleNum_, other.sampleNum_); - const unsigned chan_num = std::min(channels_, other.channels_); + const unsigned chan_num = upmix ? channels_ : std::min(channels_, other.channels_); + for(unsigned i=0; i<chan_num; i++) { + unsigned src_chan = upmix ? std::min(i, other.channels_-1) : i; for(unsigned j=0; j<samp_num; j++) - samples_[i][j] += other.samples_[i][j]; + samples_[i][j] += other.samples_[src_chan][j]; } return samp_num; } -size_t AudioBuffer::copy(AudioBuffer& in, int sample_num /* = -1 */, size_t pos_in /* = 0 */, size_t pos_out /* = 0 */) +size_t AudioBuffer::copy(AudioBuffer& in, int sample_num /* = -1 */, size_t pos_in /* = 0 */, size_t pos_out /* = 0 */, bool up /* = true */) { if(sample_num == -1) sample_num = in.samples(); @@ -179,7 +182,8 @@ size_t AudioBuffer::copy(AudioBuffer& in, int sample_num /* = -1 */, size_t pos_ int to_copy = std::min((int)in.samples()-(int)pos_in, sample_num); if(to_copy <= 0) return 0; - const size_t chan_num = std::min(in.channels_, channels_); + const bool upmix = up && (in.channels_ < channels_); + const size_t chan_num = upmix ? channels_ : std::min(in.channels_, channels_); if(pos_out+to_copy > sampleNum_) resize(pos_out+to_copy); @@ -189,7 +193,8 @@ size_t AudioBuffer::copy(AudioBuffer& in, int sample_num /* = -1 */, size_t pos_ unsigned i; for(i=0; i<chan_num; i++) { - std::copy(in.samples_[i].begin()+pos_in, in.samples_[i].begin()+pos_in+to_copy, samples_[i].begin()+pos_out); + unsigned src_chan = upmix ? std::min(i, in.channels_-1) : i; + std::copy(in.samples_[src_chan].begin()+pos_in, in.samples_[src_chan].begin()+pos_in+to_copy, samples_[i].begin()+pos_out); } return to_copy; diff --git a/daemon/src/audio/audiobuffer.h b/daemon/src/audio/audiobuffer.h index 36a1905518f502321f21e52357c44d3ba33872d3..a55dfb95acedc65a5d357d171c795ba95d6a69c2 100644 --- a/daemon/src/audio/audiobuffer.h +++ b/daemon/src/audio/audiobuffer.h @@ -35,7 +35,6 @@ #include <cstddef> // for size_t #include "sfl_types.h" -//#include "noncopyable.h" class AudioBuffer { public: @@ -98,8 +97,8 @@ class AudioBuffer { * Return the total number of single samples in the buffer (same as samples()*channels()). */ inline size_t capacity() const { - return samples()*channels(); - } + return samples()*channels(); + } /** * Resize the buffer to make it able to hold sample_num multichannel samples. @@ -165,12 +164,20 @@ class AudioBuffer { void applyGain(double gain); /** - * Mix elements of the other buffer with this buffer (in-place simple addition). + * Mix elements of the other buffer within this buffer (in-place simple addition). + * If other.channels() is higher than this.channels(), only the first this.channels() channels are imported. + * If other.channels() is lower than this.channels(), behavior depends on upmix. + * Sample rate is not considered by this function. + * * TODO: some kind of check for overflow/saturation. * + * @param other: the other buffer to mix in this one. + * @param upmix: if true, upmixing occurs when other.channels() < this.channels(). + * If false, only the first other.channels() channels are edited in this buffer. + * * @returns Number of samples modified. */ - size_t mix(const AudioBuffer& other); + size_t mix(const AudioBuffer& other, bool upmix=true); /** * Copy sample_num samples from in (from sample pos_in) to this buffer (at sample pos_out). @@ -179,7 +186,7 @@ class AudioBuffer { * The number of channels is changed to match the in channel number. * Buffer sample number is also increased if required to hold the new requested samples. */ - size_t copy(AudioBuffer& in, int sample_num=-1, size_t pos_in=0, size_t pos_out=0); + size_t copy(AudioBuffer& in, int sample_num=-1, size_t pos_in=0, size_t pos_out=0, bool upmix=true); /** * Copy sample_num samples from in to this buffer (at sample pos_out). @@ -190,8 +197,6 @@ class AudioBuffer { size_t copy(SFLAudioSample* in, size_t sample_num, size_t pos_out=0); private: - //NON_COPYABLE(AudioBuffer); - int sampleRate_; unsigned channels_; // should allways be the same as samples_.size() size_t sampleNum_; diff --git a/daemon/src/audio/audioloop.cpp b/daemon/src/audio/audioloop.cpp index 7a525a8efefcd1d15f0540e852ddf1bd7d207723..cfc8f936b364a034a8832ab92f5101a86f4801c4 100644 --- a/daemon/src/audio/audioloop.cpp +++ b/daemon/src/audio/audioloop.cpp @@ -49,7 +49,6 @@ AudioLoop::AudioLoop(unsigned int sampleRate) : buffer_(), pos_(0), isRecording_ AudioLoop::~AudioLoop() { - //delete [] buffer_; delete buffer_; } @@ -64,7 +63,6 @@ AudioLoop::seek(double relative_position) static unsigned int updatePlaybackScale = 0; void -//AudioLoop::getNext(SFLAudioSample* output, size_t total_samples, short volume) AudioLoop::getNext(AudioBuffer& output, unsigned int volume) { if(!buffer_) { @@ -88,23 +86,8 @@ AudioLoop::getNext(AudioBuffer& output, unsigned int volume) while (total_samples > 0) { size_t samples = std::min(total_samples, buf_samples - pos); - /* if (samples > (buf_samples - pos)) - samples = buf_samples - pos;*/ - - // short->char conversion - //memcpy(output, buffer_ + pos, samples * sizeof(SFLAudioSample)); - //buffer_.copy(output, pos, samples); output.copy(*buffer_, samples, pos, output_pos); - // Scaling needed - /*if (volume != 100) { - const double gain = volume * 0.01; - - for (size_t i = 0; i < samples; ++i, ++output) - *output *= gain; - } else - output_pos += samples;*/ - //output += samples; // this is the destination... output_pos += samples; pos = (pos + samples) % buf_samples; diff --git a/daemon/src/audio/audioloop.h b/daemon/src/audio/audioloop.h index e51dbe8f5d4e32f064becc6a809f866ceeaf8047..c6eed88eff695d4de51bdbacff364d3bb0a86727 100644 --- a/daemon/src/audio/audioloop.h +++ b/daemon/src/audio/audioloop.h @@ -56,7 +56,6 @@ class AudioLoop { * @param nb of int16 to send * @param volume The volume */ - //void getNext(SFLAudioSample* output, size_t samples, short volume=100); void getNext(AudioBuffer& output, unsigned int volume=100); void seek(double relative_position); @@ -73,7 +72,7 @@ class AudioLoop { * @return unsigned int The size */ size_t getSize() { - return buffer_->samples();//size_; + return buffer_->samples(); } /** @@ -87,17 +86,10 @@ class AudioLoop { protected: /** The data buffer */ AudioBuffer * buffer_; - //SFLAudioSample* buffer_; - - /** Number of samples inside the buffer */ - //size_t size_; /** current position, set to 0, when initialize */ size_t pos_; - /** Sample rate */ - //unsigned int sampleRate_; - /** Is a playback recording */ bool isRecording_; diff --git a/daemon/src/audio/pulseaudio/pulselayer.cpp b/daemon/src/audio/pulseaudio/pulselayer.cpp index f061d914942a9bda94eaca9afbe2a8407fcd2ab9..e04d6fd656e93b8a0001a997c2cf58f1fd20a699 100644 --- a/daemon/src/audio/pulseaudio/pulselayer.cpp +++ b/daemon/src/audio/pulseaudio/pulselayer.cpp @@ -135,8 +135,6 @@ PulseLayer::~PulseLayer() if (mainloop_) pa_threaded_mainloop_free(mainloop_); - - //delete [] mic_buffer_; } void PulseLayer::context_state_callback(pa_context* c, void *user_data) @@ -365,6 +363,8 @@ void PulseLayer::writeToSpeaker() } else if (ret == 0) return; + DEBUG("writeToSpeaker with n_channels=%d", n_channels); + size_t writableBytes = ret; size_t writableSamples = writableBytes/sample_size; diff --git a/daemon/src/audio/pulseaudio/pulselayer.h b/daemon/src/audio/pulseaudio/pulselayer.h index cba5d1d2ef3012e0e5d14a94ac4150a75df390c8..f9c1b3c1fe592a8f0d2df7999ca41908eca53867 100644 --- a/daemon/src/audio/pulseaudio/pulselayer.h +++ b/daemon/src/audio/pulseaudio/pulselayer.h @@ -55,15 +55,15 @@ typedef struct PaDeviceInfos { pa_channel_map channel_map; PaDeviceInfos(unsigned idx, const char* ep_name, pa_sample_spec samp_spec, pa_channel_map chan_map) - : index(idx), name(ep_name), sample_spec(samp_spec), channel_map(chan_map) - {} + : index(idx), name(ep_name), sample_spec(samp_spec), channel_map(chan_map) {} + virtual ~PaDeviceInfos() {} /** * Unary function to search for a device by name in a list using std functions. */ struct nameComparator : public std::unary_function<const PaDeviceInfos, bool> { - explicit nameComparator(const std::string &baseline) : baseline(baseline) {} + explicit nameComparator(const std::string &ref) : baseline(ref) {} bool operator() (const PaDeviceInfos &arg) { return arg.name == baseline; } diff --git a/daemon/src/audio/ringbuffer.cpp b/daemon/src/audio/ringbuffer.cpp index deca77200859c28c1e77e8c646df4c3739363fc1..9c0bb544b333b8d62443ec7cb5a9a4414f1c3f99 100644 --- a/daemon/src/audio/ringbuffer.cpp +++ b/daemon/src/audio/ringbuffer.cpp @@ -3,6 +3,7 @@ * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> * Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> + * Author: Adrien Beraud <adrien.beraud@gmail.com> * * Portions (c) Dominic Mazzoni (Audacity) * @@ -40,15 +41,14 @@ #include "ringbuffer.h" namespace { - // corresponds to 106 ms (about 5 rtp packets) + // corresponds to 160 ms (about 5 rtp packets) const size_t MIN_BUFFER_SIZE = 1280; } // Create a ring buffer with 'size' bytes RingBuffer::RingBuffer(size_t size, const std::string &call_id) : endPos_(0) - , bufferSize_(std::max(size, MIN_BUFFER_SIZE)) - , buffer_(1, std::vector<SFLAudioSample>(bufferSize_)) + , buffer_(std::max(size, MIN_BUFFER_SIZE), 1) , readpointers_() , buffer_id_(call_id) { @@ -73,19 +73,21 @@ RingBuffer::flushAll() size_t RingBuffer::putLength() const { + const size_t buffer_size = buffer_.samples(); const size_t startPos = (not readpointers_.empty()) ? getSmallestReadPointer() : 0; - return (endPos_ + bufferSize_ - startPos) % bufferSize_; + return (endPos_ + buffer_size - startPos) % buffer_size; } size_t RingBuffer::getLength(const std::string &call_id) const { - return (endPos_ + bufferSize_ - getReadPointer(call_id)) % bufferSize_; + const size_t buffer_size = buffer_.samples(); + return (endPos_ + buffer_size - getReadPointer(call_id)) % buffer_size; } void RingBuffer::debug() { - DEBUG("Start=%d; End=%d; BufferSize=%d", getSmallestReadPointer(), endPos_, bufferSize_); + DEBUG("Start=%d; End=%d; BufferSize=%d", getSmallestReadPointer(), endPos_, buffer_.samples()); } size_t RingBuffer::getReadPointer(const std::string &call_id) const @@ -103,7 +105,7 @@ RingBuffer::getSmallestReadPointer() const if (hasNoReadPointers()) return 0; - size_t smallest = bufferSize_; + size_t smallest = buffer_.samples(); ReadPointer::const_iterator iter; @@ -161,22 +163,20 @@ bool RingBuffer::hasNoReadPointers() const // // This one puts some data inside the ring buffer. -//void RingBuffer::put(void* buffer, size_t toCopy) void RingBuffer::put(AudioBuffer& buf) { const size_t len = putLength(); - const unsigned chans = buf.channels(); const size_t sample_num = buf.samples(); + const size_t buffer_size = buffer_.samples(); size_t toCopy = sample_num; // Add more channels if the input buffer holds more channels than the ring. - if(buffer_.size() < chans) - buffer_.resize(chans, std::vector<SFLAudioSample>(bufferSize_, 0)); + if(buffer_.channels() < buf.channels()) + buffer_.setChannelNum(buf.channels()); - if (toCopy > bufferSize_ - len) - toCopy = bufferSize_ - len; + if (toCopy > buffer_size - len) + toCopy = buffer_size - len; - //unsigned char *src = static_cast<SFLAudioSample *>(buffer); size_t in_pos = 0; size_t pos = endPos_; @@ -184,14 +184,12 @@ void RingBuffer::put(AudioBuffer& buf) size_t block = toCopy; size_t i; - if (block > bufferSize_ - pos) // Wrap block around ring ? - block = bufferSize_ - pos; // Fill in to the end of the buffer + if (block > buffer_size - pos) // Wrap block around ring ? + block = buffer_size - pos; // Fill in to the end of the buffer - for(i=0; i<chans; i++) { - copy(buf.getChannel(i)->begin()+in_pos, buf.getChannel(i)->begin()+in_pos+block, buffer_[i].begin()+pos); - } + buffer_.copy(buf, block, in_pos, pos); in_pos += block; - pos = (pos + block) % bufferSize_; + pos = (pos + block) % buffer_size; toCopy -= block; } endPos_ = pos; @@ -209,7 +207,6 @@ RingBuffer::availableForGet(const std::string &call_id) const } // Get will move 'toCopy' bytes from the internal FIFO to 'buffer' -//size_t RingBuffer::get(void *buffer, size_t toCopy, const std::string &call_id) size_t RingBuffer::get(AudioBuffer& buf, const std::string &call_id) { if (hasNoReadPointers()) @@ -220,12 +217,9 @@ size_t RingBuffer::get(AudioBuffer& buf, const std::string &call_id) const size_t len = getLength(call_id); const size_t sample_num = buf.samples(); - const size_t chans = std::min((unsigned)buffer_.size(), buf.channels()); + const size_t buffer_size = buffer_.samples(); size_t toCopy = std::min(sample_num, len); - /* if (toCopy > len) - toCopy = len;*/ - const size_t copied = toCopy; size_t dest = 0; @@ -235,17 +229,13 @@ size_t RingBuffer::get(AudioBuffer& buf, const std::string &call_id) size_t block = toCopy; unsigned i; - if (block > bufferSize_ - startPos) - block = bufferSize_ - startPos; + if (block > buffer_size - startPos) + block = buffer_size - startPos; - for(i=0; i<chans; i++) { - copy(buffer_[i].begin()+startPos, buffer_[i].begin()+startPos+block, buf.getChannel(i)->begin()+dest); - // memcpy(buf->getChannel(i), &(*buffer_[i].begin()) + startPos, block); - } + buf.copy(buffer_, block, startPos, dest); - //memcpy(dest, &(*buffer_.begin()) + startPos, block); dest += block; - startPos = (startPos + block) % bufferSize_; + startPos = (startPos + block) % buffer_size; toCopy -= block; } @@ -261,7 +251,8 @@ RingBuffer::discard(size_t toDiscard, const std::string &call_id) if (toDiscard > len) toDiscard = len; - size_t startPos = (getReadPointer(call_id) + toDiscard) % bufferSize_; + size_t buffer_size = buffer_.samples(); + size_t startPos = (getReadPointer(call_id) + toDiscard) % buffer_size; storeReadPointer(startPos, call_id); diff --git a/daemon/src/audio/ringbuffer.h b/daemon/src/audio/ringbuffer.h index 3f9f304041ef3e348464e260cae31f93715f569b..9977e8978508ff1ea0a0444aa34bcbf287b54d27 100644 --- a/daemon/src/audio/ringbuffer.h +++ b/daemon/src/audio/ringbuffer.h @@ -3,6 +3,7 @@ * Author: Yan Morin <yan.morin@savoirfairelinux.com> * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * Author: Adrien Beraud <adrien.beraud@gmail.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 @@ -98,7 +99,6 @@ class RingBuffer { * @param toCopy Number of bytes to copy */ void put(AudioBuffer& buf); - //void put(void* buffer, size_t toCopy); /** * To get how much samples are available in the buffer to read in @@ -113,7 +113,6 @@ class RingBuffer { * @return size_t Number of bytes copied */ size_t get(AudioBuffer& buf, const std::string &call_id); - //size_t get(void* buffer, size_t toCopy, const std::string &call_id); /** * Discard data from the buffer @@ -141,10 +140,8 @@ class RingBuffer { /** Pointer on the last data */ size_t endPos_; - /** Buffer size */ - size_t bufferSize_; /** Data */ - std::vector<std::vector<SFLAudioSample> > buffer_; + AudioBuffer buffer_; ReadPointer readpointers_; std::string buffer_id_; diff --git a/daemon/src/audio/sound/dtmf.h b/daemon/src/audio/sound/dtmf.h index 994dbcd6670c09707fbe2c7b0529550ec809e00e..f53c36671bf3dcbd68a140443dd20593e0047a7d 100644 --- a/daemon/src/audio/sound/dtmf.h +++ b/daemon/src/audio/sound/dtmf.h @@ -58,7 +58,7 @@ class DTMF { /** * Copy the sound inside the sampling* buffer - * @param buffer : a vector of SFLDataFormat + * @param buffer : a vector of SFLAudioSample */ bool generateDTMF(std::vector<SFLAudioSample> &buffer); diff --git a/daemon/test/mainbuffertest.cpp b/daemon/test/mainbuffertest.cpp index a505427ded9950a3ff020bc62131e681933e8507..56f281e62934ad891bb171b6a23fee715a98f3f2 100644 --- a/daemon/test/mainbuffertest.cpp +++ b/daemon/test/mainbuffertest.cpp @@ -422,7 +422,7 @@ void MainBufferTest::testTwoPointer() input_buffer->put(test_input); CPPUNIT_ASSERT(output_buffer->get(test_output, MainBuffer::DEFAULT_ID) == 1); - CPPUNIT_ASSERT((*test_input.getChannel())[0] == (*test_output.getChannel())[0]); + CPPUNIT_ASSERT(test_sample == (*test_output.getChannel())[0]); }