Jack2: JackAudioAdapterInterface.cpp Source File

Jack2 1.9.12

JackAudioAdapterInterface.cpp
1 /*
2 Copyright (C) 2008 Grame
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef __APPLE__
21 #include <TargetConditionals.h>
22 #endif
23
24 #include "JackAudioAdapter.h"
25 #ifndef MY_TARGET_OS_IPHONE
26 #include "JackLibSampleRateResampler.h"
27 #endif
28 #include "JackTime.h"
29 #include "JackError.h"
30 #include <stdio.h>
31
32 namespace Jack
33 {
34
35 #ifdef JACK_MONITOR
36
37 void MeasureTable::Write(int time1, int time2, float r1, float r2, int pos1, int pos2)
38 {
39 int pos = (++fCount) % TABLE_MAX;
40 fTable[pos].time1 = time1;
41 fTable[pos].time2 = time2;
42 fTable[pos].r1 = r1;
43 fTable[pos].r2 = r2;
44 fTable[pos].pos1 = pos1;
45 fTable[pos].pos2 = pos2;
46 }
47
48 void MeasureTable::Save(unsigned int fHostBufferSize, unsigned int fHostSampleRate, unsigned int fAdaptedSampleRate, unsigned int fAdaptedBufferSize)
49 {
50 FILE* file = fopen("JackAudioAdapter.log", "w");
51
52 int max = (fCount) % TABLE_MAX - 1;
53 for (int i = 1; i < max; i++) {
54 fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n",
55 fTable[i].delta, fTable[i].time1, fTable[i].time2,
56 fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
57 }
58 fclose(file);
59
60 // No used for now
61 // Adapter timing 1
62 file = fopen("AdapterTiming1.plot", "w");
63 fprintf(file, "set multiplot\n");
64 fprintf(file, "set grid\n");
65 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
66 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
67 fprintf(file, "set xlabel \"audio cycles\"\n");
68 fprintf(file, "set ylabel \"frames\"\n");
69 fprintf(file, "plot ");
70 fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,");
71 fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
72
73 fprintf(file, "\n unset multiplot\n");
74 fprintf(file, "set output 'AdapterTiming1.svg\n");
75 fprintf(file, "set terminal svg\n");
76
77 fprintf(file, "set multiplot\n");
78 fprintf(file, "set grid\n");
79 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
80 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
81 fprintf(file, "set xlabel \"audio cycles\"\n");
82 fprintf(file, "set ylabel \"frames\"\n");
83 fprintf(file, "plot ");
84 fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
85 fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines\n");
86 fprintf(file, "unset multiplot\n");
87 fprintf(file, "unset output\n");
88
89 fclose(file);
90
91 // Adapter timing 2
92 file = fopen("AdapterTiming2.plot", "w");
93 fprintf(file, "set multiplot\n");
94 fprintf(file, "set grid\n");
95 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
96 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
97 fprintf(file, "set xlabel \"audio cycles\"\n");
98 fprintf(file, "set ylabel \"resampling ratio\"\n");
99 fprintf(file, "plot ");
100 fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
101 fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
102
103 fprintf(file, "\n unset multiplot\n");
104 fprintf(file, "set output 'AdapterTiming2.svg\n");
105 fprintf(file, "set terminal svg\n");
106
107 fprintf(file, "set multiplot\n");
108 fprintf(file, "set grid\n");
109 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
110 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
111 fprintf(file, "set xlabel \"audio cycles\"\n");
112 fprintf(file, "set ylabel \"resampling ratio\"\n");
113 fprintf(file, "plot ");
114 fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
115 fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines\n");
116 fprintf(file, "unset multiplot\n");
117 fprintf(file, "unset output\n");
118
119 fclose(file);
120
121 // Adapter timing 3
122 file = fopen("AdapterTiming3.plot", "w");
123 fprintf(file, "set multiplot\n");
124 fprintf(file, "set grid\n");
125 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
126 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
127 fprintf(file, "set xlabel \"audio cycles\"\n");
128 fprintf(file, "set ylabel \"frames\"\n");
129 fprintf(file, "plot ");
130 fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
131 fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
132
133 fprintf(file, "\n unset multiplot\n");
134 fprintf(file, "set output 'AdapterTiming3.svg\n");
135 fprintf(file, "set terminal svg\n");
136
137 fprintf(file, "set multiplot\n");
138 fprintf(file, "set grid\n");
139 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
140 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
141 fprintf(file, "set xlabel \"audio cycles\"\n");
142 fprintf(file, "set ylabel \"frames\"\n");
143 fprintf(file, "plot ");
144 fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
145 fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines\n");
146 fprintf(file, "unset multiplot\n");
147 fprintf(file, "unset output\n");
148
149 fclose(file);
150 }
151
152 #endif
153
154 void JackAudioAdapterInterface::GrowRingBufferSize()
155 {
156 fRingbufferCurSize *= 2;
157 }
158
159 void JackAudioAdapterInterface::AdaptRingBufferSize()
160 {
161 if (fHostBufferSize > fAdaptedBufferSize) {
162 fRingbufferCurSize = 4 * fHostBufferSize;
163 } else {
164 fRingbufferCurSize = 4 * fAdaptedBufferSize;
165 }
166 }
167
168 void JackAudioAdapterInterface::ResetRingBuffers()
169 {
170 if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
171 fRingbufferCurSize = DEFAULT_RB_SIZE;
172 }
173
174 for (int i = 0; i < fCaptureChannels; i++) {
175 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
176 }
177 for (int i = 0; i < fPlaybackChannels; i++) {
178 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
179 }
180 }
181
182 void JackAudioAdapterInterface::Reset()
183 {
184 ResetRingBuffers();
185 fRunning = false;
186 }
187
188 #ifdef MY_TARGET_OS_IPHONE
189 void JackAudioAdapterInterface::Create()
190 {}
191 #else
192 void JackAudioAdapterInterface::Create()
193 {
194 //ringbuffers
195 fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
196 fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
197
198 if (fAdaptative) {
199 AdaptRingBufferSize();
200 jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
201 } else {
202 if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
203 fRingbufferCurSize = DEFAULT_RB_SIZE;
204 }
205 jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
206 }
207
208 for (int i = 0; i < fCaptureChannels; i++ ) {
209 fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
210 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
211 }
212 for (int i = 0; i < fPlaybackChannels; i++ ) {
213 fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
214 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
215 }
216
217 if (fCaptureChannels > 0) {
218 jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
219 }
220 if (fPlaybackChannels > 0) {
221 jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
222 }
223 }
224 #endif
225
226 void JackAudioAdapterInterface::Destroy()
227 {
228 for (int i = 0; i < fCaptureChannels; i++) {
229 delete(fCaptureRingBuffer[i]);
230 }
231 for (int i = 0; i < fPlaybackChannels; i++) {
232 delete (fPlaybackRingBuffer[i]);
233 }
234
235 delete[] fCaptureRingBuffer;
236 delete[] fPlaybackRingBuffer;
237 }
238
239 int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames)
240 {
241 bool failure = false;
242 fRunning = true;
243
244 // Finer estimation of the position in the ringbuffer
245 int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0;
246
247 double ratio = 1;
248
249 // TODO : done like this just to avoid crash when input only or output only...
250 if (fCaptureChannels > 0) {
251 ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
252 } else if (fPlaybackChannels > 0) {
253 ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames);
254 }
255
256 #ifdef JACK_MONITOR
257 if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL)
258 fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
259 #endif
260
261 // Push/pull from ringbuffer
262 for (int i = 0; i < fCaptureChannels; i++) {
263 fCaptureRingBuffer[i]->SetRatio(ratio);
264 if (inputBuffer[i]) {
265 if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames) {
266 failure = true;
267 }
268 }
269 }
270
271 for (int i = 0; i < fPlaybackChannels; i++) {
272 fPlaybackRingBuffer[i]->SetRatio(1/ratio);
273 if (outputBuffer[i]) {
274 if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) {
275 failure = true;
276 }
277 }
278 }
279 // Reset all ringbuffers in case of failure
280 if (failure) {
281 jack_error("JackAudioAdapterInterface::PushAndPull ringbuffer failure... reset");
282 if (fAdaptative) {
283 GrowRingBufferSize();
284 jack_info("Ringbuffer size = %d frames", fRingbufferCurSize);
285 }
286 ResetRingBuffers();
287 return -1;
288 } else {
289 return 0;
290 }
291 }
292
293 int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
294 {
295 fPullAndPushTime = GetMicroSeconds();
296 if (!fRunning) {
297 return 0;
298 }
299
300 int res = 0;
301
302 // Push/pull from ringbuffer
303 for (int i = 0; i < fCaptureChannels; i++) {
304 if (inputBuffer[i]) {
305 if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) {
306 res = -1;
307 }
308 }
309 }
310
311 for (int i = 0; i < fPlaybackChannels; i++) {
312 if (outputBuffer[i]) {
313 if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) {
314 res = -1;
315 }
316 }
317 }
318
319 return res;
320 }
321
322 int JackAudioAdapterInterface::SetHostBufferSize(jack_nframes_t buffer_size)
323 {
324 fHostBufferSize = buffer_size;
325 if (fAdaptative) {
326 AdaptRingBufferSize();
327 }
328 return 0;
329 }
330
331 int JackAudioAdapterInterface::SetAdaptedBufferSize(jack_nframes_t buffer_size)
332 {
333 fAdaptedBufferSize = buffer_size;
334 if (fAdaptative) {
335 AdaptRingBufferSize();
336 }
337 return 0;
338 }
339
340 int JackAudioAdapterInterface::SetBufferSize(jack_nframes_t buffer_size)
341 {
342 SetHostBufferSize(buffer_size);
343 SetAdaptedBufferSize(buffer_size);
344 return 0;
345 }
346
347 int JackAudioAdapterInterface::SetHostSampleRate(jack_nframes_t sample_rate)
348 {
349 fHostSampleRate = sample_rate;
350 fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
351 return 0;
352 }
353
354 int JackAudioAdapterInterface::SetAdaptedSampleRate(jack_nframes_t sample_rate)
355 {
356 fAdaptedSampleRate = sample_rate;
357 fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
358 return 0;
359 }
360
361 int JackAudioAdapterInterface::SetSampleRate(jack_nframes_t sample_rate)
362 {
363 SetHostSampleRate(sample_rate);
364 SetAdaptedSampleRate(sample_rate);
365 return 0;
366 }
367
368 void JackAudioAdapterInterface::SetInputs(int inputs)
369 {
370 jack_log("JackAudioAdapterInterface::SetInputs %d", inputs);
371 fCaptureChannels = inputs;
372 }
373
374 void JackAudioAdapterInterface::SetOutputs(int outputs)
375 {
376 jack_log("JackAudioAdapterInterface::SetOutputs %d", outputs);
377 fPlaybackChannels = outputs;
378 }
379
380 int JackAudioAdapterInterface::GetInputs()
381 {
382 //jack_log("JackAudioAdapterInterface::GetInputs %d", fCaptureChannels);
383 return fCaptureChannels;
384 }
385
386 int JackAudioAdapterInterface::GetOutputs()
387 {
388 //jack_log ("JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels);
389 return fPlaybackChannels;
390 }
391
392
393 } // namespace
jack_log
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108
jack_error
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
jack_info
SERVER_EXPORT void jack_info(const char *fmt,...)
Definition: JackError.cpp:100