markdr | dd1893d | 2018-02-05 17:13:47 -0800 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
tturney | 91191de | 2017-11-16 15:07:17 -0800 | [diff] [blame] | 2 | # |
| 3 | # Copyright 2017 - The Android Open Source Project |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | |
| 17 | import logging |
| 18 | import math |
| 19 | import numpy |
| 20 | import unittest |
| 21 | |
| 22 | import acts.test_utils.audio_analysis_lib.audio_data as audio_data |
| 23 | import acts.test_utils.audio_analysis_lib.audio_analysis as audio_analysis |
| 24 | import acts.test_utils.audio_analysis_lib.audio_quality_measurement as \ |
| 25 | audio_quality_measurement |
| 26 | |
| 27 | |
| 28 | class NoiseLevelTest(unittest.TestCase): |
| 29 | def setUp(self): |
| 30 | """Uses the same seed to generate noise for each test.""" |
| 31 | numpy.random.seed(0) |
| 32 | |
| 33 | def testNoiseLevel(self): |
| 34 | # Generates the standard sin wave with standard_noise portion of noise. |
| 35 | rate = 48000 |
| 36 | length_in_secs = 2 |
| 37 | frequency = 440 |
| 38 | amplitude = 1 |
| 39 | standard_noise = 0.05 |
| 40 | |
| 41 | wave = [] |
| 42 | for index in range(0, rate * length_in_secs): |
| 43 | phase = 2.0 * math.pi * frequency * float(index) / float(rate) |
| 44 | sine_wave = math.sin(phase) |
| 45 | noise = standard_noise * numpy.random.standard_normal() |
| 46 | wave.append(float(amplitude) * (sine_wave + noise)) |
| 47 | |
| 48 | # Calculates the average value after applying teager operator. |
| 49 | teager_value_of_wave, length = 0, len(wave) |
| 50 | for i in range(1, length - 1): |
| 51 | ith_teager_value = abs(wave[i] * wave[i] - wave[i - 1] * wave[i + |
| 52 | 1]) |
| 53 | ith_teager_value *= max(1, abs(wave[i])) |
| 54 | teager_value_of_wave += ith_teager_value |
| 55 | teager_value_of_wave /= float(length * (amplitude**2)) |
| 56 | |
| 57 | noise = audio_quality_measurement.noise_level( |
| 58 | amplitude, frequency, rate, teager_value_of_wave) |
| 59 | |
| 60 | self.assertTrue(abs(noise - standard_noise) < 0.01) |
| 61 | |
| 62 | |
| 63 | class ErrorTest(unittest.TestCase): |
| 64 | def testError(self): |
| 65 | value1 = [0.2, 0.4, 0.1, 0.01, 0.01, 0.01] |
| 66 | value2 = [0.3, 0.3, 0.08, 0.0095, 0.0098, 0.0099] |
| 67 | error = [0.5, 0.25, 0.2, 0.05, 0.02, 0.01] |
| 68 | for i in range(len(value1)): |
| 69 | ret = audio_quality_measurement.error(value1[i], value2[i]) |
| 70 | self.assertTrue(abs(ret - error[i]) < 0.001) |
| 71 | |
| 72 | |
| 73 | class QualityMeasurementTest(unittest.TestCase): |
| 74 | def setUp(self): |
| 75 | """Creates a test signal of sine wave.""" |
| 76 | numpy.random.seed(0) |
| 77 | |
| 78 | self.rate = 48000 |
| 79 | self.freq = 440 |
| 80 | self.amplitude = 1 |
| 81 | length_in_secs = 2 |
| 82 | self.samples = length_in_secs * self.rate |
| 83 | self.y = [] |
| 84 | for index in range(self.samples): |
| 85 | phase = 2.0 * math.pi * self.freq * float(index) / float(self.rate) |
| 86 | sine_wave = math.sin(phase) |
| 87 | self.y.append(float(self.amplitude) * sine_wave) |
| 88 | |
| 89 | def add_noise(self): |
| 90 | """Adds noise to the test signal.""" |
| 91 | noise_amplitude = 0.01 * self.amplitude |
| 92 | for index in range(self.samples): |
| 93 | noise = noise_amplitude * numpy.random.standard_normal() |
| 94 | self.y[index] += noise |
| 95 | |
| 96 | def generate_delay(self): |
| 97 | """Generates some delays during playing.""" |
| 98 | self.delay_start_time = [0.200, 0.375, 0.513, 0.814, 1.000, 1.300] |
| 99 | self.delay_end_time = [0.201, 0.377, 0.516, 0.824, 1.100, 1.600] |
| 100 | |
| 101 | for i in range(len(self.delay_start_time)): |
| 102 | start_index = int(self.delay_start_time[i] * self.rate) |
| 103 | end_index = int(self.delay_end_time[i] * self.rate) |
| 104 | for j in range(start_index, end_index): |
| 105 | self.y[j] = 0 |
| 106 | |
| 107 | def generate_artifacts_before_playback(self): |
| 108 | """Generates artifacts before playing.""" |
| 109 | silence_before_playback_end_time = 0.2 |
| 110 | end_index = int(silence_before_playback_end_time * self.rate) |
| 111 | for i in range(0, end_index): |
| 112 | self.y[i] = 0 |
| 113 | noise_start_index = int(0.1 * self.rate) |
| 114 | noise_end_index = int(0.1005 * self.rate) |
| 115 | for i in range(noise_start_index, noise_end_index): |
| 116 | self.y[i] = 3 * self.amplitude |
| 117 | |
| 118 | def generate_artifacts_after_playback(self): |
| 119 | """Generates artifacts after playing.""" |
| 120 | silence_after_playback_start_time = int(1.9 * self.rate) |
| 121 | noise_start_index = int(1.95 * self.rate) |
| 122 | noise_end_index = int((1.95 + 0.02) * self.rate) |
| 123 | |
| 124 | for i in range(silence_after_playback_start_time, self.samples): |
| 125 | self.y[i] = 0 |
| 126 | for i in range(noise_start_index, noise_end_index): |
| 127 | self.y[i] = self.amplitude |
| 128 | |
| 129 | def generate_burst_during_playback(self): |
| 130 | """Generates bursts during playing.""" |
| 131 | self.burst_start_time = [0.300, 0.475, 0.613, 0.814, 1.300] |
| 132 | self.burst_end_time = [0.301, 0.476, 0.614, 0.815, 1.301] |
| 133 | |
| 134 | for i in range(len(self.burst_start_time)): |
| 135 | start_index = int(self.burst_start_time[i] * self.rate) |
| 136 | end_index = int(self.burst_end_time[i] * self.rate) |
| 137 | for j in range(start_index, end_index): |
| 138 | self.y[j] = self.amplitude * (3 + numpy.random.uniform(-1, 1)) |
| 139 | |
| 140 | def generate_volume_changing(self): |
| 141 | "Generates volume changing during playing." |
| 142 | start_time = [0.300, 1.400] |
| 143 | end_time = [0.600, 1.700] |
| 144 | for i in range(len(start_time)): |
| 145 | start_index = int(start_time[i] * self.rate) |
| 146 | end_index = int(end_time[i] * self.rate) |
| 147 | for j in range(start_index, end_index): |
| 148 | self.y[j] *= 1.4 |
| 149 | self.volume_changing = [+1, -1, +1, -1] |
| 150 | self.volume_changing_time = [0.3, 0.6, 1.4, 1.7] |
| 151 | |
| 152 | def testGoodSignal(self): |
| 153 | """Sine wave signal with no noise or artifacts.""" |
| 154 | result = audio_quality_measurement.quality_measurement(self.y, |
| 155 | self.rate) |
| 156 | self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) |
| 157 | self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) |
| 158 | self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) |
| 159 | self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0) |
| 160 | self.assertTrue(len(result['volume_changes']) == 0) |
| 161 | self.assertTrue(result['equivalent_noise_level'] < 0.005) |
| 162 | |
| 163 | def testGoodSignalNoise(self): |
| 164 | """Sine wave signal with noise.""" |
| 165 | self.add_noise() |
| 166 | result = audio_quality_measurement.quality_measurement(self.y, |
| 167 | self.rate) |
| 168 | self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) |
| 169 | self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) |
| 170 | self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) |
| 171 | self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0) |
| 172 | self.assertTrue(len(result['volume_changes']) == 0) |
| 173 | self.assertTrue(0.009 < result['equivalent_noise_level'] and |
| 174 | result['equivalent_noise_level'] < 0.011) |
| 175 | |
| 176 | def testDelay(self): |
| 177 | """Sine wave with delay during playing.""" |
| 178 | self.generate_delay() |
| 179 | result = audio_quality_measurement.quality_measurement(self.y, |
| 180 | self.rate) |
| 181 | self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) |
| 182 | self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) |
| 183 | self.assertTrue( |
| 184 | len(result['volume_changes']) == 2 * len(self.delay_start_time)) |
| 185 | self.assertTrue(result['equivalent_noise_level'] < 0.005) |
| 186 | |
| 187 | self.assertTrue( |
| 188 | len(result['artifacts']['delay_during_playback']) == |
| 189 | len(self.delay_start_time)) |
| 190 | for i in range(len(result['artifacts']['delay_during_playback'])): |
| 191 | delta = abs(result['artifacts']['delay_during_playback'][i][0] - |
| 192 | self.delay_start_time[i]) |
| 193 | self.assertTrue(delta < 0.001) |
| 194 | duration = self.delay_end_time[i] - self.delay_start_time[i] |
| 195 | delta = abs(result['artifacts']['delay_during_playback'][i][1] - |
| 196 | duration) |
| 197 | self.assertTrue(delta < 0.001) |
| 198 | |
| 199 | def testArtifactsBeforePlayback(self): |
| 200 | """Sine wave with artifacts before playback.""" |
| 201 | self.generate_artifacts_before_playback() |
| 202 | result = audio_quality_measurement.quality_measurement(self.y, |
| 203 | self.rate) |
| 204 | self.assertTrue(len(result['artifacts']['noise_before_playback']) == 1) |
| 205 | delta = abs(result['artifacts']['noise_before_playback'][0][0] - 0.1) |
| 206 | self.assertTrue(delta < 0.01) |
| 207 | delta = abs(result['artifacts']['noise_before_playback'][0][1] - 0.005) |
| 208 | self.assertTrue(delta < 0.004) |
| 209 | self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) |
| 210 | self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) |
| 211 | self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0) |
| 212 | self.assertTrue(len(result['volume_changes']) == 0) |
| 213 | self.assertTrue(result['equivalent_noise_level'] < 0.005) |
| 214 | |
| 215 | def testArtifactsAfterPlayback(self): |
| 216 | """Sine wave with artifacts after playback.""" |
| 217 | self.generate_artifacts_after_playback() |
| 218 | result = audio_quality_measurement.quality_measurement(self.y, |
| 219 | self.rate) |
| 220 | self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) |
| 221 | self.assertTrue(len(result['artifacts']['noise_after_playback']) == 1) |
| 222 | delta = abs(result['artifacts']['noise_after_playback'][0][0] - 1.95) |
| 223 | self.assertTrue(delta < 0.01) |
| 224 | delta = abs(result['artifacts']['noise_after_playback'][0][1] - 0.02) |
| 225 | self.assertTrue(delta < 0.001) |
| 226 | self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) |
| 227 | self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0) |
| 228 | self.assertTrue(len(result['volume_changes']) == 0) |
| 229 | self.assertTrue(result['equivalent_noise_level'] < 0.005) |
| 230 | |
| 231 | def testBurstDuringPlayback(self): |
| 232 | """Sine wave with burst during playback.""" |
| 233 | self.generate_burst_during_playback() |
| 234 | result = audio_quality_measurement.quality_measurement(self.y, |
| 235 | self.rate) |
| 236 | self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) |
| 237 | self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) |
| 238 | self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) |
| 239 | self.assertTrue(len(result['artifacts']['burst_during_playback']) == 5) |
| 240 | self.assertTrue(len(result['volume_changes']) == 10) |
| 241 | self.assertTrue(result['equivalent_noise_level'] > 0.02) |
| 242 | for i in range(len(result['artifacts']['burst_during_playback'])): |
| 243 | delta = abs(self.burst_start_time[i] - result['artifacts'][ |
| 244 | 'burst_during_playback'][i]) |
| 245 | self.assertTrue(delta < 0.002) |
| 246 | |
| 247 | def testVolumeChanging(self): |
| 248 | """Sine wave with volume changing during playback.""" |
| 249 | self.generate_volume_changing() |
| 250 | result = audio_quality_measurement.quality_measurement(self.y, |
| 251 | self.rate) |
| 252 | self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) |
| 253 | self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) |
| 254 | self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) |
| 255 | self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0) |
| 256 | self.assertTrue(result['equivalent_noise_level'] < 0.005) |
| 257 | self.assertTrue( |
| 258 | len(result['volume_changes']) == len(self.volume_changing)) |
| 259 | for i in range(len(self.volume_changing)): |
| 260 | self.assertTrue( |
| 261 | abs(self.volume_changing_time[i] - result['volume_changes'][i][ |
| 262 | 0]) < 0.01) |
| 263 | self.assertTrue( |
| 264 | self.volume_changing[i] == result['volume_changes'][i][1]) |
| 265 | |
| 266 | |
| 267 | if __name__ == '__main__': |
| 268 | unittest.main() |