aboutsummaryrefslogtreecommitdiff
path: root/common_audio
diff options
context:
space:
mode:
authorAlex Loiko <aleloi@webrtc.org>2018-02-16 10:42:48 +0100
committerCommit Bot <commit-bot@chromium.org>2018-02-16 10:46:48 +0000
commit6df09f6f6a7daf5b6708081f1fb66e711186a306 (patch)
treea349b4d2b0ba15dac8c231490dde86f645a68931 /common_audio
parente4be6dad656a36165534b520e4888eb1717dced3 (diff)
downloadwebrtc-6df09f6f6a7daf5b6708081f1fb66e711186a306.tar.gz
Add decibel conversion functions to //common_audio:common_audio
The functions replace some existing code and will be used in the the new AutomaticGainController. Bug: webrtc:7949 Change-Id: I9a32132d4a4699a507b8548a2eac10972a2f3fd6 Reviewed-on: https://webrtc-review.googlesource.com/53141 Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Commit-Queue: Alex Loiko <aleloi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22045}
Diffstat (limited to 'common_audio')
-rw-r--r--common_audio/audio_util_unittest.cc127
-rw-r--r--common_audio/include/audio_util.h28
2 files changed, 110 insertions, 45 deletions
diff --git a/common_audio/audio_util_unittest.cc b/common_audio/audio_util_unittest.cc
index 7af3c36960..230669ed1e 100644
--- a/common_audio/audio_util_unittest.cc
+++ b/common_audio/audio_util_unittest.cc
@@ -9,6 +9,8 @@
*/
#include "common_audio/include/audio_util.h"
+
+#include "rtc_base/arraysize.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "typedefs.h" // NOLINT(build/include)
@@ -26,84 +28,121 @@ void ExpectArraysEq(const int16_t* ref, const int16_t* test, size_t length) {
void ExpectArraysEq(const float* ref, const float* test, size_t length) {
for (size_t i = 0; i < length; ++i) {
- EXPECT_FLOAT_EQ(ref[i], test[i]);
+ EXPECT_NEAR(ref[i], test[i], 0.01f);
}
}
TEST(AudioUtilTest, FloatToS16) {
- const size_t kSize = 9;
- const float kInput[kSize] = {0.f,
- 0.4f / 32767.f,
- 0.6f / 32767.f,
- -0.4f / 32768.f,
- -0.6f / 32768.f,
- 1.f,
- -1.f,
- 1.1f,
- -1.1f};
- const int16_t kReference[kSize] = {0, 0, 1, 0, -1,
- 32767, -32768, 32767, -32768};
+ static constexpr float kInput[] = {0.f,
+ 0.4f / 32767.f,
+ 0.6f / 32767.f,
+ -0.4f / 32768.f,
+ -0.6f / 32768.f,
+ 1.f,
+ -1.f,
+ 1.1f,
+ -1.1f};
+ static constexpr int16_t kReference[] = {0, 0, 1, 0, -1,
+ 32767, -32768, 32767, -32768};
+ static constexpr size_t kSize = arraysize(kInput);
+ static_assert(arraysize(kReference) == kSize, "");
int16_t output[kSize];
FloatToS16(kInput, kSize, output);
ExpectArraysEq(kReference, output, kSize);
}
TEST(AudioUtilTest, S16ToFloat) {
- const size_t kSize = 7;
- const int16_t kInput[kSize] = {0, 1, -1, 16384, -16384, 32767, -32768};
- const float kReference[kSize] = {
+ static constexpr int16_t kInput[] = {0, 1, -1, 16384, -16384, 32767, -32768};
+ static constexpr float kReference[] = {
0.f, 1.f / 32767.f, -1.f / 32768.f, 16384.f / 32767.f, -0.5f, 1.f, -1.f};
+ static constexpr size_t kSize = arraysize(kInput);
+ static_assert(arraysize(kReference) == kSize, "");
float output[kSize];
S16ToFloat(kInput, kSize, output);
ExpectArraysEq(kReference, output, kSize);
}
TEST(AudioUtilTest, FloatS16ToS16) {
- const size_t kSize = 7;
- const float kInput[kSize] = {0.f, 0.4f, 0.5f, -0.4f,
- -0.5f, 32768.f, -32769.f};
- const int16_t kReference[kSize] = {0, 0, 1, 0, -1, 32767, -32768};
+ static constexpr float kInput[] = {0.f, 0.4f, 0.5f, -0.4f,
+ -0.5f, 32768.f, -32769.f};
+ static constexpr int16_t kReference[] = {0, 0, 1, 0, -1, 32767, -32768};
+ static constexpr size_t kSize = arraysize(kInput);
+ static_assert(arraysize(kReference) == kSize, "");
int16_t output[kSize];
FloatS16ToS16(kInput, kSize, output);
ExpectArraysEq(kReference, output, kSize);
}
TEST(AudioUtilTest, FloatToFloatS16) {
- const size_t kSize = 9;
- const float kInput[kSize] = {0.f,
- 0.4f / 32767.f,
- 0.6f / 32767.f,
- -0.4f / 32768.f,
- -0.6f / 32768.f,
- 1.f,
- -1.f,
- 1.1f,
- -1.1f};
- const float kReference[kSize] = {0.f, 0.4f, 0.6f, -0.4f, -0.6f,
- 32767.f, -32768.f, 36043.7f, -36044.8f};
+ static constexpr float kInput[] = {0.f,
+ 0.4f / 32767.f,
+ 0.6f / 32767.f,
+ -0.4f / 32768.f,
+ -0.6f / 32768.f,
+ 1.f,
+ -1.f,
+ 1.1f,
+ -1.1f};
+ static constexpr float kReference[] = {
+ 0.f, 0.4f, 0.6f, -0.4f, -0.6f, 32767.f, -32768.f, 36043.7f, -36044.8f};
+ static constexpr size_t kSize = arraysize(kInput);
+ static_assert(arraysize(kReference) == kSize, "");
float output[kSize];
FloatToFloatS16(kInput, kSize, output);
ExpectArraysEq(kReference, output, kSize);
}
TEST(AudioUtilTest, FloatS16ToFloat) {
- const size_t kSize = 9;
- const float kInput[kSize] = {0.f, 0.4f, 0.6f, -0.4f, -0.6f,
- 32767.f, -32768.f, 36043.7f, -36044.8f};
- const float kReference[kSize] = {0.f,
- 0.4f / 32767.f,
- 0.6f / 32767.f,
- -0.4f / 32768.f,
- -0.6f / 32768.f,
- 1.f,
- -1.f,
- 1.1f,
- -1.1f};
+ static constexpr float kInput[] = {
+ 0.f, 0.4f, 0.6f, -0.4f, -0.6f, 32767.f, -32768.f, 36043.7f, -36044.8f};
+ static constexpr float kReference[] = {0.f,
+ 0.4f / 32767.f,
+ 0.6f / 32767.f,
+ -0.4f / 32768.f,
+ -0.6f / 32768.f,
+ 1.f,
+ -1.f,
+ 1.1f,
+ -1.1f};
+ static constexpr size_t kSize = arraysize(kInput);
+ static_assert(arraysize(kReference) == kSize, "");
float output[kSize];
FloatS16ToFloat(kInput, kSize, output);
ExpectArraysEq(kReference, output, kSize);
}
+TEST(AudioUtilTest, DbfsToFloatS16) {
+ static constexpr float kInput[] = {-90.f, -70.f, -30.f, -20.f, -10.f,
+ -5.f, -1.f, 0.f, 1.f};
+ static constexpr float kReference[] = {
+ 1.036215186f, 10.36215115f, 1036.215088f, 3276.800049f, 10362.15137f,
+ 18426.80078f, 29204.51172f, 32768.f, 36766.30078f};
+ static constexpr size_t kSize = arraysize(kInput);
+ static_assert(arraysize(kReference) == kSize, "");
+ float output[kSize];
+ for (size_t i = 0; i < kSize; ++i) {
+ output[i] = DbfsToFloatS16(kInput[i]);
+ }
+ ExpectArraysEq(kReference, output, kSize);
+}
+
+TEST(AudioUtilTest, FloatS16ToDbfs) {
+ static constexpr float kInput[] = {1.036215143f, 10.36215143f, 1036.215143f,
+ 3276.8f, 10362.151436f, 18426.800543f,
+ 29204.51074f, 32768.0f, 36766.30071f};
+
+ static constexpr float kReference[] = {
+ -90.f, -70.f, -30.f, -20.f, -10.f, -5.f, -1.f, 0.f, 0.9999923706f};
+ static constexpr size_t kSize = arraysize(kInput);
+ static_assert(arraysize(kReference) == kSize, "");
+
+ float output[kSize];
+ for (size_t i = 0; i < kSize; ++i) {
+ output[i] = FloatS16ToDbfs(kInput[i]);
+ }
+ ExpectArraysEq(kReference, output, kSize);
+}
+
TEST(AudioUtilTest, InterleavingStereo) {
const int16_t kInterleaved[] = {2, 3, 4, 9, 8, 27, 16, 81};
const size_t kSamplesPerChannel = 4;
diff --git a/common_audio/include/audio_util.h b/common_audio/include/audio_util.h
index b9e1b26b0d..e4ea9a1a33 100644
--- a/common_audio/include/audio_util.h
+++ b/common_audio/include/audio_util.h
@@ -12,8 +12,9 @@
#define COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
#include <algorithm>
-#include <limits>
+#include <cmath>
#include <cstring>
+#include <limits>
#include "rtc_base/checks.h"
#include "typedefs.h" // NOLINT(build/include)
@@ -26,6 +27,10 @@ typedef std::numeric_limits<int16_t> limits_int16;
// S16: int16_t [-32768, 32767]
// Float: float [-1.0, 1.0]
// FloatS16: float [-32768.0, 32767.0]
+// Dbfs: float [-20.0*log(10, 32768), 0] = [-90.3, 0]
+// The ratio conversion functions use this naming convention:
+// Ratio: float (0, +inf)
+// Db: float (-inf, +inf)
static inline int16_t FloatToS16(float v) {
if (v > 0)
return v >= 1 ? limits_int16::max()
@@ -65,6 +70,27 @@ void FloatS16ToS16(const float* src, size_t size, int16_t* dest);
void FloatToFloatS16(const float* src, size_t size, float* dest);
void FloatS16ToFloat(const float* src, size_t size, float* dest);
+inline float DbToRatio(float v) {
+ return std::pow(10.0f, v / 20.0f);
+}
+
+inline float DbfsToFloatS16(float v) {
+ static constexpr float kMaximumAbsFloatS16 = -limits_int16::min();
+ return DbToRatio(v) * kMaximumAbsFloatS16;
+}
+
+inline float FloatS16ToDbfs(float v) {
+ RTC_DCHECK_GE(v, 0);
+
+ // kMinDbfs is equal to -20.0 * log10(-limits_int16::min())
+ static constexpr float kMinDbfs = -90.30899869919436f;
+ if (v <= 1.0f) {
+ return kMinDbfs;
+ }
+ // Equal to 20 * log10(v / (-limits_int16::min()))
+ return 20.0f * std::log10(v) + kMinDbfs;
+}
+
// Copy audio from |src| channels to |dest| channels unless |src| and |dest|
// point to the same address. |src| and |dest| must have the same number of
// channels, and there must be sufficient space allocated in |dest|.