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