summaryrefslogtreecommitdiffstats
path: root/dom/media/gtest/TestAudioSampleFormat.cpp
blob: 4737a73a23ffb88ffa0a3477a7fe96f8c0603583 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 *
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "AudioSampleFormat.h"
#include "gtest/gtest.h"
#include <type_traits>

using namespace mozilla;

template <typename T>
constexpr T LowestSample() {
  if constexpr (std::is_integral_v<T>) {
    return std::numeric_limits<T>::lowest();
  } else {
    return -1.0f;
  }
}

// When converting a sample-type to another sample-type, this returns the
// maximum value possible in the destination format
template <typename Dest>
constexpr Dest HighestSample() {
  if constexpr (std::is_integral_v<Dest>) {
    return std::numeric_limits<Dest>::max();
  } else {
    return +1.0f;
  }
}

// When converting a sample-type to another sample-type, this returns the
// maximum value expected in the destination format
template <typename Dest, typename Source>
constexpr Dest HighestSampleExpected() {
  // When converting small integer samples to large integer sample, the higher
  // bound isn't reached because of positive / negative integer assymetry.
  if constexpr (std::is_same_v<Source, uint8_t> &&
                std::is_same_v<Dest, int16_t>) {
    return 32512;  // INT16_MAX - 2 << 7 + 1
  } else if constexpr (std::is_same_v<Source, uint8_t> &&
                       std::is_same_v<Dest, int32_t>) {
    return 2130706432;  // INT32_MAX - (2 << 23) + 1
  } else if constexpr (std::is_same_v<Source, int16_t> &&
                       std::is_same_v<Dest, int32_t>) {
    return 2147418112;  // INT32_MAX - UINT16_MAX
  }

  if constexpr (std::is_integral_v<Dest>) {
    return std::numeric_limits<Dest>::max();
  } else {
    return +1.0f;
  }
}

template <typename Source, typename Dest>
void TestSampleTypePair() {
  std::cout << __PRETTY_FUNCTION__ << std::endl;

  ASSERT_EQ(LowestSample<Dest>(),
            ConvertAudioSample<Dest>(LowestSample<Source>()));
  Dest expected = HighestSampleExpected<Dest, Source>();
  ASSERT_EQ(expected, ConvertAudioSample<Dest>(HighestSample<Source>()));
  ASSERT_EQ(Bias<Dest>(), ConvertAudioSample<Dest>(Bias<Source>()));
}

template <typename T>
void TestSampleType24bits() {
  std::cout << __PRETTY_FUNCTION__ << std::endl;

  int32_t max_sample_24bits = (2 << 22) - 1;
  int32_t min_sample_24bits = -(2 << 22);
  int32_t silence_24bits = 0;

  ASSERT_EQ(LowestSample<T>(), Int24ToAudioSample<T>(min_sample_24bits));
  ASSERT_EQ(Int24ToAudioSample<T>(min_sample_24bits), LowestSample<T>());
  if constexpr (std::is_same_v<T, int32_t>) {
    // Quantization issue: 2147483392 + (2<<8 - 1) == INT32_MAX
    // See comment on HighestSampleExpected above
    const int32_t HIGHEST_FROM_24BITS = 2147483392;
    ASSERT_EQ(HIGHEST_FROM_24BITS, Int24ToAudioSample<T>(max_sample_24bits));
    ASSERT_EQ(Int24ToAudioSample<T>(max_sample_24bits), HIGHEST_FROM_24BITS);
  } else {
    ASSERT_EQ(HighestSample<T>(), Int24ToAudioSample<T>(max_sample_24bits));
    ASSERT_EQ(Int24ToAudioSample<T>(max_sample_24bits), HighestSample<T>());
  }
  ASSERT_EQ(Bias<T>(), Int24ToAudioSample<T>(silence_24bits));
  ASSERT_EQ(Int24ToAudioSample<T>(silence_24bits), Bias<T>());
}

TEST(AudioSampleFormat, Boundaries)
{
  TestSampleTypePair<uint8_t, uint8_t>();
  TestSampleTypePair<uint8_t, int16_t>();
  TestSampleTypePair<uint8_t, int32_t>();
  TestSampleTypePair<uint8_t, float>();
  TestSampleTypePair<int16_t, uint8_t>();
  TestSampleTypePair<int16_t, int16_t>();
  TestSampleTypePair<int16_t, int32_t>();
  TestSampleTypePair<int16_t, float>();
  TestSampleTypePair<int32_t, uint8_t>();
  TestSampleTypePair<int32_t, int16_t>();
  TestSampleTypePair<int32_t, int32_t>();
  TestSampleTypePair<int32_t, float>();
  TestSampleTypePair<float, uint8_t>();
  TestSampleTypePair<float, int16_t>();
  TestSampleTypePair<float, int32_t>();
  TestSampleTypePair<float, float>();

  // Separately test 24-bit audio stored in 32-bits integers.
  TestSampleType24bits<uint8_t>();
  TestSampleType24bits<int16_t>();
  TestSampleType24bits<int32_t>();
  TestSampleType24bits<float>();
}