|  | // Copyright 2016 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // Scale volume with slew rate limiting | 
|  |  | 
|  | #ifndef CHROMECAST_MEDIA_BASE_SLEW_VOLUME_H_ | 
|  | #define CHROMECAST_MEDIA_BASE_SLEW_VOLUME_H_ | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | namespace chromecast { | 
|  | namespace media { | 
|  |  | 
|  | class SlewVolume { | 
|  | public: | 
|  | SlewVolume(); | 
|  | explicit SlewVolume(int max_slew_time_ms); | 
|  | // Use raised negative cosine function when |use_cosine_slew| is true and | 
|  | // linear otherwise. | 
|  | SlewVolume(int max_slew_time_ms, bool use_cosine_slew); | 
|  |  | 
|  | SlewVolume(const SlewVolume&) = delete; | 
|  | SlewVolume& operator=(const SlewVolume&) = delete; | 
|  |  | 
|  | ~SlewVolume() = default; | 
|  |  | 
|  | void SetSampleRate(int sample_rate); | 
|  | void SetVolume(double volume_scale); | 
|  |  | 
|  | // Return the largest multiplier that was applied in the last call to | 
|  | // ProcessFMAC() or ProcessFMUL(). The largest multiplier is used because | 
|  | // that determines the largest possible value in the buffer. | 
|  | float LastBufferMaxMultiplier(); | 
|  | void SetMaxSlewTimeMs(int max_slew_time_ms); | 
|  |  | 
|  | // Called to indicate that the stream was interrupted; volume changes can be | 
|  | // applied immediately. | 
|  | void Interrupted(); | 
|  |  | 
|  | // Smoothly calculates dest[i] += src[i] * |volume_scale|. | 
|  | // |volume_scale| will always be consistent across a frame. | 
|  | // |src| and |dest| are interleaved buffers with |channels| channels and at | 
|  | // least |frames| frames (|channels| * |frames| total size). | 
|  | // |src| and |dest| may be the same. | 
|  | // |src| and |dest| must be 16-byte aligned. | 
|  | // If using planar data, |repeat_transition| should be true for channels 2 | 
|  | // through n, which will cause the slewing process to be repeated. | 
|  | void ProcessFMAC(bool repeat_transition, | 
|  | const float* src, | 
|  | int frames, | 
|  | int channels, | 
|  | float* dest); | 
|  |  | 
|  | // Smoothly calculates dest[i] = src[i] * |volume_scale|. | 
|  | // |volume_scale| will always be consistent across a frame. | 
|  | // |src| and |dest| are interleaved buffers with |channels| channels and at | 
|  | // least |frames| frames (|channels| * |frames| total size). | 
|  | // |src| and |dest| may be the same. | 
|  | // |src| and |dest| must be 16-byte aligned. | 
|  | // If using planar data, |repeat_transition| should be true for channels 2 | 
|  | // through n, which will cause the slewing process to be repeated. | 
|  | void ProcessFMUL(bool repeat_transition, | 
|  | const float* src, | 
|  | int frames, | 
|  | int channels, | 
|  | float* dest); | 
|  |  | 
|  | private: | 
|  | template <typename Traits> | 
|  | void ProcessData(bool repeat_transition, | 
|  | const float* src, | 
|  | int frames, | 
|  | int channels, | 
|  | float* dest); | 
|  |  | 
|  | double sample_rate_; | 
|  | double volume_scale_ = 1.0; | 
|  | double current_volume_ = 1.0; | 
|  | double last_starting_volume_ = 1.0; | 
|  | double max_slew_time_ms_; | 
|  | double max_slew_per_sample_; | 
|  | bool interrupted_ = true; | 
|  | bool use_cosine_slew_ = false; | 
|  | int slew_counter_; | 
|  | double slew_angle_; | 
|  | double slew_offset_; | 
|  | double slew_cos_; | 
|  | double slew_sin_; | 
|  | }; | 
|  |  | 
|  | }  // namespace media | 
|  | }  // namespace chromecast | 
|  |  | 
|  | #endif  // CHROMECAST_MEDIA_BASE_SLEW_VOLUME_H_ |