Jack2  1.9.9
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  int res = 0;
300 
301  // Push/pull from ringbuffer
302  for (int i = 0; i < fCaptureChannels; i++) {
303  if (inputBuffer[i]) {
304  if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) {
305  res = -1;
306  }
307  }
308  }
309 
310  for (int i = 0; i < fPlaybackChannels; i++) {
311  if (outputBuffer[i]) {
312  if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) {
313  res = -1;
314  }
315  }
316  }
317 
318  return res;
319  }
320 
321  int JackAudioAdapterInterface::SetHostBufferSize(jack_nframes_t buffer_size)
322  {
323  fHostBufferSize = buffer_size;
324  if (fAdaptative) {
325  AdaptRingBufferSize();
326  }
327  return 0;
328  }
329 
330  int JackAudioAdapterInterface::SetAdaptedBufferSize(jack_nframes_t buffer_size)
331  {
332  fAdaptedBufferSize = buffer_size;
333  if (fAdaptative) {
334  AdaptRingBufferSize();
335  }
336  return 0;
337  }
338 
339  int JackAudioAdapterInterface::SetBufferSize(jack_nframes_t buffer_size)
340  {
341  SetHostBufferSize(buffer_size);
342  SetAdaptedBufferSize(buffer_size);
343  return 0;
344  }
345 
346  int JackAudioAdapterInterface::SetHostSampleRate(jack_nframes_t sample_rate)
347  {
348  fHostSampleRate = sample_rate;
349  fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
350  return 0;
351  }
352 
353  int JackAudioAdapterInterface::SetAdaptedSampleRate(jack_nframes_t sample_rate)
354  {
355  fAdaptedSampleRate = sample_rate;
356  fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
357  return 0;
358  }
359 
360  int JackAudioAdapterInterface::SetSampleRate(jack_nframes_t sample_rate)
361  {
362  SetHostSampleRate(sample_rate);
363  SetAdaptedSampleRate(sample_rate);
364  return 0;
365  }
366 
367  void JackAudioAdapterInterface::SetInputs(int inputs)
368  {
369  jack_log("JackAudioAdapterInterface::SetInputs %d", inputs);
370  fCaptureChannels = inputs;
371  }
372 
373  void JackAudioAdapterInterface::SetOutputs(int outputs)
374  {
375  jack_log("JackAudioAdapterInterface::SetOutputs %d", outputs);
376  fPlaybackChannels = outputs;
377  }
378 
379  int JackAudioAdapterInterface::GetInputs()
380  {
381  //jack_log("JackAudioAdapterInterface::GetInputs %d", fCaptureChannels);
382  return fCaptureChannels;
383  }
384 
385  int JackAudioAdapterInterface::GetOutputs()
386  {
387  //jack_log ("JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels);
388  return fPlaybackChannels;
389  }
390 
391 
392 } // namespace
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:91
SERVER_EXPORT void jack_info(const char *fmt,...)
Definition: JackError.cpp:99
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:107