15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/multi_channel_resampler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_bus.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiChannelResampler::MultiChannelResampler(int channels,
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             double io_sample_rate_ratio,
16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                             size_t request_size,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const ReadCB& read_cb)
18a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    : read_cb_(read_cb),
19a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      wrapped_resampler_audio_bus_(AudioBus::CreateWrapper(channels)),
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      output_frames_ready_(0) {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate each channel's resampler.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resamplers_.reserve(channels);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < channels; ++i) {
24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    resamplers_.push_back(new SincResampler(
25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        io_sample_rate_ratio, request_size, base::Bind(
26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            &MultiChannelResampler::ProvideInput, base::Unretained(this), i)));
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
29a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Setup the wrapped AudioBus for channel data.
30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  wrapped_resampler_audio_bus_->set_frames(request_size);
31a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
32a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Allocate storage for all channels except the first, which will use the
33a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // |destination| provided to ProvideInput() directly.
34a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (channels > 1) {
35a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    resampler_audio_bus_ = AudioBus::Create(channels - 1, request_size);
36a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    for (int i = 0; i < resampler_audio_bus_->channels(); ++i) {
37a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      wrapped_resampler_audio_bus_->SetChannelData(
38a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          i + 1, resampler_audio_bus_->channel(i));
39a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    }
40a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiChannelResampler::~MultiChannelResampler() {}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void MultiChannelResampler::Resample(int frames, AudioBus* audio_bus) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(static_cast<size_t>(audio_bus->channels()), resamplers_.size());
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Optimize the single channel case to avoid the chunking process below.
49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (audio_bus->channels() == 1) {
50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    resamplers_[0]->Resample(frames, audio_bus->channel(0));
51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to ensure that SincResampler only calls ProvideInput once for each
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // channel.  To ensure this, we chunk the number of requested frames into
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SincResampler::ChunkSize() sized chunks.  SincResampler guarantees it will
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only call ProvideInput() once when we resample this way.
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  output_frames_ready_ = 0;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (output_frames_ready_ < frames) {
60b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    int chunk_size = resamplers_[0]->ChunkSize();
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int frames_this_time = std::min(frames - output_frames_ready_, chunk_size);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Resample each channel.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < resamplers_.size(); ++i) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_EQ(chunk_size, resamplers_[i]->ChunkSize());
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Depending on the sample-rate scale factor, and the internal buffering
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // used in a SincResampler kernel, this call to Resample() will only
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // sometimes call ProvideInput().  However, if it calls ProvideInput() for
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the first channel, then it will call it for the remaining channels,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // since they all buffer in the same way and are processing the same
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // number of frames.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resamplers_[i]->Resample(
74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          frames_this_time, audio_bus->channel(i) + output_frames_ready_);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    output_frames_ready_ += frames_this_time;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void MultiChannelResampler::ProvideInput(int channel,
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                         int frames,
83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                         float* destination) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the data from the multi-channel provider when the first channel asks
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for it.  For subsequent channels, we can just dish out the channel data
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from that (stored in |resampler_audio_bus_|).
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (channel == 0) {
88a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    wrapped_resampler_audio_bus_->SetChannelData(0, destination);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    read_cb_.Run(output_frames_ready_, wrapped_resampler_audio_bus_.get());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // All channels must ask for the same amount.  This should always be the
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // case, but let's just make sure.
93a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DCHECK_EQ(frames, wrapped_resampler_audio_bus_->frames());
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Copy the channel data from what we received from |read_cb_|.
96a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    memcpy(destination, wrapped_resampler_audio_bus_->channel(channel),
97a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)           sizeof(*wrapped_resampler_audio_bus_->channel(channel)) * frames);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiChannelResampler::Flush() {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < resamplers_.size(); ++i)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resamplers_[i]->Flush();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MultiChannelResampler::SetRatio(double io_sample_rate_ratio) {
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < resamplers_.size(); ++i)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    resamplers_[i]->SetRatio(io_sample_rate_ratio);
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)int MultiChannelResampler::ChunkSize() const {
11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(!resamplers_.empty());
11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return resamplers_[0]->ChunkSize();
11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
117