Esempio n. 1
0
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");
    }
}