Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2792)

Unified Diff: chromecast/media/cma/backend/alsa/slew_volume.cc

Issue 2341783004: [chromecast] Slew stream volume changes in StreamMixerAlsa. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chromecast/media/cma/backend/alsa/slew_volume.cc
diff --git a/chromecast/media/cma/backend/alsa/slew_volume.cc b/chromecast/media/cma/backend/alsa/slew_volume.cc
new file mode 100644
index 0000000000000000000000000000000000000000..25254f2cef024830682950f360b69886d5675303
--- /dev/null
+++ b/chromecast/media/cma/backend/alsa/slew_volume.cc
@@ -0,0 +1,147 @@
+// Copyright 2016 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 "chromecast/media/cma/backend/alsa/slew_volume.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "media/base/vector_math.h"
+
+namespace {
+
+// The time to slew from 0.0 to 1.0.
+const int kMaxSlewTimeMs = 100;
+const int kDefaultSampleRate = 44100;
+// ::media::base::FMAC requires |src| to be 16-byte aligned
+const int kRequiredAlignment = 16;
+}
+
+namespace chromecast {
+namespace media {
+
+SlewVolume::SlewVolume() : SlewVolume(kMaxSlewTimeMs, kMaxSlewTimeMs) {}
+
+SlewVolume::SlewVolume(int max_slew_time_up_ms, int max_slew_time_down_ms)
+ : max_slew_time_up_ms_(max_slew_time_up_ms),
+ max_slew_time_down_ms_(max_slew_time_down_ms),
+ max_slew_up_(1000.0 / (max_slew_time_up_ms * kDefaultSampleRate)),
+ max_slew_down_(1000.0 / (max_slew_time_down_ms * kDefaultSampleRate)) {}
+
+// Slew rate should be 1 / (slew_time * sample_rate)
+void SlewVolume::SetSampleRate(int sample_rate) {
+ max_slew_up_ = (1000.0 / (max_slew_time_up_ms_ * sample_rate));
+ max_slew_down_ = (1000.0 / (max_slew_time_down_ms_ * sample_rate));
+}
+
+void SlewVolume::SetVolume(double volume_scale) {
+ volume_scale_ = volume_scale;
+}
+
+bool SlewVolume::ProcessFMAC(const float* src, int frames, float* dest) {
kmackay 2016/09/14 20:48:15 Do we need to return bool? It always returns true
jyw 2016/09/15 01:12:15 Done.
+ DCHECK(src);
+ DCHECK(dest);
+ if (!frames) {
+ return true;
+ }
kmackay 2016/09/14 20:48:15 if (current_volume_ == volume_scale_) { ::media:
jyw 2016/09/15 01:12:15 Done.
+
+ if (current_volume_ < volume_scale_) {
+ do {
+ (*dest) += (*src) * current_volume_;
+ ++src;
+ ++dest;
+ --frames;
+ current_volume_ += max_slew_up_;
+ } while (current_volume_ < volume_scale_ && frames);
+ current_volume_ = std::min(current_volume_, volume_scale_);
+ } else {
+ do {
+ (*dest) += (*src) * current_volume_;
+ ++src;
+ ++dest;
+ --frames;
+ current_volume_ -= max_slew_down_;
+ } while (current_volume_ > volume_scale_ && frames);
+ current_volume_ = std::max(current_volume_, volume_scale_);
+ }
+
+ if (current_volume_ == 0.0) {
+ return true;
+ }
+
+ int unaligned_frames =
kmackay 2016/09/14 20:48:14 prefer to just do the simple naive method here rat
jyw 2016/09/15 01:12:15 Done.
+ (reinterpret_cast<uintptr_t>(src) & (kRequiredAlignment - 1)) /
+ sizeof(float);
+ if (unaligned_frames > 0) {
+ unaligned_frames = kRequiredAlignment / sizeof(float) - unaligned_frames;
+ }
+ if (frames >= unaligned_frames) {
+ for (int f = 0; f < unaligned_frames; ++f) {
+ (*dest) += (*src) * current_volume_;
+ ++src;
+ ++dest;
+ }
+ frames -= unaligned_frames;
+ }
+
+ if (frames) {
+ ::media::vector_math::FMAC(src, volume_scale_, frames, dest);
+ }
+ return true;
+}
+
+// Scaling samples naively like this takes 0.2% of the CPU's time @ 44100hz
+// (profiled with waves_standalone).
+// Assumes 2 channel audio.
+bool SlewVolume::ProcessInterleaved(int32_t* data, int frames) {
+ DCHECK(data);
+
+ if (!frames) {
+ return true;
+ }
kmackay 2016/09/14 20:48:14 if (current_volume_ == volume_scale_) { ::media:
jyw 2016/09/15 01:12:15 can't use FMUL, which requires floats. data is an
+
+ if (current_volume_ < volume_scale_) {
+ do {
+ (*data) *= current_volume_;
kmackay 2016/09/14 20:48:14 It might be nice to have a helper function/macro f
+ ++data;
+ (*data) *= current_volume_;
+ ++data;
+ --frames;
+ current_volume_ += max_slew_up_;
+ } while (current_volume_ < volume_scale_ && frames);
+ current_volume_ = std::min(current_volume_, volume_scale_);
+ } else {
+ do {
+ (*data) *= current_volume_;
+ ++data;
+ (*data) *= current_volume_;
+ ++data;
+ --frames;
+ current_volume_ -= max_slew_down_;
+ } while (current_volume_ > volume_scale_ && frames);
+ current_volume_ = std::max(current_volume_, volume_scale_);
+ }
+
+ if (current_volume_ == 1.0) {
+ return true;
+ }
+
+ if (current_volume_ == 0.0) {
+ std::fill_n(data, frames * 2, 0);
+ return true;
+ }
+
+ while (frames) {
+ (*data) *= current_volume_;
+ ++data;
+ (*data) *= current_volume_;
+ ++data;
+ --frames;
+ }
+
+ return true;
+}
+
+} // namespace media
+} // namespace chromecast

Powered by Google App Engine
This is Rietveld 408576698