| Index: chromecast/media/cma/backend/alsa/post_processors/governor_shlib.cc | 
| diff --git a/chromecast/media/cma/backend/alsa/post_processors/governor_shlib.cc b/chromecast/media/cma/backend/alsa/post_processors/governor_shlib.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..433868787aaa53cadf564a76ae7fadaf8144e5ec | 
| --- /dev/null | 
| +++ b/chromecast/media/cma/backend/alsa/post_processors/governor_shlib.cc | 
| @@ -0,0 +1,102 @@ | 
| +// Copyright 2017 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include <memory> | 
| +#include <string> | 
| + | 
| +#include "base/logging.h" | 
| +#include "base/macros.h" | 
| +#include "base/values.h" | 
| +#include "chromecast/base/serializers.h" | 
| +#include "chromecast/media/cma/backend/alsa/slew_volume.h" | 
| +#include "chromecast/public/media/audio_post_processor_shlib.h" | 
| + | 
| +namespace chromecast { | 
| +namespace media { | 
| + | 
| +namespace { | 
| +const int kNoSampleRate = -1; | 
| + | 
| +// Configuration strings: | 
| +const char kOnsetVolumeKey[] = "onset_volume"; | 
| +const char kClampMultiplierKey[] = "clamp_multiplier"; | 
| + | 
| +}  // namespace | 
| + | 
| +// Provides a flat reduction in output volume if the input volume is above a | 
| +// given threshold. | 
| +// Used to protect speakers at high output levels | 
| +// while providing dyanmic range at low output level. | 
| +// The configuration string for this plugin is: | 
| +//  {"onset_volume": |VOLUME_TO_CLAMP|, "clamp_multiplier": |CLAMP_MULTIPLIER|} | 
| +// Input volumes > |VOLUME_TO_CLAMP| will be attenuated by |CLAMP_MULTIPLIER|. | 
| +class Governor : public AudioPostProcessor { | 
| + public: | 
| +  Governor(const std::string& config, int channels); | 
| +  ~Governor(); | 
| + | 
| +  bool SetSampleRate(int sample_rate) override; | 
| +  int ProcessFrames(uint8_t* data, int frames, float volume) override; | 
| +  int GetRingingTimeInFrames() override; | 
| + | 
| + private: | 
| +  float GetGovernorMultiplier(); | 
| + | 
| +  int channels_; | 
| +  int sample_rate_; | 
| +  float volume_; | 
| +  double onset_volume_; | 
| +  double clamp_multiplier_; | 
| +  SlewVolume governor_; | 
| +  DISALLOW_COPY_AND_ASSIGN(Governor); | 
| +}; | 
| + | 
| +Governor::Governor(const std::string& config, int channels) | 
| +    : channels_(channels), sample_rate_(kNoSampleRate), volume_(1.0) { | 
| +  auto config_dict = base::DictionaryValue::From(DeserializeFromJson(config)); | 
| +  CHECK(config_dict) << "Governor config is not valid json: " << config; | 
| +  CHECK(config_dict->GetDouble(kOnsetVolumeKey, &onset_volume_)); | 
| +  CHECK(config_dict->GetDouble(kClampMultiplierKey, &clamp_multiplier_)); | 
| +  governor_.SetVolume(1.0); | 
| +  LOG(INFO) << "Created a governor: onset_volume = " << onset_volume_ | 
| +            << ", clamp_multiplier = " << clamp_multiplier_; | 
| +} | 
| + | 
| +Governor::~Governor() = default; | 
| + | 
| +bool Governor::SetSampleRate(int sample_rate) { | 
| +  sample_rate_ = sample_rate; | 
| +  governor_.SetSampleRate(sample_rate); | 
| +  return true; | 
| +} | 
| + | 
| +int Governor::ProcessFrames(uint8_t* data, int frames, float volume) { | 
| +  if (volume != volume_) { | 
| +    volume_ = volume; | 
| +    governor_.SetVolume(GetGovernorMultiplier()); | 
| +  } | 
| + | 
| +  governor_.ProcessInterleaved(reinterpret_cast<int32_t*>(data), frames); | 
| +  return 0;  // No delay in this pipeline. | 
| +} | 
| + | 
| +int Governor::GetRingingTimeInFrames() { | 
| +  return 0; | 
| +} | 
| + | 
| +float Governor::GetGovernorMultiplier() { | 
| +  if (volume_ >= onset_volume_) { | 
| +    return clamp_multiplier_; | 
| +  } | 
| +  return 1.0; | 
| +} | 
| + | 
| +}  // namespace media | 
| +}  // namespace chromecast | 
| + | 
| +std::unique_ptr<chromecast::media::AudioPostProcessor> | 
| +AudioPostProcessorShlib_Create(const std::string& config, int channels) { | 
| +  return std::unique_ptr<chromecast::media::AudioPostProcessor>( | 
| +      new chromecast::media::Governor(config, channels)); | 
| +} | 
|  |