1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 /* This assumes an input signal that has at least a few hundred 18 milliseconds of high-amplitude sinusoidal signal. The signal is 19 expected to be a relatively low-frequency sinusoid (200-400 Hz). 20 If the signal is linearly reproduced or clipped, There will be no 21 large step changes in value from one sample to the next. On the 22 other hand, if the signal contains numerical overflow 23 (wrap-around), very large excursions will be produced. 24 25 This program first searches for the high-amplitude recorded 26 segment, then examines just that part of the signal for "large 27 excursions", and returns the results of the search as four 28 integers: 29 30 n_wraps signal_size sine_start sine_end 31 32 where n_wraps is the number of anomolous value jumps found, 33 signal_size is the number of lin16 samples found in the file, 34 sine_start and sine_end are the limits of the region searched for 35 anomolous jumps. */ 36 37 #include <stdlib.h> 38 #include <math.h> 39 40 // MAX_ALLOWED_STEP is the largest sample-to-sample change that will 41 // be considered "normal" for 250 Hz signals sampled at 8kHz. This is 42 // calibrated by the largest sample-to-sample change that is naturally 43 // present in a 250 Hz sine wave with amplitude of 40000 (which is 44 // actually 7804). 45 #define MAX_ALLOWED_STEP 16000 46 47 // This is the RMS value that is expected to be exceded by a sinusoid 48 // with a peak amplitude of 32767 (actually 23169). 49 #define SIGNAL_ON_RMS 12000.0 50 51 static void findEndpoints(short* data, int n, int step, int* start, int* end) { 52 int size = step; 53 *start = *end = 0; 54 int last_frame = n - size; 55 for (int frame = 0; frame < last_frame; frame += step) { 56 double sum = 0.0; 57 for (int i=0; i < size; ++i) { 58 float val = data[i + frame]; 59 sum += (val * val); 60 } 61 float rms = sqrt(sum / size); 62 if (! *start) { 63 if (rms >= SIGNAL_ON_RMS) { 64 *start = frame + size; 65 } 66 continue; 67 } else { 68 if (rms < SIGNAL_ON_RMS) { 69 *end = frame - size; 70 return; 71 } 72 } 73 } 74 if ((*start > 0) && (! *end)) { 75 *end = n - size - 1; 76 } 77 } 78 79 static void checkExcursions(short* data, int start, int end, int* numJumps, 80 int* maxPeak, int* minPeak) { 81 *numJumps = 0; 82 int endm = end - 1; 83 if ((endm - start) < 3) { 84 *numJumps = -1; 85 return; 86 } 87 *maxPeak = *minPeak = data[start]; 88 for (int i = start; i < endm; ++i) { 89 int v1 = data[i]; 90 int v2 = data[i+1]; 91 if (v1 > *maxPeak) 92 *maxPeak = v1; 93 if (v1 < *minPeak) 94 *minPeak = v1; 95 int diff = v2 - v1; 96 if (diff < 0) 97 diff = -diff; 98 if (diff > MAX_ALLOWED_STEP) 99 (*numJumps) += 1; 100 } 101 return; 102 } 103 104 int overflowCheck(short* pcm, int numSamples, float sampleRate, 105 float* duration, int* numDeltas, int* onset, int* offset, 106 int* maxPeak, int* minPeak) { 107 float windSize = 0.020; 108 int minBuff = int(2.0 * sampleRate); // must have 2 sec of data at least. 109 110 if(pcm && (numSamples >= minBuff)) { 111 int step = int(0.5 + (windSize * sampleRate)); 112 *onset = 0; 113 *offset = 0; 114 115 findEndpoints(pcm, numSamples, step, onset, offset); 116 *numDeltas = -1; 117 checkExcursions(pcm, *onset, *offset, numDeltas, maxPeak, minPeak); 118 *duration = (*offset - *onset) / sampleRate; 119 return 1; // true/success 120 } 121 return 0; // failure 122 } 123