1#!/usr/bin/env python3 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# Note: This test has been labelled as an integration test due to its use of 18# real data, and the 12+ second execution time. It also generates sine waves 19# during the test, rather than using data that has been pre-calculated. 20 21import math 22import numpy 23import unittest 24 25# TODO(markdr): Remove this after soundfile is added to setup.py 26import sys 27import mock 28sys.modules['soundfile'] = mock.Mock() 29 30import acts.test_utils.audio_analysis_lib.audio_quality_measurement as audio_quality_measurement 31 32 33class NoiseLevelTest(unittest.TestCase): 34 def setUp(self): 35 """Uses the same seed to generate noise for each test.""" 36 numpy.random.seed(0) 37 38 def test_noise_level(self): 39 # Generates the standard sin wave with standard_noise portion of noise. 40 rate = 48000 41 length_in_secs = 2 42 frequency = 440 43 amplitude = 1 44 standard_noise = 0.05 45 46 wave = [] 47 for index in range(0, rate * length_in_secs): 48 phase = 2.0 * math.pi * frequency * float(index) / float(rate) 49 sine_wave = math.sin(phase) 50 noise = standard_noise * numpy.random.standard_normal() 51 wave.append(float(amplitude) * (sine_wave + noise)) 52 53 # Calculates the average value after applying teager operator. 54 teager_value_of_wave, length = 0, len(wave) 55 for i in range(1, length - 1): 56 ith_teager_value = abs(wave[i] * wave[i] - wave[i - 1] * wave[i + 57 1]) 58 ith_teager_value *= max(1, abs(wave[i])) 59 teager_value_of_wave += ith_teager_value 60 teager_value_of_wave /= float(length * (amplitude**2)) 61 62 noise = audio_quality_measurement.noise_level( 63 amplitude, frequency, rate, teager_value_of_wave) 64 65 self.assertTrue(abs(noise - standard_noise) < 0.01) 66 67 68class ErrorTest(unittest.TestCase): 69 def test_error(self): 70 value1 = [0.2, 0.4, 0.1, 0.01, 0.01, 0.01] 71 value2 = [0.3, 0.3, 0.08, 0.0095, 0.0098, 0.0099] 72 error = [0.5, 0.25, 0.2, 0.05, 0.02, 0.01] 73 for i in range(len(value1)): 74 ret = audio_quality_measurement.error(value1[i], value2[i]) 75 self.assertTrue(abs(ret - error[i]) < 0.001) 76 77 78class QualityMeasurementTest(unittest.TestCase): 79 def setUp(self): 80 """Creates a test signal of sine wave.""" 81 numpy.random.seed(0) 82 83 self.rate = 48000 84 self.freq = 440 85 self.amplitude = 1 86 length_in_secs = 2 87 self.samples = length_in_secs * self.rate 88 self.y = [] 89 for index in range(self.samples): 90 phase = 2.0 * math.pi * self.freq * float(index) / float(self.rate) 91 sine_wave = math.sin(phase) 92 self.y.append(float(self.amplitude) * sine_wave) 93 94 def add_noise(self): 95 """Adds noise to the test signal.""" 96 noise_amplitude = 0.01 * self.amplitude 97 for index in range(self.samples): 98 noise = noise_amplitude * numpy.random.standard_normal() 99 self.y[index] += noise 100 101 def generate_delay(self): 102 """Generates some delays during playing.""" 103 self.delay_start_time = [0.200, 0.375, 0.513, 0.814, 1.000, 1.300] 104 self.delay_end_time = [0.201, 0.377, 0.516, 0.824, 1.100, 1.600] 105 106 for i in range(len(self.delay_start_time)): 107 start_index = int(self.delay_start_time[i] * self.rate) 108 end_index = int(self.delay_end_time[i] * self.rate) 109 for j in range(start_index, end_index): 110 self.y[j] = 0 111 112 def generate_artifacts_before_playback(self): 113 """Generates artifacts before playing.""" 114 silence_before_playback_end_time = 0.2 115 end_index = int(silence_before_playback_end_time * self.rate) 116 for i in range(0, end_index): 117 self.y[i] = 0 118 noise_start_index = int(0.1 * self.rate) 119 noise_end_index = int(0.1005 * self.rate) 120 for i in range(noise_start_index, noise_end_index): 121 self.y[i] = 3 * self.amplitude 122 123 def generate_artifacts_after_playback(self): 124 """Generates artifacts after playing.""" 125 silence_after_playback_start_time = int(1.9 * self.rate) 126 noise_start_index = int(1.95 * self.rate) 127 noise_end_index = int((1.95 + 0.02) * self.rate) 128 129 for i in range(silence_after_playback_start_time, self.samples): 130 self.y[i] = 0 131 for i in range(noise_start_index, noise_end_index): 132 self.y[i] = self.amplitude 133 134 def generate_burst_during_playback(self): 135 """Generates bursts during playing.""" 136 self.burst_start_time = [0.300, 0.475, 0.613, 0.814, 1.300] 137 self.burst_end_time = [0.301, 0.476, 0.614, 0.815, 1.301] 138 139 for i in range(len(self.burst_start_time)): 140 start_index = int(self.burst_start_time[i] * self.rate) 141 end_index = int(self.burst_end_time[i] * self.rate) 142 for j in range(start_index, end_index): 143 self.y[j] = self.amplitude * (3 + numpy.random.uniform(-1, 1)) 144 145 def generate_volume_changing(self): 146 """Generates volume changing during playing.""" 147 start_time = [0.300, 1.400] 148 end_time = [0.600, 1.700] 149 for i in range(len(start_time)): 150 start_index = int(start_time[i] * self.rate) 151 end_index = int(end_time[i] * self.rate) 152 for j in range(start_index, end_index): 153 self.y[j] *= 1.4 154 self.volume_changing = [+1, -1, +1, -1] 155 self.volume_changing_time = [0.3, 0.6, 1.4, 1.7] 156 157 def test_good_signal(self): 158 """Sine wave signal with no noise or artifacts.""" 159 result = audio_quality_measurement.quality_measurement(self.y, 160 self.rate) 161 self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) 162 self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) 163 self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) 164 self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0) 165 self.assertTrue(len(result['volume_changes']) == 0) 166 self.assertTrue(result['equivalent_noise_level'] < 0.005) 167 168 def test_good_signal_with_noise(self): 169 """Sine wave signal with noise.""" 170 self.add_noise() 171 result = audio_quality_measurement.quality_measurement(self.y, 172 self.rate) 173 self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) 174 self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) 175 self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) 176 self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0) 177 self.assertTrue(len(result['volume_changes']) == 0) 178 self.assertTrue(0.009 < result['equivalent_noise_level'] < 0.011) 179 180 def test_delay(self): 181 """Sine wave with delay during playing.""" 182 self.generate_delay() 183 result = audio_quality_measurement.quality_measurement(self.y, 184 self.rate) 185 self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) 186 self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) 187 self.assertTrue( 188 len(result['volume_changes']) == 2 * len(self.delay_start_time)) 189 self.assertTrue(result['equivalent_noise_level'] < 0.005) 190 191 self.assertTrue( 192 len(result['artifacts']['delay_during_playback']) == 193 len(self.delay_start_time)) 194 for i in range(len(result['artifacts']['delay_during_playback'])): 195 delta = abs(result['artifacts']['delay_during_playback'][i][0] - 196 self.delay_start_time[i]) 197 self.assertTrue(delta < 0.001) 198 duration = self.delay_end_time[i] - self.delay_start_time[i] 199 delta = abs(result['artifacts']['delay_during_playback'][i][1] - 200 duration) 201 self.assertTrue(delta < 0.001) 202 203 def test_artifacts_before_playback(self): 204 """Sine wave with artifacts before playback.""" 205 self.generate_artifacts_before_playback() 206 result = audio_quality_measurement.quality_measurement(self.y, 207 self.rate) 208 self.assertTrue(len(result['artifacts']['noise_before_playback']) == 1) 209 delta = abs(result['artifacts']['noise_before_playback'][0][0] - 0.1) 210 self.assertTrue(delta < 0.01) 211 delta = abs(result['artifacts']['noise_before_playback'][0][1] - 0.005) 212 self.assertTrue(delta < 0.004) 213 self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) 214 self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) 215 self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0) 216 self.assertTrue(len(result['volume_changes']) == 0) 217 self.assertTrue(result['equivalent_noise_level'] < 0.005) 218 219 def test_artifacts_after_playback(self): 220 """Sine wave with artifacts after playback.""" 221 self.generate_artifacts_after_playback() 222 result = audio_quality_measurement.quality_measurement(self.y, 223 self.rate) 224 self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) 225 self.assertTrue(len(result['artifacts']['noise_after_playback']) == 1) 226 delta = abs(result['artifacts']['noise_after_playback'][0][0] - 1.95) 227 self.assertTrue(delta < 0.01) 228 delta = abs(result['artifacts']['noise_after_playback'][0][1] - 0.02) 229 self.assertTrue(delta < 0.001) 230 self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) 231 self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0) 232 self.assertTrue(len(result['volume_changes']) == 0) 233 self.assertTrue(result['equivalent_noise_level'] < 0.005) 234 235 def test_burst_during_playback(self): 236 """Sine wave with burst during playback.""" 237 self.generate_burst_during_playback() 238 result = audio_quality_measurement.quality_measurement(self.y, 239 self.rate) 240 self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) 241 self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) 242 self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) 243 self.assertTrue(len(result['artifacts']['burst_during_playback']) == 5) 244 self.assertTrue(len(result['volume_changes']) == 10) 245 self.assertTrue(result['equivalent_noise_level'] > 0.02) 246 for i in range(len(result['artifacts']['burst_during_playback'])): 247 delta = abs(self.burst_start_time[i] - result['artifacts'][ 248 'burst_during_playback'][i]) 249 self.assertTrue(delta < 0.002) 250 251 def test_volume_changing(self): 252 """Sine wave with volume changing during playback.""" 253 self.generate_volume_changing() 254 result = audio_quality_measurement.quality_measurement(self.y, 255 self.rate) 256 self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0) 257 self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0) 258 self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0) 259 self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0) 260 self.assertTrue(result['equivalent_noise_level'] < 0.005) 261 self.assertTrue( 262 len(result['volume_changes']) == len(self.volume_changing)) 263 for i in range(len(self.volume_changing)): 264 self.assertTrue( 265 abs(self.volume_changing_time[i] - result['volume_changes'][i][ 266 0]) < 0.01) 267 self.assertTrue( 268 self.volume_changing[i] == result['volume_changes'][i][1]) 269 270 271if __name__ == '__main__': 272 unittest.main() 273