cannam@124
|
1
|
cannam@124
|
2 /*
|
cannam@124
|
3 * PortAudio Portable Real-Time Audio Library
|
cannam@124
|
4 * Latest Version at: http://www.portaudio.com
|
cannam@124
|
5 *
|
cannam@124
|
6 * Copyright (c) 1999-2010 Phil Burk and Ross Bencina
|
cannam@124
|
7 *
|
cannam@124
|
8 * Permission is hereby granted, free of charge, to any person obtaining
|
cannam@124
|
9 * a copy of this software and associated documentation files
|
cannam@124
|
10 * (the "Software"), to deal in the Software without restriction,
|
cannam@124
|
11 * including without limitation the rights to use, copy, modify, merge,
|
cannam@124
|
12 * publish, distribute, sublicense, and/or sell copies of the Software,
|
cannam@124
|
13 * and to permit persons to whom the Software is furnished to do so,
|
cannam@124
|
14 * subject to the following conditions:
|
cannam@124
|
15 *
|
cannam@124
|
16 * The above copyright notice and this permission notice shall be
|
cannam@124
|
17 * included in all copies or substantial portions of the Software.
|
cannam@124
|
18 *
|
cannam@124
|
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
cannam@124
|
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
cannam@124
|
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
cannam@124
|
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
cannam@124
|
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
cannam@124
|
24 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
cannam@124
|
25 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
cannam@124
|
26 */
|
cannam@124
|
27
|
cannam@124
|
28 /*
|
cannam@124
|
29 * The text above constitutes the entire PortAudio license; however,
|
cannam@124
|
30 * the PortAudio community also makes the following non-binding requests:
|
cannam@124
|
31 *
|
cannam@124
|
32 * Any person wishing to distribute modifications to the Software is
|
cannam@124
|
33 * requested to send the modifications to the original developer so that
|
cannam@124
|
34 * they can be incorporated into the canonical version. It is also
|
cannam@124
|
35 * requested that these non-binding requests be included along with the
|
cannam@124
|
36 * license above.
|
cannam@124
|
37 */
|
cannam@124
|
38
|
cannam@124
|
39 #ifndef _AUDIO_ANALYZER_H
|
cannam@124
|
40 #define _AUDIO_ANALYZER_H
|
cannam@124
|
41
|
cannam@124
|
42 #include "biquad_filter.h"
|
cannam@124
|
43
|
cannam@124
|
44 #define MATH_PI (3.141592653589793238462643)
|
cannam@124
|
45 #define MATH_TWO_PI (2.0 * MATH_PI)
|
cannam@124
|
46
|
cannam@124
|
47 typedef struct PaQaSineGenerator_s
|
cannam@124
|
48 {
|
cannam@124
|
49 double phase;
|
cannam@124
|
50 double phaseIncrement;
|
cannam@124
|
51 double frequency;
|
cannam@124
|
52 double amplitude;
|
cannam@124
|
53 } PaQaSineGenerator;
|
cannam@124
|
54
|
cannam@124
|
55 /** Container for a monophonic audio sample in memory. */
|
cannam@124
|
56 typedef struct PaQaRecording_s
|
cannam@124
|
57 {
|
cannam@124
|
58 /** Maximum number of frames that can fit in the allocated buffer. */
|
cannam@124
|
59 int maxFrames;
|
cannam@124
|
60 float *buffer;
|
cannam@124
|
61 /** Actual number of valid frames in the buffer. */
|
cannam@124
|
62 int numFrames;
|
cannam@124
|
63 int sampleRate;
|
cannam@124
|
64 } PaQaRecording;
|
cannam@124
|
65
|
cannam@124
|
66 typedef struct PaQaTestTone_s
|
cannam@124
|
67 {
|
cannam@124
|
68 int samplesPerFrame;
|
cannam@124
|
69 int startDelay;
|
cannam@124
|
70 double sampleRate;
|
cannam@124
|
71 double frequency;
|
cannam@124
|
72 double amplitude;
|
cannam@124
|
73 } PaQaTestTone;
|
cannam@124
|
74
|
cannam@124
|
75 typedef struct PaQaAnalysisResult_s
|
cannam@124
|
76 {
|
cannam@124
|
77 int valid;
|
cannam@124
|
78 /** Latency in samples from output to input. */
|
cannam@124
|
79 double latency;
|
cannam@124
|
80 double amplitudeRatio;
|
cannam@124
|
81 double popAmplitude;
|
cannam@124
|
82 double popPosition;
|
cannam@124
|
83 double numDroppedFrames;
|
cannam@124
|
84 double droppedFramesPosition;
|
cannam@124
|
85 double numAddedFrames;
|
cannam@124
|
86 double addedFramesPosition;
|
cannam@124
|
87 } PaQaAnalysisResult;
|
cannam@124
|
88
|
cannam@124
|
89
|
cannam@124
|
90 /*================================================================*/
|
cannam@124
|
91 /*================= General DSP Tools ============================*/
|
cannam@124
|
92 /*================================================================*/
|
cannam@124
|
93 /**
|
cannam@124
|
94 * Calculate Nth frequency of a series for use in testing multiple channels.
|
cannam@124
|
95 * Series should avoid harmonic overlap between channels.
|
cannam@124
|
96 */
|
cannam@124
|
97 double PaQa_GetNthFrequency( double baseFrequency, int index );
|
cannam@124
|
98
|
cannam@124
|
99 void PaQa_EraseBuffer( float *buffer, int numFrames, int samplesPerFrame );
|
cannam@124
|
100
|
cannam@124
|
101 void PaQa_MixSine( PaQaSineGenerator *generator, float *buffer, int numSamples, int stride );
|
cannam@124
|
102
|
cannam@124
|
103 void PaQa_WriteSine( float *buffer, int numSamples, int stride,
|
cannam@124
|
104 double frequency, double amplitude );
|
cannam@124
|
105
|
cannam@124
|
106 /**
|
cannam@124
|
107 * Generate a signal with a sharp edge in the middle that can be recognized despite some phase shift.
|
cannam@124
|
108 */
|
cannam@124
|
109 void PaQa_GenerateCrack( float *buffer, int numSamples, int stride );
|
cannam@124
|
110
|
cannam@124
|
111 double PaQa_ComputePhaseDifference( double phase1, double phase2 );
|
cannam@124
|
112
|
cannam@124
|
113 /**
|
cannam@124
|
114 * Measure the area under the curve by summing absolute value of each value.
|
cannam@124
|
115 */
|
cannam@124
|
116 double PaQa_MeasureArea( float *buffer, int numFrames, int stride );
|
cannam@124
|
117
|
cannam@124
|
118 /**
|
cannam@124
|
119 * Measure slope of the positive zero crossings.
|
cannam@124
|
120 */
|
cannam@124
|
121 double PaQa_MeasureCrossingSlope( float *buffer, int numFrames );
|
cannam@124
|
122
|
cannam@124
|
123
|
cannam@124
|
124 /**
|
cannam@124
|
125 * Prepare an oscillator that can generate a sine tone for testing.
|
cannam@124
|
126 */
|
cannam@124
|
127 void PaQa_SetupSineGenerator( PaQaSineGenerator *generator, double frequency, double amplitude, double frameRate );
|
cannam@124
|
128
|
cannam@124
|
129 /*================================================================*/
|
cannam@124
|
130 /*================= Recordings ===================================*/
|
cannam@124
|
131 /*================================================================*/
|
cannam@124
|
132 /**
|
cannam@124
|
133 * Allocate memory for containg a mono audio signal. Set up recording for writing.
|
cannam@124
|
134 */
|
cannam@124
|
135 int PaQa_InitializeRecording( PaQaRecording *recording, int maxSamples, int sampleRate );
|
cannam@124
|
136
|
cannam@124
|
137 /**
|
cannam@124
|
138 * Free memory allocated by PaQa_InitializeRecording.
|
cannam@124
|
139 */
|
cannam@124
|
140 void PaQa_TerminateRecording( PaQaRecording *recording );
|
cannam@124
|
141
|
cannam@124
|
142 /**
|
cannam@124
|
143 * Apply a biquad filter to the audio from the input recording and write it to the output recording.
|
cannam@124
|
144 */
|
cannam@124
|
145 void PaQa_FilterRecording( PaQaRecording *input, PaQaRecording *output, BiquadFilter *filter );
|
cannam@124
|
146
|
cannam@124
|
147
|
cannam@124
|
148 int PaQa_SaveRecordingToWaveFile( PaQaRecording *recording, const char *filename );
|
cannam@124
|
149
|
cannam@124
|
150 /**
|
cannam@124
|
151 * @param stride is the spacing of samples to skip in the input buffer. To use every samples pass 1. To use every other sample pass 2.
|
cannam@124
|
152 */
|
cannam@124
|
153 int PaQa_WriteRecording( PaQaRecording *recording, float *buffer, int numSamples, int stride );
|
cannam@124
|
154
|
cannam@124
|
155 /** Write zeros into a recording. */
|
cannam@124
|
156 int PaQa_WriteSilence( PaQaRecording *recording, int numSamples );
|
cannam@124
|
157
|
cannam@124
|
158 int PaQa_RecordFreeze( PaQaRecording *recording, int numSamples );
|
cannam@124
|
159
|
cannam@124
|
160 double PaQa_CorrelateSine( PaQaRecording *recording, double frequency, double frameRate,
|
cannam@124
|
161 int startFrame, int numSamples, double *phasePtr );
|
cannam@124
|
162
|
cannam@124
|
163 double PaQa_FindFirstMatch( PaQaRecording *recording, float *buffer, int numSamples, double tolerance );
|
cannam@124
|
164
|
cannam@124
|
165 /**
|
cannam@124
|
166 * Estimate the original amplitude of a clipped sine wave by measuring
|
cannam@124
|
167 * its average slope at the zero crossings.
|
cannam@124
|
168 */
|
cannam@124
|
169 double PaQa_MeasureSineAmplitudeBySlope( PaQaRecording *recording,
|
cannam@124
|
170 double frequency, double frameRate,
|
cannam@124
|
171 int startFrame, int numFrames );
|
cannam@124
|
172
|
cannam@124
|
173 double PaQa_MeasureRootMeanSquare( float *buffer, int numFrames );
|
cannam@124
|
174
|
cannam@124
|
175 /**
|
cannam@124
|
176 * Compare the amplitudes of these two signals.
|
cannam@124
|
177 * Return ratio of recorded signal over buffer signal.
|
cannam@124
|
178 */
|
cannam@124
|
179 double PaQa_CompareAmplitudes( PaQaRecording *recording, int startAt, float *buffer, int numSamples );
|
cannam@124
|
180
|
cannam@124
|
181 /**
|
cannam@124
|
182 * Analyse a recording of a sine wave.
|
cannam@124
|
183 * Measure latency and look for dropped frames, etc.
|
cannam@124
|
184 */
|
cannam@124
|
185 int PaQa_AnalyseRecording( PaQaRecording *recording, PaQaTestTone *testTone, PaQaAnalysisResult *analysisResult );
|
cannam@124
|
186
|
cannam@124
|
187 #endif /* _AUDIO_ANALYZER_H */
|