Use jack_client_open instead of old jack_client_new.
[jack2.git] / common / JackAudioAdapterInterface.cpp
blobdff17818dedad47b612ca69c99f7787bdb15456f
1 /*
2 Copyright (C) 2008 Grame
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.
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.
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.
20 #include "JackAudioAdapter.h"
21 #include "JackLibSampleRateResampler.h"
22 #include "JackTime.h"
23 #include <stdio.h>
25 namespace Jack
28 #ifdef JACK_MONITOR
30 void MeasureTable::Write(int time1, int time2, float r1, float r2, int pos1, int pos2)
32 int pos = (++fCount) % TABLE_MAX;
33 fTable[pos].time1 = time1;
34 fTable[pos].time2 = time2;
35 fTable[pos].r1 = r1;
36 fTable[pos].r2 = r2;
37 fTable[pos].pos1 = pos1;
38 fTable[pos].pos2 = pos2;
41 void MeasureTable::Save(unsigned int fHostBufferSize, unsigned int fHostSampleRate, unsigned int fAdaptedSampleRate, unsigned int fAdaptedBufferSize)
43 char buffer[1024];
44 FILE* file = fopen("JackAudioAdapter.log", "w");
46 int max = (fCount) % TABLE_MAX - 1;
47 for (int i = 1; i < max; i++)
49 fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n",
50 fTable[i].delta, fTable[i].time1, fTable[i].time2,
51 fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
53 fclose(file);
55 // No used for now
56 // Adapter timing 1
57 file = fopen("AdapterTiming1.plot", "w");
58 fprintf(file, "set multiplot\n");
59 fprintf(file, "set grid\n");
60 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
61 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
62 fprintf(file, "set xlabel \"audio cycles\"\n");
63 fprintf(file, "set ylabel \"frames\"\n");
64 fprintf(file, "plot ");
65 sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,");
66 fprintf(file, buffer);
67 sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
68 fprintf(file, buffer);
70 fprintf(file, "\n unset multiplot\n");
71 fprintf(file, "set output 'AdapterTiming1.pdf\n");
72 fprintf(file, "set terminal pdf\n");
74 fprintf(file, "set multiplot\n");
75 fprintf(file, "set grid\n");
76 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
77 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
78 fprintf(file, "set xlabel \"audio cycles\"\n");
79 fprintf(file, "set ylabel \"frames\"\n");
80 fprintf(file, "plot ");
81 sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
82 fprintf(file, buffer);
83 sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines");
84 fprintf(file, buffer);
86 fclose(file);
88 // Adapter timing 2
89 file = fopen("AdapterTiming2.plot", "w");
90 fprintf(file, "set multiplot\n");
91 fprintf(file, "set grid\n");
92 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
93 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
94 fprintf(file, "set xlabel \"audio cycles\"\n");
95 fprintf(file, "set ylabel \"resampling ratio\"\n");
96 fprintf(file, "plot ");
97 sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
98 fprintf(file, buffer);
99 sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
100 fprintf(file, buffer);
102 fprintf(file, "\n unset multiplot\n");
103 fprintf(file, "set output 'AdapterTiming2.pdf\n");
104 fprintf(file, "set terminal pdf\n");
106 fprintf(file, "set multiplot\n");
107 fprintf(file, "set grid\n");
108 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
109 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
110 fprintf(file, "set xlabel \"audio cycles\"\n");
111 fprintf(file, "set ylabel \"resampling ratio\"\n");
112 fprintf(file, "plot ");
113 sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
114 fprintf(file, buffer);
115 sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
116 fprintf(file, buffer);
118 fclose(file);
120 // Adapter timing 3
121 file = fopen("AdapterTiming3.plot", "w");
122 fprintf(file, "set multiplot\n");
123 fprintf(file, "set grid\n");
124 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
125 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
126 fprintf(file, "set xlabel \"audio cycles\"\n");
127 fprintf(file, "set ylabel \"frames\"\n");
128 fprintf(file, "plot ");
129 sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
130 fprintf(file, buffer);
131 sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
132 fprintf(file, buffer);
134 fprintf(file, "\n unset multiplot\n");
135 fprintf(file, "set output 'AdapterTiming3.pdf\n");
136 fprintf(file, "set terminal pdf\n");
138 fprintf(file, "set multiplot\n");
139 fprintf(file, "set grid\n");
140 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
141 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
142 fprintf(file, "set xlabel \"audio cycles\"\n");
143 fprintf(file, "set ylabel \"frames\"\n");
144 fprintf(file, "plot ");
145 sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
146 fprintf(file, buffer);
147 sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
148 fprintf(file, buffer);
150 fclose(file);
153 #endif
155 void JackAudioAdapterInterface::GrowRingBufferSize()
157 fRingbufferCurSize *= 2;
160 void JackAudioAdapterInterface::AdaptRingBufferSize()
162 if (fHostBufferSize > fAdaptedBufferSize)
163 fRingbufferCurSize = 4 * fHostBufferSize;
164 else
165 fRingbufferCurSize = 4 * fAdaptedBufferSize;
168 void JackAudioAdapterInterface::ResetRingBuffers()
170 if (fRingbufferCurSize > DEFAULT_RB_SIZE)
171 fRingbufferCurSize = DEFAULT_RB_SIZE;
173 for (int i = 0; i < fCaptureChannels; i++)
174 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
175 for (int i = 0; i < fPlaybackChannels; i++)
176 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
179 void JackAudioAdapterInterface::Reset()
181 ResetRingBuffers();
182 fRunning = false;
185 void JackAudioAdapterInterface::Create()
187 //ringbuffers
188 fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
189 fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
191 if (fAdaptative) {
192 AdaptRingBufferSize();
193 jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
194 } else {
195 if (fRingbufferCurSize > DEFAULT_RB_SIZE)
196 fRingbufferCurSize = DEFAULT_RB_SIZE;
197 jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
200 for (int i = 0; i < fCaptureChannels; i++ ) {
201 fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
202 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
204 for (int i = 0; i < fPlaybackChannels; i++ ) {
205 fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
206 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
209 if (fCaptureChannels > 0)
210 jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
211 if (fPlaybackChannels > 0)
212 jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
215 void JackAudioAdapterInterface::Destroy()
217 for (int i = 0; i < fCaptureChannels; i++ )
218 delete ( fCaptureRingBuffer[i] );
219 for (int i = 0; i < fPlaybackChannels; i++ )
220 delete ( fPlaybackRingBuffer[i] );
222 delete[] fCaptureRingBuffer;
223 delete[] fPlaybackRingBuffer;
226 int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames)
228 bool failure = false;
229 fRunning = true;
231 // Finer estimation of the position in the ringbuffer
232 int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0;
234 double ratio = 1;
236 // TODO : done like this just to avoid crash when input only or output only...
237 if (fCaptureChannels > 0)
238 ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
239 else if (fPlaybackChannels > 0)
240 ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames);
242 #ifdef JACK_MONITOR
243 if (fCaptureRingBuffer[0] != NULL)
244 fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
245 #endif
247 // Push/pull from ringbuffer
248 for (int i = 0; i < fCaptureChannels; i++) {
249 fCaptureRingBuffer[i]->SetRatio(ratio);
250 if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames)
251 failure = true;
254 for (int i = 0; i < fPlaybackChannels; i++) {
255 fPlaybackRingBuffer[i]->SetRatio(1/ratio);
256 if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames)
257 failure = true;
259 // Reset all ringbuffers in case of failure
260 if (failure) {
261 jack_error("JackAudioAdapterInterface::PushAndPull ringbuffer failure... reset");
262 if (fAdaptative) {
263 GrowRingBufferSize();
264 jack_info("Ringbuffer size = %d frames", fRingbufferCurSize);
266 ResetRingBuffers();
267 return -1;
268 } else {
269 return 0;
273 int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
275 fPullAndPushTime = GetMicroSeconds();
276 if (!fRunning)
277 return 0;
279 int res = 0;
281 // Push/pull from ringbuffer
282 for (int i = 0; i < fCaptureChannels; i++) {
283 if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames)
284 res = -1;
287 for (int i = 0; i < fPlaybackChannels; i++) {
288 if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames)
289 res = -1;
292 return res;
295 } // namespace