• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
findEndpoints(short * data,int n,int step,int * start,int * end)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 
checkExcursions(short * data,int start,int end,int * numJumps,int * maxPeak,int * minPeak)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 
overflowCheck(short * pcm,int numSamples,float sampleRate,float * duration,int * numDeltas,int * onset,int * offset,int * maxPeak,int * minPeak)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