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 AudioSender::process() { auto& mainBuffer = Manager::instance().getRingBufferPool(); auto mainBuffFormat = mainBuffer.getInternalAudioFormat(); // compute nb of byte to get corresponding to 1 audio frame const std::size_t samplesToGet = std::chrono::duration_cast<std::chrono::seconds>(mainBuffFormat.sample_rate * secondsPerPacket_).count(); if (mainBuffer.availableForGet(id_) < samplesToGet) { const auto wait_time = std::chrono::duration_cast<std::chrono::milliseconds>(secondsPerPacket_); if (not mainBuffer.waitForDataAvailable(id_, samplesToGet, wait_time)) return; } // get data micData_.setFormat(mainBuffFormat); micData_.resize(samplesToGet); const auto samples = mainBuffer.getData(micData_, id_); if (samples != samplesToGet) return; // down/upmix as needed auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(args_.codec); micData_.setChannelNum(accountAudioCodec->audioformat.nb_channels, true); if (mainBuffFormat.sample_rate != accountAudioCodec->audioformat.sample_rate) { if (not resampler_) { RING_DBG("Creating audio resampler"); resampler_.reset(new Resampler(accountAudioCodec->audioformat)); } resampledData_.setFormat(accountAudioCodec->audioformat); resampledData_.resize(samplesToGet); resampler_->resample(micData_, resampledData_); Smartools::getInstance().setLocalAudioCodec(audioEncoder_->getEncoderName()); if (audioEncoder_->encode_audio(resampledData_) < 0) RING_ERR("encoding failed"); } else { if (audioEncoder_->encode_audio(micData_) < 0) RING_ERR("encoding failed"); } }