1#!/usr/bin/env python2
2# Copyright 2016 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6from __future__ import absolute_import
7from __future__ import division
8from __future__ import print_function
9
10import logging
11import math
12import numpy
13import unittest
14
15import common
16from autotest_lib.client.cros.audio import audio_data
17from autotest_lib.client.cros.audio import audio_quality_measurement
18from six.moves import range
19
20class NoiseLevelTest(unittest.TestCase):
21    def setUp(self):
22        """Uses the same seed to generate noise for each test."""
23        numpy.random.seed(0)
24
25
26    def testNoiseLevel(self):
27        # Generates the standard sin wave with standard_noise portion of noise.
28        rate = 48000
29        length_in_secs = 2
30        frequency = 440
31        amplitude = 1
32        standard_noise = 0.05
33
34        wave = []
35        for index in range(0, rate * length_in_secs):
36            phase = 2.0 * math.pi * frequency * float(index) / float(rate)
37            sine_wave = math.sin(phase)
38            noise = standard_noise * numpy.random.standard_normal()
39            wave.append(float(amplitude) * (sine_wave + noise))
40
41        # Calculates the average value after applying teager operator.
42        teager_value_of_wave, length = 0, len(wave)
43        for i in range(1, length-1):
44            ith_teager_value = abs(wave[i] * wave[i] - wave[i - 1] * wave[i + 1])
45            ith_teager_value *= max(1, abs(wave[i]))
46            teager_value_of_wave += ith_teager_value
47        teager_value_of_wave /= float(length * (amplitude ** 2))
48
49        noise = audio_quality_measurement.noise_level(amplitude, frequency,
50                                                      rate,
51                                                      teager_value_of_wave)
52
53        self.assertTrue(abs(noise - standard_noise) < 0.01)
54
55
56class ErrorTest(unittest.TestCase):
57    def testError(self):
58        value1 = [0.2, 0.4, 0.1, 0.01, 0.01, 0.01]
59        value2 = [0.3, 0.3, 0.08, 0.0095, 0.0098, 0.0099]
60        error  = [0.5, 0.25, 0.2, 0.05, 0.02, 0.01]
61        for i in range( len(value1) ):
62          ret = audio_quality_measurement.error(value1[i], value2[i])
63          self.assertTrue(abs(ret - error[i]) < 0.001)
64
65
66class QualityMeasurementTest(unittest.TestCase):
67    def setUp(self):
68        """Creates a test signal of sine wave."""
69        numpy.random.seed(0)
70
71        self.rate = 48000
72        self.freq = 440
73        self.amplitude = 1
74        length_in_secs = 2
75        self.samples = length_in_secs * self.rate
76        self.y = []
77        for index in range(self.samples):
78            phase = 2.0 * math.pi * self.freq * float(index) / float(self.rate)
79            sine_wave = math.sin(phase)
80            self.y.append(float(self.amplitude) * sine_wave)
81
82
83    def add_noise(self):
84        """Adds noise to the test signal."""
85        noise_amplitude = 0.01 * self.amplitude
86        for index in range(self.samples):
87            noise = noise_amplitude * numpy.random.standard_normal()
88            self.y[index] += noise
89
90
91    def generate_delay(self):
92        """Generates some delays during playing."""
93        self.delay_start_time = [0.200, 0.375, 0.513, 0.814, 1.000, 1.300]
94        self.delay_end_time   = [0.201, 0.377, 0.516, 0.824, 1.100, 1.600]
95
96        for i in range(len(self.delay_start_time)):
97            start_index = int(self.delay_start_time[i] * self.rate)
98            end_index   = int(self.delay_end_time[i]   * self.rate)
99            for j in range(start_index,end_index):
100                self.y[j] = 0
101
102
103    def generate_artifacts_before_playback(self):
104        """Generates artifacts before playing."""
105        silence_before_playback_end_time = 0.2
106        end_index = int(silence_before_playback_end_time * self.rate)
107        for i in range(0, end_index):
108            self.y[i] = 0
109        noise_start_index = int(0.1 * self.rate)
110        noise_end_index = int(0.1005 * self.rate)
111        for i in range(noise_start_index, noise_end_index):
112            self.y[i] = 3 * self.amplitude
113
114
115    def generate_artifacts_after_playback(self):
116        """Generates artifacts after playing."""
117        silence_after_playback_start_time = int(1.9 * self.rate)
118        noise_start_index = int(1.95 * self.rate)
119        noise_end_index = int((1.95 + 0.02) * self.rate)
120
121        for i in range(silence_after_playback_start_time, self.samples):
122            self.y[i] = 0
123        for i in range(noise_start_index, noise_end_index):
124            self.y[i] = self.amplitude
125
126
127    def generate_burst_during_playback(self):
128        """Generates bursts during playing."""
129        self.burst_start_time = [0.300, 0.475, 0.613, 0.814, 1.300]
130        self.burst_end_time   = [0.301, 0.476, 0.614, 0.815, 1.301]
131
132        for i in range(len(self.burst_start_time)):
133            start_index = int(self.burst_start_time[i] * self.rate)
134            end_index   = int(self.burst_end_time[i]   * self.rate)
135            for j in range(start_index, end_index):
136                self.y[j] = self.amplitude * (3 + numpy.random.uniform(-1, 1))
137
138
139    def generate_volume_changing(self):
140        "Generates volume changing during playing."
141        start_time = [0.300, 1.400]
142        end_time   = [0.600, 1.700]
143        for i in range(len(start_time)):
144            start_index = int(start_time[i] * self.rate)
145            end_index   = int(end_time[i]   * self.rate)
146            for j in range(start_index,end_index):
147                self.y[j] *= 1.4
148        self.volume_changing = [+1, -1, +1, -1]
149        self.volume_changing_time = [0.3, 0.6, 1.4, 1.7]
150
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
164    def testGoodSignalNoise(self):
165        """Sine wave signal with noise."""
166        self.add_noise();
167        result = audio_quality_measurement.quality_measurement(self.y,
168                                                               self.rate)
169        self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0)
170        self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0)
171        self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0)
172        self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0)
173        self.assertTrue(len(result['volume_changes']) == 0)
174        self.assertTrue(0.009 < result['equivalent_noise_level'] and
175                                result['equivalent_noise_level'] < 0.011)
176
177
178    def testDelay(self):
179        """Sine wave with delay during playing."""
180        self.generate_delay()
181        result = audio_quality_measurement.quality_measurement(self.y,
182                                                               self.rate)
183        self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0)
184        self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0)
185        self.assertTrue(len(result['volume_changes']) ==
186                        2 * len(self.delay_start_time))
187        self.assertTrue(result['equivalent_noise_level'] < 0.005)
188
189        self.assertTrue(len(result['artifacts']['delay_during_playback']) ==
190                        len(self.delay_start_time))
191        for i in range(len(result['artifacts']['delay_during_playback'])):
192            delta = abs(result['artifacts']['delay_during_playback'][i][0] -
193                        self.delay_start_time[i])
194            self.assertTrue(delta < 0.001)
195            duration = self.delay_end_time[i] - self.delay_start_time[i]
196            delta = abs(result['artifacts']['delay_during_playback'][i][1] -
197                        duration)
198            self.assertTrue(delta < 0.001)
199
200
201    def testArtifactsBeforePlayback(self):
202        """Sine wave with artifacts before playback."""
203        self.generate_artifacts_before_playback()
204        result = audio_quality_measurement.quality_measurement(self.y,
205                                                               self.rate)
206        self.assertTrue(len(result['artifacts']['noise_before_playback']) == 1)
207        delta = abs(result['artifacts']['noise_before_playback'][0][0] - 0.1)
208        self.assertTrue(delta < 0.01)
209        delta = abs(result['artifacts']['noise_before_playback'][0][1] - 0.005)
210        self.assertTrue(delta < 0.004)
211        self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0)
212        self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0)
213        self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0)
214        self.assertTrue(len(result['volume_changes']) == 0)
215        self.assertTrue(result['equivalent_noise_level'] < 0.005)
216
217
218    def testArtifactsAfterPlayback(self):
219        """Sine wave with artifacts after playback."""
220        self.generate_artifacts_after_playback()
221        result = audio_quality_measurement.quality_measurement(self.y,
222                                                               self.rate)
223        self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0)
224        self.assertTrue(len(result['artifacts']['noise_after_playback']) == 1)
225        delta = abs(result['artifacts']['noise_after_playback'][0][0] - 1.95)
226        self.assertTrue(delta < 0.01)
227        delta = abs(result['artifacts']['noise_after_playback'][0][1] - 0.02)
228        self.assertTrue(delta < 0.001)
229        self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0)
230        self.assertTrue(len(result['artifacts']['burst_during_playback'] ) == 0)
231        self.assertTrue(len(result['volume_changes']) == 0)
232        self.assertTrue(result['equivalent_noise_level'] < 0.005)
233
234
235    def testBurstDuringPlayback(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] -
248                        result['artifacts']['burst_during_playback'][i])
249            self.assertTrue(delta < 0.002)
250
251
252    def testVolumeChanging(self):
253        """Sine wave with volume changing during playback."""
254        self.generate_volume_changing()
255        result = audio_quality_measurement.quality_measurement(self.y,
256                                                               self.rate)
257        self.assertTrue(len(result['artifacts']['noise_before_playback']) == 0)
258        self.assertTrue(len(result['artifacts']['noise_after_playback']) == 0)
259        self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0)
260        self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0)
261        self.assertTrue(result['equivalent_noise_level'] < 0.005)
262        self.assertTrue(len(result['volume_changes']) ==
263                        len(self.volume_changing))
264        for i in range(len(self.volume_changing)):
265            self.assertTrue(abs(self.volume_changing_time[i] -
266                                result['volume_changes'][i][0]) < 0.01)
267            self.assertTrue(self.volume_changing[i] ==
268                            result['volume_changes'][i][1])
269
270if __name__ == '__main__':
271    unittest.main()
272