• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2016 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""This module provides utilities to detect some artifacts and measure the
6    quality of audio."""
7
8import logging
9import math
10import numpy
11
12from autotest_lib.client.cros.audio import audio_analysis
13
14# The input signal should be one sine wave with fixed frequency which
15# can have silence before and/or after sine wave.
16# For example:
17#   silence      sine wave      silence
18#  -----------|VVVVVVVVVVVVV|-----------
19#     (a)           (b)           (c)
20# This module detects these artifacts:
21#   1. Detect noise in (a) and (c).
22#   2. Detect delay in (b).
23#   3. Detect burst in (b).
24# Assume the transitions between (a)(b) and (b)(c) are smooth and
25# amplitude increases/decreases linearly.
26# This module will detect artifacts in the sine wave.
27# This module also estimates the equivalent noise level by teager operator.
28# This module also detects volume changes in the sine wave. However, volume
29# changes may be affected by delay or burst.
30# Some artifacts may cause each other.
31
32# In this module, amplitude and frequency are derived from Hilbert transform.
33# Both amplitude and frequency are a function of time.
34
35# To detect each artifact, each point will be compared with
36# average amplitude of its block. The block size will be 1.5 ms.
37# Using average amplitude can mitigate the error caused by
38# Hilbert transform and noise.
39# In some case, for more accuracy, the block size may be modified
40# to other values.
41DEFAULT_BLOCK_SIZE_SECS = 0.0015
42
43# If the difference between average frequency of this block and
44# dominant frequency of full signal is less than 0.5 times of
45# dominant frequency, this block is considered to be within the
46# sine wave. In most cases, if there is no sine wave(only noise),
47# average frequency will be much greater than 5 times of
48# dominant frequency.
49# Also, for delay during playback, the frequency will be about 0
50# in perfect situation or much greater than 5 times of dominant
51# frequency if it's noised.
52DEFAULT_FREQUENCY_ERROR = 0.5
53
54# If the amplitude of some sample is less than 0.6 times of the
55# average amplitude of its left/right block, it will be considered
56# as a delay during playing.
57DEFAULT_DELAY_AMPLITUDE_THRESHOLD = 0.6
58
59# If the average amplitude of the block before or after playing
60# is more than 0.5 times to the average amplitude of the wave,
61# it will be considered as a noise artifact.
62DEFAULT_NOISE_AMPLITUDE_THRESHOLD = 0.5
63
64# In the sine wave, if the amplitude is more than 1.4 times of
65# its left side and its right side, it will be considered as
66# a burst.
67DEFAULT_BURST_AMPLITUDE_THRESHOLD = 1.4
68
69# When detecting burst, if the amplitude is lower than 0.5 times
70# average amplitude, we ignore it.
71DEFAULT_BURST_TOO_SMALL = 0.5
72
73# For a signal which is the combination of sine wave with fixed frequency f and
74# amplitude 1 and standard noise with amplitude k, the average teager value is
75# nearly linear to the noise level k.
76# Given frequency f, we simulate a sine wave with default noise level and
77# calculate its average teager value. Then, we can estimate the equivalent
78# noise level of input signal by the average teager value of input signal.
79DEFAULT_STANDARD_NOISE = 0.005
80
81# For delay, burst, volume increasing/decreasing, if two delay(
82# burst, volume increasing/decreasing) happen within
83# DEFAULT_SAME_EVENT_SECS seconds, we consider they are the
84# same event.
85DEFAULT_SAME_EVENT_SECS = 0.001
86
87# When detecting increasing/decreasing volume of signal, if the amplitude
88# is lower than 0.1 times average amplitude, we ignore it.
89DEFAULT_VOLUME_CHANGE_TOO_SMALL = 0.1
90
91# If average amplitude of right block is less/more than average
92# amplitude of left block times DEFAULT_VOLUME_CHANGE_AMPLITUDE, it will be
93# considered as decreasing/increasing on volume.
94DEFAULT_VOLUME_CHANGE_AMPLITUDE = 0.1
95
96# If the increasing/decreasing volume event is too close to the start or the end
97# of sine wave, we consider its volume change as part of rising/falling phase in
98# the start/end.
99NEAR_START_OR_END_SECS = 0.01
100
101# After applying Hilbert transform, the resulting amplitude and frequency may be
102# extremely large in the start and/or the end part. Thus, we will append zeros
103# before and after the whole wave for 0.1 secs.
104APPEND_ZEROS_SECS = 0.1
105
106# If the noise event is too close to the start or the end of the data, we
107# consider its noise as part of artifacts caused by edge effect of Hilbert
108# transform.
109# For example, originally, the data duration is 10 seconds.
110# We append 0.1 seconds of zeros in the beginning and the end of the data, so
111# the data becomes 10.2 seocnds long.
112# Then, we apply Hilbert transform to 10.2 seconds of data.
113# Near 0.1 seconds and 10.1 seconds, there will be edge effect of Hilbert
114# transform. We do not want these be treated as noise.
115# If NEAR_DATA_START_OR_END_SECS is set to 0.01, then the noise happened
116# at [0, 0.11] and [10.09, 10.1] will be ignored.
117NEAR_DATA_START_OR_END_SECS = 0.01
118
119# If the noise event is too close to the start or the end of the sine wave in
120# the data, we consider its noise as part of artifacts caused by edge effect of
121# Hilbert transform.
122# A |-------------|vvvvvvvvvvvvvvvvvvvvvvv|-------------|
123# B |ooooooooo| d |                       | d |ooooooooo|
124#
125# A is full signal. It contains a sine wave and silence before and after sine
126# wave.
127# In B, |oooo| shows the parts that we are going to check for noise before/after
128# sine wave. | d | is determined by NEAR_SINE_START_OR_END_SECS.
129NEAR_SINE_START_OR_END_SECS = 0.01
130
131
132class SineWaveNotFound(Exception):
133    """Error when there's no sine wave found in the signal"""
134    pass
135
136
137def hilbert(x):
138    """Hilbert transform copied from scipy.
139
140    More information can be found here:
141    http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.hilbert.html
142
143    @param x: Real signal data to transform.
144
145    @returns: Analytic signal of x, we can further extract amplitude and
146              frequency from it.
147
148    """
149    x = numpy.asarray(x)
150    if numpy.iscomplexobj(x):
151        raise ValueError("x must be real.")
152    axis = -1
153    N = x.shape[axis]
154    if N <= 0:
155        raise ValueError("N must be positive.")
156
157    Xf = numpy.fft.fft(x, N, axis=axis)
158    h = numpy.zeros(N)
159    if N % 2 == 0:
160        h[0] = h[N // 2] = 1
161        h[1:N // 2] = 2
162    else:
163        h[0] = 1
164        h[1:(N + 1) // 2] = 2
165
166    if len(x.shape) > 1:
167        ind = [newaxis] * x.ndim
168        ind[axis] = slice(None)
169        h = h[ind]
170    x = numpy.fft.ifft(Xf * h, axis=axis)
171    return x
172
173
174def noised_sine_wave(frequency, rate, noise_level):
175    """Generates a sine wave of 2 second with specified noise level.
176
177    @param frequency: Frequency of sine wave.
178    @param rate: Sampling rate.
179    @param noise_level: Required noise level.
180
181    @returns: A sine wave with specified noise level.
182
183    """
184    wave = []
185    for index in xrange(0, rate * 2):
186        sample = 2.0 * math.pi * frequency * float(index) / float(rate)
187        sine_wave = math.sin(sample)
188        noise = noise_level * numpy.random.standard_normal()
189        wave.append(sine_wave + noise)
190    return wave
191
192
193def average_teager_value(wave, amplitude):
194    """Computes the normalized average teager value.
195
196    After averaging the teager value, we will normalize the value by
197    dividing square of amplitude.
198
199    @param wave: Wave to apply teager operator.
200    @param amplitude: Average amplitude of given wave.
201
202    @returns: Average teager value.
203
204    """
205    teager_value, length = 0, len(wave)
206    for i in range(1, length - 1):
207        ith_teager_value = abs(wave[i] * wave[i] - wave[i - 1] * wave[i + 1])
208        ith_teager_value *= max(1, abs(wave[i]))
209        teager_value += ith_teager_value
210    teager_value = (float(teager_value) / length) / (amplitude ** 2)
211    return teager_value
212
213
214def noise_level(amplitude, frequency, rate, teager_value_of_input):
215    """Computes the noise level compared with standard_noise.
216
217    For a signal which is the combination of sine wave with fixed frequency f
218    and amplitude 1 and standard noise with amplitude k, the average teager
219    value is nearly linear to the noise level k.
220    Thus, we can compute the average teager value of a sine wave with
221    standard_noise. Then, we can estimate the noise level of given input.
222
223    @param amplitude: Amplitude of input audio.
224    @param frequency: Dominant frequency of input audio.
225    @param rate: Sampling rate.
226    @param teager_value_of_input: Average teager value of input audio.
227
228    @returns: A float value denotes the audio is equivalent to have
229              how many times of noise compared with its amplitude.
230              For example, 0.02 denotes that the wave has a noise which
231              has standard distribution with standard deviation being
232              0.02 times the amplitude of the wave.
233
234    """
235    standard_noise = DEFAULT_STANDARD_NOISE
236
237    # Generates the standard sine wave with stdandard_noise level of noise.
238    standard_wave = noised_sine_wave(frequency, rate, standard_noise)
239
240    # Calculates the average teager value.
241    teager_value_of_std_wave = average_teager_value(standard_wave, amplitude)
242
243    return (teager_value_of_input / teager_value_of_std_wave) * standard_noise
244
245
246def error(f1, f2):
247    """Calculates the relative error between f1 and f2.
248
249    @param f1: Exact value.
250    @param f2: Test value.
251
252    @returns: Relative error between f1 and f2.
253
254    """
255    return abs(float(f1) - float(f2)) / float(f1)
256
257
258def hilbert_analysis(signal, rate, block_size):
259    """Finds amplitude and frequency of each time of signal by Hilbert transform.
260
261    @param signal: The wave to analyze.
262    @param rate: Sampling rate.
263    @param block_size: The size of block to transform.
264
265    @returns: A tuple of list: (amplitude, frequency) composed of
266              amplitude and frequency of each time.
267
268    """
269    # To apply Hilbert transform, the wave will be transformed
270    # segment by segment. For each segment, its size will be
271    # block_size and we will only take middle part of it.
272    # Thus, each segment looks like: |-----|=====|=====|-----|.
273    # "=...=" part will be taken while "-...-" part will be ignored.
274    #
275    # The whole size of taken part will be half of block_size
276    # which will be hilbert_block.
277    # The size of each ignored part will be half of hilbert_block
278    # which will be half_hilbert_block.
279    hilbert_block = block_size // 2
280    half_hilbert_block = hilbert_block // 2
281    # As mentioned above, for each block, we will only take middle
282    # part of it. Thus, the whole transformation will be completed as:
283    # |=====|=====|-----|           |-----|=====|=====|-----|
284    #       |-----|=====|=====|-----|           |-----|=====|=====|
285    #                   |-----|=====|=====|-----|
286    # Specially, beginning and ending part may not have ignored part.
287    length = len(signal)
288    result = []
289    for left_border in xrange(0, length, hilbert_block):
290        right_border = min(length, left_border + hilbert_block)
291        temp_left_border = max(0, left_border - half_hilbert_block)
292        temp_right_border = min(length, right_border + half_hilbert_block)
293        temp = hilbert(signal[temp_left_border:temp_right_border])
294        for index in xrange(left_border, right_border):
295            result.append(temp[index - temp_left_border])
296    result = numpy.asarray(result)
297    amplitude = numpy.abs(result)
298    phase = numpy.unwrap(numpy.angle(result))
299    frequency = numpy.diff(phase) / (2.0 * numpy.pi) * rate
300    #frequency.append(frequency[len(frequency)-1])
301    frequecny = numpy.append(frequency, frequency[len(frequency) - 1])
302    return (amplitude, frequency)
303
304
305def find_block_average_value(arr, side_block_size, block_size):
306    """For each index, finds average value of its block, left block, right block.
307
308    It will find average value for each index in the range.
309
310    For each index, the range of its block is
311        [max(0, index - block_size / 2), min(length - 1, index + block_size / 2)]
312    For each index, the range of its left block is
313        [max(0, index - size_block_size), index]
314    For each index, the range of its right block is
315        [index, min(length - 1, index + side_block_size)]
316
317    @param arr: The array to be computed.
318    @param side_block_size: the size of the left_block and right_block.
319    @param block_size: the size of the block.
320
321    @returns: A tuple of lists: (left_block_average_array,
322                                 right_block_average_array,
323                                 block_average_array)
324    """
325    length = len(arr)
326    left_border, right_border = 0, 1
327    left_block_sum = arr[0]
328    right_block_sum = arr[0]
329    left_average_array = numpy.zeros(length)
330    right_average_array = numpy.zeros(length)
331    block_average_array = numpy.zeros(length)
332    for index in xrange(0, length):
333        while left_border < index - side_block_size:
334            left_block_sum -= arr[left_border]
335            left_border += 1
336        while right_border < min(length, index + side_block_size):
337            right_block_sum += arr[right_border]
338            right_border += 1
339
340        left_average_value = float(left_block_sum) / (index - left_border + 1)
341        right_average_value = float(right_block_sum) / (right_border - index)
342        left_average_array[index] = left_average_value
343        right_average_array[index] = right_average_value
344
345        if index + 1 < length:
346            left_block_sum += arr[index + 1]
347        right_block_sum -= arr[index]
348    left_border, right_border = 0, 1
349    block_sum = 0
350    for index in xrange(0, length):
351        while left_border < index - block_size / 2:
352            block_sum -= arr[left_border]
353            left_border += 1
354        while right_border < min(length, index + block_size / 2):
355            block_sum += arr[right_border]
356            right_border += 1
357
358        average_value = float(block_sum) / (right_border - left_border)
359        block_average_array[index] = average_value
360    return (left_average_array, right_average_array, block_average_array)
361
362
363def find_start_end_index(dominant_frequency,
364                         block_frequency_delta,
365                         block_size,
366                         frequency_error_threshold):
367    """Finds start and end index of sine wave.
368
369    For each block with size of block_size, we check that whether its frequency
370    is close enough to the dominant_frequency. If yes, we will consider this
371    block to be within the sine wave.
372    Then, it will return the start and end index of sine wave indicating that
373    sine wave is between [start_index, end_index)
374    It's okay if the whole signal only contains sine wave.
375
376    @param dominant_frequency: Dominant frequency of signal.
377    @param block_frequency_delta: Average absolute difference between dominant
378                                  frequency and frequency of each block. For
379                                  each index, its block is
380                                  [max(0, index - block_size / 2),
381                                   min(length - 1, index + block_size / 2)]
382    @param block_size: Block size in samples.
383
384    @returns: A tuple composed of (start_index, end_index)
385
386    """
387    length = len(block_frequency_delta)
388
389    # Finds the start/end time index of playing based on dominant frequency
390    start_index, end_index = length - 1 , 0
391    for index in xrange(0, length):
392        left_border = max(0, index - block_size / 2)
393        right_border = min(length - 1, index + block_size / 2)
394        frequency_error = block_frequency_delta[index] / dominant_frequency
395        if frequency_error < frequency_error_threshold:
396            start_index = min(start_index, left_border)
397            end_index = max(end_index, right_border + 1)
398    return (start_index, end_index)
399
400
401def noise_detection(start_index, end_index,
402                    block_amplitude, average_amplitude,
403                    rate, noise_amplitude_threshold):
404    """Detects noise before/after sine wave.
405
406    If average amplitude of some sample's block before start of wave or after
407    end of wave is more than average_amplitude times noise_amplitude_threshold,
408    it will be considered as a noise.
409
410    @param start_index: Start index of sine wave.
411    @param end_index: End index of sine wave.
412    @param block_amplitude: An array for average amplitude of each block, where
413                            amplitude is computed from Hilbert transform.
414    @param average_amplitude: Average amplitude of sine wave.
415    @param rate: Sampling rate
416    @param noise_amplitude_threshold: If the average amplitude of a block is
417                        higher than average amplitude of the wave times
418                        noise_amplitude_threshold, it will be considered as
419                        noise before/after playback.
420
421    @returns: A tuple of lists indicating the time that noise happens:
422            (noise_before_playing, noise_after_playing).
423
424    """
425    length = len(block_amplitude)
426    amplitude_threshold = average_amplitude * noise_amplitude_threshold
427    same_event_samples = rate * DEFAULT_SAME_EVENT_SECS
428
429    # Detects noise before playing.
430    noise_time_point = []
431    last_noise_end_time_point = []
432    previous_noise_index = None
433    times = 0
434    for index in xrange(0, length):
435        # Ignore noise too close to the beginning or the end of sine wave.
436        # Check the docstring of NEAR_SINE_START_OR_END_SECS.
437        if ((start_index - rate * NEAR_SINE_START_OR_END_SECS) <= index and
438            (index < end_index + rate * NEAR_SINE_START_OR_END_SECS)):
439            continue
440
441        # Ignore noise too close to the beginning or the end of original data.
442        # Check the docstring of NEAR_DATA_START_OR_END_SECS.
443        if (float(index) / rate <=
444            NEAR_DATA_START_OR_END_SECS + APPEND_ZEROS_SECS):
445            continue
446        if (float(length - index) / rate <=
447            NEAR_DATA_START_OR_END_SECS + APPEND_ZEROS_SECS):
448            continue
449        if block_amplitude[index] > amplitude_threshold:
450            same_event = False
451            if previous_noise_index:
452                same_event = (index - previous_noise_index) < same_event_samples
453            if not same_event:
454                index_start_sec = float(index) / rate - APPEND_ZEROS_SECS
455                index_end_sec = float(index + 1) / rate - APPEND_ZEROS_SECS
456                noise_time_point.append(index_start_sec)
457                last_noise_end_time_point.append(index_end_sec)
458                times += 1
459            index_end_sec = float(index + 1) / rate - APPEND_ZEROS_SECS
460            last_noise_end_time_point[times - 1] = index_end_sec
461            previous_noise_index = index
462
463    noise_before_playing, noise_after_playing = [], []
464    for i in xrange(times):
465        duration = last_noise_end_time_point[i] - noise_time_point[i]
466        if noise_time_point[i] < float(start_index) / rate - APPEND_ZEROS_SECS:
467            noise_before_playing.append((noise_time_point[i], duration))
468        else:
469            noise_after_playing.append((noise_time_point[i], duration))
470
471    return (noise_before_playing, noise_after_playing)
472
473
474def delay_detection(start_index, end_index,
475                    block_amplitude, average_amplitude,
476                    dominant_frequency,
477                    rate,
478                    left_block_amplitude,
479                    right_block_amplitude,
480                    block_frequency_delta,
481                    delay_amplitude_threshold,
482                    frequency_error_threshold):
483    """Detects delay during playing.
484
485    For each sample, we will check whether the average amplitude of its block
486    is less than average amplitude of its left block and its right block times
487    delay_amplitude_threshold. Also, we will check whether the frequency of
488    its block is far from the dominant frequency.
489    If at least one constraint fulfilled, it will be considered as a delay.
490
491    @param start_index: Start index of sine wave.
492    @param end_index: End index of sine wave.
493    @param block_amplitude: An array for average amplitude of each block, where
494                            amplitude is computed from Hilbert transform.
495    @param average_amplitude: Average amplitude of sine wave.
496    @param dominant_frequency: Dominant frequency of signal.
497    @param rate: Sampling rate
498    @param left_block_amplitude: Average amplitude of left block of each index.
499                                Ref to find_block_average_value function.
500    @param right_block_amplitude: Average amplitude of right block of each index.
501                                Ref to find_block_average_value function.
502    @param block_frequency_delta: Average absolute difference frequency to
503                                dominant frequency of block of each index.
504                                Ref to find_block_average_value function.
505    @param delay_amplitude_threshold: If the average amplitude of a block is
506                        lower than average amplitude of the wave times
507                        delay_amplitude_threshold, it will be considered
508                        as delay.
509    @param frequency_error_threshold: Ref to DEFAULT_FREQUENCY_ERROR
510
511    @returns: List of delay occurrence:
512                [(time_1, duration_1), (time_2, duration_2), ...],
513              where time and duration are in seconds.
514
515    """
516    delay_time_points = []
517    last_delay_end_time_points = []
518    previous_delay_index = None
519    times = 0
520    same_event_samples = rate * DEFAULT_SAME_EVENT_SECS
521    start_time = float(start_index) / rate - APPEND_ZEROS_SECS
522    end_time = float(end_index) / rate - APPEND_ZEROS_SECS
523    for index in xrange(start_index, end_index):
524        if block_amplitude[index] > average_amplitude * delay_amplitude_threshold:
525            continue
526        now_time = float(index) / rate - APPEND_ZEROS_SECS
527        if abs(now_time - start_time) < NEAR_START_OR_END_SECS:
528            continue
529        if abs(now_time - end_time) < NEAR_START_OR_END_SECS:
530            continue
531        # If amplitude less than its left/right side and small enough,
532        # it will be considered as a delay.
533        amp_threshold = average_amplitude * delay_amplitude_threshold
534        left_threshold = delay_amplitude_threshold * left_block_amplitude[index]
535        amp_threshold = min(amp_threshold, left_threshold)
536        right_threshold = delay_amplitude_threshold * right_block_amplitude[index]
537        amp_threshold = min(amp_threshold, right_threshold)
538
539        frequency_error = block_frequency_delta[index] / dominant_frequency
540
541        amplitude_too_small = block_amplitude[index] < amp_threshold
542        frequency_not_match = frequency_error > frequency_error_threshold
543
544        if amplitude_too_small or frequency_not_match:
545            same_event = False
546            if previous_delay_index:
547                same_event = (index - previous_delay_index) < same_event_samples
548            if not same_event:
549                index_start_sec = float(index) / rate - APPEND_ZEROS_SECS
550                index_end_sec = float(index + 1) / rate - APPEND_ZEROS_SECS
551                delay_time_points.append(index_start_sec)
552                last_delay_end_time_points.append(index_end_sec)
553                times += 1
554            previous_delay_index = index
555            index_end_sec = float(index + 1) / rate - APPEND_ZEROS_SECS
556            last_delay_end_time_points[times - 1] = index_end_sec
557
558    delay_list = []
559    for i in xrange(len(delay_time_points)):
560        duration = last_delay_end_time_points[i] - delay_time_points[i]
561        delay_list.append( (delay_time_points[i], duration) )
562    return delay_list
563
564
565def burst_detection(start_index, end_index,
566                    block_amplitude, average_amplitude,
567                    dominant_frequency,
568                    rate,
569                    left_block_amplitude,
570                    right_block_amplitude,
571                    block_frequency_delta,
572                    burst_amplitude_threshold,
573                    frequency_error_threshold):
574    """Detects burst during playing.
575
576    For each sample, we will check whether the average amplitude of its block is
577    more than average amplitude of its left block and its right block times
578    burst_amplitude_threshold. Also, we will check whether the frequency of
579    its block is not compatible to the dominant frequency.
580    If at least one constraint fulfilled, it will be considered as a burst.
581
582    @param start_index: Start index of sine wave.
583    @param end_index: End index of sine wave.
584    @param block_amplitude: An array for average amplitude of each block, where
585                            amplitude is computed from Hilbert transform.
586    @param average_amplitude: Average amplitude of sine wave.
587    @param dominant_frequency: Dominant frequency of signal.
588    @param rate: Sampling rate
589    @param left_block_amplitude: Average amplitude of left block of each index.
590                                Ref to find_block_average_value function.
591    @param right_block_amplitude: Average amplitude of right block of each index.
592                                Ref to find_block_average_value function.
593    @param block_frequency_delta: Average absolute difference frequency to
594                                dominant frequency of block of each index.
595    @param burst_amplitude_threshold: If the amplitude is higher than average
596                            amplitude of its left block and its right block
597                            times burst_amplitude_threshold. It will be
598                            considered as a burst.
599    @param frequency_error_threshold: Ref to DEFAULT_FREQUENCY_ERROR
600
601    @returns: List of burst occurence: [time_1, time_2, ...],
602              where time is in seconds.
603
604    """
605    burst_time_points = []
606    previous_burst_index = None
607    same_event_samples = rate * DEFAULT_SAME_EVENT_SECS
608    for index in xrange(start_index, end_index):
609        # If amplitude higher than its left/right side and large enough,
610        # it will be considered as a burst.
611        if block_amplitude[index] <= average_amplitude * DEFAULT_BURST_TOO_SMALL:
612            continue
613        if abs(index - start_index) < rate * NEAR_START_OR_END_SECS:
614            continue
615        if abs(index - end_index) < rate * NEAR_START_OR_END_SECS:
616            continue
617        amp_threshold = average_amplitude * DEFAULT_BURST_TOO_SMALL
618        left_threshold = burst_amplitude_threshold * left_block_amplitude[index]
619        amp_threshold = max(amp_threshold, left_threshold)
620        right_threshold = burst_amplitude_threshold * right_block_amplitude[index]
621        amp_threshold = max(amp_threshold, right_threshold)
622
623        frequency_error = block_frequency_delta[index] / dominant_frequency
624
625        amplitude_too_large = block_amplitude[index] > amp_threshold
626        frequency_not_match = frequency_error > frequency_error_threshold
627
628        if amplitude_too_large or frequency_not_match:
629            same_event = False
630            if previous_burst_index:
631                same_event = index - previous_burst_index < same_event_samples
632            if not same_event:
633                burst_time_points.append(float(index) / rate - APPEND_ZEROS_SECS)
634            previous_burst_index = index
635
636    return burst_time_points
637
638
639def changing_volume_detection(start_index, end_index,
640                              average_amplitude,
641                              rate,
642                              left_block_amplitude,
643                              right_block_amplitude,
644                              volume_changing_amplitude_threshold):
645    """Finds volume changing during playback.
646
647    For each index, we will compare average amplitude of its left block and its
648    right block. If average amplitude of right block is more than average
649    amplitude of left block times (1 + DEFAULT_VOLUME_CHANGE_AMPLITUDE), it will
650    be considered as an increasing volume. If the one of right block is less
651    than that of left block times (1 - DEFAULT_VOLUME_CHANGE_AMPLITUDE), it will
652    be considered as a decreasing volume.
653
654    @param start_index: Start index of sine wave.
655    @param end_index: End index of sine wave.
656    @param average_amplitude: Average amplitude of sine wave.
657    @param rate: Sampling rate
658    @param left_block_amplitude: Average amplitude of left block of each index.
659                                Ref to find_block_average_value function.
660    @param right_block_amplitude: Average amplitude of right block of each index.
661                                Ref to find_block_average_value function.
662    @param volume_changing_amplitude_threshold: If the average amplitude of right
663                                                block is higher or lower than
664                                                that of left one times this
665                                                value, it will be considered as
666                                                a volume change.
667                                                Also refer to
668                                                DEFAULT_VOLUME_CHANGE_AMPLITUDE
669
670    @returns: List of volume changing composed of 1 for increasing and
671              -1 for decreasing.
672
673    """
674    length = len(left_block_amplitude)
675
676    # Detects rising and/or falling volume.
677    previous_rising_index, previous_falling_index = None, None
678    changing_time = []
679    changing_events = []
680    amplitude_threshold = average_amplitude * DEFAULT_VOLUME_CHANGE_TOO_SMALL
681    same_event_samples = rate * DEFAULT_SAME_EVENT_SECS
682    for index in xrange(start_index, end_index):
683        # Skips if amplitude is too small.
684        if left_block_amplitude[index] < amplitude_threshold:
685            continue
686        if right_block_amplitude[index] < amplitude_threshold:
687            continue
688        # Skips if changing is from start or end time
689        if float(abs(start_index - index)) / rate < NEAR_START_OR_END_SECS:
690            continue
691        if float(abs(end_index   - index)) / rate < NEAR_START_OR_END_SECS:
692            continue
693
694        delta_margin = volume_changing_amplitude_threshold
695        if left_block_amplitude[index] > 0:
696            delta_margin *= left_block_amplitude[index]
697
698        increasing_threshold = left_block_amplitude[index] + delta_margin
699        decreasing_threshold = left_block_amplitude[index] - delta_margin
700
701        if right_block_amplitude[index] > increasing_threshold:
702            same_event = False
703            if previous_rising_index:
704                same_event = index - previous_rising_index < same_event_samples
705            if not same_event:
706                changing_time.append(float(index) / rate - APPEND_ZEROS_SECS)
707                changing_events.append(+1)
708            previous_rising_index = index
709        if right_block_amplitude[index] < decreasing_threshold:
710            same_event = False
711            if previous_falling_index:
712                same_event = index - previous_falling_index < same_event_samples
713            if not same_event:
714                changing_time.append(float(index) / rate - APPEND_ZEROS_SECS)
715                changing_events.append(-1)
716            previous_falling_index = index
717
718    # Combines consecutive increasing/decreasing event.
719    combined_changing_events, prev = [], 0
720    for i in xrange(len(changing_events)):
721        if changing_events[i] == prev:
722            continue
723        combined_changing_events.append((changing_time[i], changing_events[i]))
724        prev = changing_events[i]
725    return combined_changing_events
726
727
728def quality_measurement(
729        signal, rate,
730        dominant_frequency=None,
731        block_size_secs=DEFAULT_BLOCK_SIZE_SECS,
732        frequency_error_threshold=DEFAULT_FREQUENCY_ERROR,
733        delay_amplitude_threshold=DEFAULT_DELAY_AMPLITUDE_THRESHOLD,
734        noise_amplitude_threshold=DEFAULT_NOISE_AMPLITUDE_THRESHOLD,
735        burst_amplitude_threshold=DEFAULT_BURST_AMPLITUDE_THRESHOLD,
736        volume_changing_amplitude_threshold=DEFAULT_VOLUME_CHANGE_AMPLITUDE):
737    """Detects several artifacts and estimates the noise level.
738
739    This method detects artifact before playing, after playing, and delay
740    during playing. Also, it estimates the noise level of the signal.
741    To avoid the influence of noise, it calculates amplitude and frequency
742    block by block.
743
744    @param signal: A list of numbers for one-channel PCM data. The data should
745                   be normalized to [-1,1].
746    @param rate: Sampling rate
747    @param dominant_frequency: Dominant frequency of signal. Set None to
748                               recalculate the frequency in this function.
749    @param block_size_secs: Block size in seconds. The measurement will be done
750                            block-by-block using average amplitude and frequency
751                            in each block to avoid noise.
752    @param frequency_error_threshold: Ref to DEFAULT_FREQUENCY_ERROR.
753    @param delay_amplitude_threshold: If the average amplitude of a block is
754                                      lower than average amplitude of the wave
755                                      times delay_amplitude_threshold, it will
756                                      be considered as delay.
757                                      Also refer to delay_detection and
758                                      DEFAULT_DELAY_AMPLITUDE_THRESHOLD.
759    @param noise_amplitude_threshold: If the average amplitude of a block is
760                                      higher than average amplitude of the wave
761                                      times noise_amplitude_threshold, it will
762                                      be considered as noise before/after
763                                      playback.
764                                      Also refer to noise_detection and
765                                      DEFAULT_NOISE_AMPLITUDE_THRESHOLD.
766    @param burst_amplitude_threshold: If the average amplitude of a block is
767                                      higher than average amplitude of its left
768                                      block and its right block times
769                                      burst_amplitude_threshold. It will be
770                                      considered as a burst.
771                                      Also refer to burst_detection and
772                                      DEFAULT_BURST_AMPLITUDE_THRESHOLD.
773    @param volume_changing_amplitude_threshold: If the average amplitude of right
774                                                block is higher or lower than
775                                                that of left one times this
776                                                value, it will be considered as
777                                                a volume change.
778                                                Also refer to
779                                                changing_volume_detection and
780                                                DEFAULT_VOLUME_CHANGE_AMPLITUDE
781
782    @returns: A dictoinary of detection/estimation:
783              {'artifacts':
784                {'noise_before_playback':
785                    [(time_1, duration_1), (time_2, duration_2), ...],
786                 'noise_after_playback':
787                    [(time_1, duration_1), (time_2, duration_2), ...],
788                 'delay_during_playback':
789                    [(time_1, duration_1), (time_2, duration_2), ...],
790                 'burst_during_playback':
791                    [time_1, time_2, ...]
792                },
793               'volume_changes':
794                 [(time_1, flag_1), (time_2, flag_2), ...],
795               'equivalent_noise_level': level
796              }
797              where durations and time points are in seconds. And,
798              equivalence_noise_level is the quotient of noise and
799              wave which refers to DEFAULT_STANDARD_NOISE.
800              volume_changes is a list of tuples containing time
801              stamps and decreasing/increasing flags for volume
802              change events.
803
804    """
805    # Calculates the block size, from seconds to samples.
806    block_size = int(block_size_secs * rate)
807
808    signal = numpy.concatenate((numpy.zeros(int(rate * APPEND_ZEROS_SECS)),
809                                signal,
810                                numpy.zeros(int(rate * APPEND_ZEROS_SECS))))
811    signal = numpy.array(signal, dtype=float)
812    length = len(signal)
813
814    # Calculates the amplitude and frequency.
815    amplitude, frequency = hilbert_analysis(signal, rate, block_size)
816
817    # Finds the dominant frequency.
818    if not dominant_frequency:
819        dominant_frequency = audio_analysis.spectral_analysis(signal, rate)[0][0]
820
821    # Finds the array which contains absolute difference between dominant
822    # frequency and frequency at each time point.
823    frequency_delta = abs(frequency - dominant_frequency)
824
825    # Computes average amplitude of each type of block
826    res = find_block_average_value(amplitude, block_size * 2, block_size)
827    left_block_amplitude, right_block_amplitude, block_amplitude = res
828
829    # Computes average absolute difference of frequency and dominant frequency
830    # of the block of each index
831    _, _, block_frequency_delta = find_block_average_value(frequency_delta,
832                                                           block_size * 2,
833                                                           block_size)
834
835    # Finds start and end index of sine wave.
836    start_index, end_index = find_start_end_index(dominant_frequency,
837                                                  block_frequency_delta,
838                                                  block_size,
839                                                  frequency_error_threshold)
840
841    if start_index > end_index:
842        raise SineWaveNotFound('No sine wave found in signal')
843
844    logging.debug('Found sine wave: start: %s, end: %s',
845                  float(start_index) / rate - APPEND_ZEROS_SECS,
846                  float(end_index) / rate - APPEND_ZEROS_SECS)
847
848    sum_of_amplitude = float(sum(amplitude[start_index:end_index]))
849    # Finds average amplitude of sine wave.
850    average_amplitude = sum_of_amplitude / (end_index - start_index)
851
852    # Finds noise before and/or after playback.
853    noise_before_playing, noise_after_playing = noise_detection(
854            start_index, end_index,
855            block_amplitude, average_amplitude,
856            rate,
857            noise_amplitude_threshold)
858
859    # Finds delay during playback.
860    delays = delay_detection(start_index, end_index,
861                             block_amplitude, average_amplitude,
862                             dominant_frequency,
863                             rate,
864                             left_block_amplitude,
865                             right_block_amplitude,
866                             block_frequency_delta,
867                             delay_amplitude_threshold,
868                             frequency_error_threshold)
869
870    # Finds burst during playback.
871    burst_time_points = burst_detection(start_index, end_index,
872                                        block_amplitude, average_amplitude,
873                                        dominant_frequency,
874                                        rate,
875                                        left_block_amplitude,
876                                        right_block_amplitude,
877                                        block_frequency_delta,
878                                        burst_amplitude_threshold,
879                                        frequency_error_threshold)
880
881    # Finds volume changing during playback.
882    volume_changes = changing_volume_detection(
883            start_index, end_index,
884            average_amplitude,
885            rate,
886            left_block_amplitude,
887            right_block_amplitude,
888            volume_changing_amplitude_threshold)
889
890    # Calculates the average teager value.
891    teager_value = average_teager_value(signal[start_index:end_index],
892                                        average_amplitude)
893
894    # Finds out the noise level.
895    noise = noise_level(average_amplitude, dominant_frequency,
896                        rate,
897                        teager_value)
898
899    return {'artifacts':
900            {'noise_before_playback': noise_before_playing,
901             'noise_after_playback': noise_after_playing,
902             'delay_during_playback': delays,
903             'burst_during_playback': burst_time_points
904            },
905            'volume_changes': volume_changes,
906            'equivalent_noise_level': noise
907           }
908