// This one puts some data inside the ring buffer. void RingBuffer::put(AudioBuffer& buf) { std::lock_guard<std::mutex> l(lock_); const size_t sample_num = buf.frames(); const size_t buffer_size = buffer_.frames(); if (buffer_size == 0) return; size_t len = putLength(); if (buffer_size - len < sample_num) discard(sample_num); size_t toCopy = sample_num; // Add more channels if the input buffer holds more channels than the ring. if (buffer_.channels() < buf.channels()) buffer_.setChannelNum(buf.channels()); size_t in_pos = 0; size_t pos = endPos_; while (toCopy) { size_t block = toCopy; if (block > buffer_size - pos) // Wrap block around ring ? block = buffer_size - pos; // Fill in to the end of the buffer buffer_.copy(buf, block, in_pos, pos); in_pos += block; pos = (pos + block) % buffer_size; toCopy -= block; } endPos_ = pos; not_empty_.notify_all(); }
void Resampler::resample(const AudioBuffer &dataIn, AudioBuffer &dataOut) { const double inputFreq = dataIn.getSampleRate(); const double outputFreq = dataOut.getSampleRate(); const double sampleFactor = outputFreq / inputFreq; if (sampleFactor == 1.0) return; const size_t nbFrames = dataIn.frames(); const size_t nbChans = dataIn.channels(); if (nbChans != format_.nb_channels) { // change channel num if needed int err; src_delete(src_state_); src_state_ = src_new(SRC_LINEAR, nbChans, &err); format_.nb_channels = nbChans; DEBUG("SRC channel number changed."); } if (nbChans != dataOut.channels()) { DEBUG("Output buffer had the wrong number of channels (in: %d, out: %d).", nbChans, dataOut.channels()); dataOut.setChannelNum(nbChans); } size_t inSamples = nbChans * nbFrames; size_t outSamples = inSamples * sampleFactor; // grow buffer if needed floatBufferIn_.resize(inSamples); floatBufferOut_.resize(outSamples); scratchBuffer_.resize(outSamples); SRC_DATA src_data; src_data.data_in = floatBufferIn_.data(); src_data.data_out = floatBufferOut_.data(); src_data.input_frames = nbFrames; src_data.output_frames = nbFrames * sampleFactor; src_data.src_ratio = sampleFactor; src_data.end_of_input = 0; // More data will come dataIn.interleaveFloat(floatBufferIn_.data()); src_process(src_state_, &src_data); /* TODO: one-shot deinterleave and float-to-short conversion */ src_float_to_short_array(floatBufferOut_.data(), scratchBuffer_.data(), outSamples); dataOut.deinterleave(scratchBuffer_.data(), src_data.output_frames, nbChans); }
void AudioBuffer::convert_channels(AudioBuffer &_dest, unsigned _frames_count) { AudioSpec destspec{m_spec.format, _dest.channels(), m_spec.rate}; if(_dest.spec() != destspec) { throw std::logic_error("unsupported format"); } _frames_count = std::min(frames(),_frames_count); if(m_spec.channels == destspec.channels) { _dest.add_frames(*this,_frames_count); return; } switch(m_spec.format) { case AUDIO_FORMAT_U8: convert_channels<uint8_t>(*this,_dest,_frames_count); break; case AUDIO_FORMAT_S16: convert_channels<int16_t>(*this,_dest,_frames_count); break; case AUDIO_FORMAT_F32: convert_channels<float>(*this,_dest,_frames_count); break; default: throw std::logic_error("unsupported format"); } }
void AudioBuffer::convert(const AudioSpec &_new_spec) { if(_new_spec == m_spec) { return; } AudioSpec new_spec = _new_spec; AudioBuffer dest[2]; unsigned bufidx = 0; AudioBuffer *source = this; if(source->rate() != new_spec.rate) { #if HAVE_LIBSAMPLERATE if(source->format() != AUDIO_FORMAT_F32) { dest[1].set_spec({AUDIO_FORMAT_F32, source->channels(), source->rate()}); source->convert_format(dest[1], source->frames()); source = &dest[1]; } dest[0].set_spec({source->format(), source->channels(), new_spec.rate}); source->convert_rate(dest[0], source->frames(), nullptr); source = &dest[0]; bufidx = 1; #else new_spec.rate = source->rate(); #endif } if(source->channels() != new_spec.channels) { dest[bufidx].set_spec({source->format(),new_spec.channels,source->rate()}); source->convert_channels(dest[bufidx], source->frames()); source = &dest[bufidx]; bufidx = (bufidx + 1) % 2; } if(source->format() != new_spec.format) { dest[bufidx].set_spec({new_spec.format,source->channels(),source->rate()}); source->convert_format(dest[bufidx], source->frames()); source = &dest[bufidx]; } if(new_spec != m_spec) { m_data = source->m_data; m_spec = new_spec; } }
void AudioBuffer::convert_channels(const AudioBuffer &_source, AudioBuffer &_dest, unsigned _frames_count) { unsigned d = _dest.samples(); _dest.resize_frames(_dest.frames()+_frames_count); if(_source.channels()==1 && _dest.channels()==2) { //from mono to stereo for(unsigned i=0; i<_frames_count; ++i) { T ch1 = _source.at<T>(i); _dest.operator[]<T>(d+i*2) = ch1; _dest.operator[]<T>(d+i*2+1) = ch1; } } else if(_source.channels()==2 && _dest.channels()==1) { //from stereo to mono for(unsigned i=0; i<_frames_count; ++i) { double ch1 = double(_source.at<T>(i*2)); double ch2 = double(_source.at<T>(i*2+1)); _dest.operator[]<T>(d+i) = T((ch1 + ch2) / 2.0); } } }
void JackLayer::write(AudioBuffer &buffer, std::vector<float> &floatBuffer) { for (unsigned i = 0; i < out_ringbuffers_.size(); ++i) { const unsigned inChannel = std::min(i, buffer.channels() - 1); convertToFloat(*buffer.getChannel(inChannel), floatBuffer); // write to output const size_t to_ringbuffer = jack_ringbuffer_write_space(out_ringbuffers_[i]); const size_t write_bytes = std::min(buffer.frames() * sizeof(floatBuffer[0]), to_ringbuffer); // FIXME: while we have samples to write AND while we have space to write them const size_t written_bytes = jack_ringbuffer_write(out_ringbuffers_[i], (const char *) floatBuffer.data(), write_bytes); if (written_bytes < write_bytes) RING_WARN("Dropped %zu bytes for channel %u", write_bytes - written_bytes, i); } }