| /* |
| * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "webrtc/common_audio/include/audio_util.h" |
| #include "webrtc/common_audio/resampler/push_sinc_resampler.h" |
| |
| #include <string.h> |
| |
| namespace webrtc { |
| |
| PushSincResampler::PushSincResampler(int source_frames, |
| int destination_frames) |
| : resampler_(new SincResampler(source_frames * 1.0 / destination_frames, |
| source_frames, this)), |
| float_buffer_(new float[destination_frames]), |
| source_ptr_(NULL), |
| destination_frames_(destination_frames), |
| first_pass_(true), |
| source_available_(0) { |
| } |
| |
| PushSincResampler::~PushSincResampler() { |
| } |
| |
| int PushSincResampler::Resample(const int16_t* source, |
| int source_length, |
| int16_t* destination, |
| int destination_capacity) { |
| assert(source_length == resampler_->request_frames()); |
| assert(destination_capacity >= destination_frames_); |
| // Cache the source pointer. Calling Resample() will immediately trigger |
| // the Run() callback whereupon we provide the cached value. |
| source_ptr_ = source; |
| source_available_ = source_length; |
| |
| // On the first pass, we call Resample() twice. During the first call, we |
| // provide dummy input and discard the output. This is done to prime the |
| // SincResampler buffer with the correct delay (half the kernel size), thereby |
| // ensuring that all later Resample() calls will only result in one input |
| // request through Run(). |
| // |
| // If this wasn't done, SincResampler would call Run() twice on the first |
| // pass, and we'd have to introduce an entire |source_frames| of delay, rather |
| // than the minimum half kernel. |
| // |
| // It works out that ChunkSize() is exactly the amount of output we need to |
| // request in order to prime the buffer with a single Run() request for |
| // |source_frames|. |
| if (first_pass_) |
| resampler_->Resample(resampler_->ChunkSize(), float_buffer_.get()); |
| |
| resampler_->Resample(destination_frames_, float_buffer_.get()); |
| RoundToInt16(float_buffer_.get(), destination_frames_, destination); |
| source_ptr_ = NULL; |
| return destination_frames_; |
| } |
| |
| void PushSincResampler::Run(int frames, float* destination) { |
| assert(source_ptr_ != NULL); |
| // Ensure we are only asked for the available samples. This would fail if |
| // Run() was triggered more than once per Resample() call. |
| assert(source_available_ == frames); |
| |
| if (first_pass_) { |
| // Provide dummy input on the first pass, the output of which will be |
| // discarded, as described in Resample(). |
| memset(destination, 0, frames * sizeof(float)); |
| first_pass_ = false; |
| } else { |
| for (int i = 0; i < frames; ++i) |
| destination[i] = static_cast<float>(source_ptr_[i]); |
| source_available_ -= frames; |
| } |
| } |
| |
| } // namespace webrtc |