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