00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef __APPLE__
00021 #include <TargetConditionals.h>
00022 #endif
00023
00024 #include "JackAudioAdapter.h"
00025 #ifndef MY_TARGET_OS_IPHONE
00026 #include "JackLibSampleRateResampler.h"
00027 #endif
00028 #include "JackTime.h"
00029 #include "JackError.h"
00030 #include <stdio.h>
00031
00032 namespace Jack
00033 {
00034
00035 #ifdef JACK_MONITOR
00036
00037 void MeasureTable::Write(int time1, int time2, float r1, float r2, int pos1, int pos2)
00038 {
00039 int pos = (++fCount) % TABLE_MAX;
00040 fTable[pos].time1 = time1;
00041 fTable[pos].time2 = time2;
00042 fTable[pos].r1 = r1;
00043 fTable[pos].r2 = r2;
00044 fTable[pos].pos1 = pos1;
00045 fTable[pos].pos2 = pos2;
00046 }
00047
00048 void MeasureTable::Save(unsigned int fHostBufferSize, unsigned int fHostSampleRate, unsigned int fAdaptedSampleRate, unsigned int fAdaptedBufferSize)
00049 {
00050 FILE* file = fopen("JackAudioAdapter.log", "w");
00051
00052 int max = (fCount) % TABLE_MAX - 1;
00053 for (int i = 1; i < max; i++) {
00054 fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n",
00055 fTable[i].delta, fTable[i].time1, fTable[i].time2,
00056 fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
00057 }
00058 fclose(file);
00059
00060
00061
00062 file = fopen("AdapterTiming1.plot", "w");
00063 fprintf(file, "set multiplot\n");
00064 fprintf(file, "set grid\n");
00065 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00066 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00067 fprintf(file, "set xlabel \"audio cycles\"\n");
00068 fprintf(file, "set ylabel \"frames\"\n");
00069 fprintf(file, "plot ");
00070 fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,");
00071 fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
00072
00073 fprintf(file, "\n unset multiplot\n");
00074 fprintf(file, "set output 'AdapterTiming1.svg\n");
00075 fprintf(file, "set terminal svg\n");
00076
00077 fprintf(file, "set multiplot\n");
00078 fprintf(file, "set grid\n");
00079 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00080 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00081 fprintf(file, "set xlabel \"audio cycles\"\n");
00082 fprintf(file, "set ylabel \"frames\"\n");
00083 fprintf(file, "plot ");
00084 fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
00085 fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines\n");
00086 fprintf(file, "unset multiplot\n");
00087 fprintf(file, "unset output\n");
00088
00089 fclose(file);
00090
00091
00092 file = fopen("AdapterTiming2.plot", "w");
00093 fprintf(file, "set multiplot\n");
00094 fprintf(file, "set grid\n");
00095 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00096 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00097 fprintf(file, "set xlabel \"audio cycles\"\n");
00098 fprintf(file, "set ylabel \"resampling ratio\"\n");
00099 fprintf(file, "plot ");
00100 fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
00101 fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
00102
00103 fprintf(file, "\n unset multiplot\n");
00104 fprintf(file, "set output 'AdapterTiming2.svg\n");
00105 fprintf(file, "set terminal svg\n");
00106
00107 fprintf(file, "set multiplot\n");
00108 fprintf(file, "set grid\n");
00109 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00110 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00111 fprintf(file, "set xlabel \"audio cycles\"\n");
00112 fprintf(file, "set ylabel \"resampling ratio\"\n");
00113 fprintf(file, "plot ");
00114 fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
00115 fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines\n");
00116 fprintf(file, "unset multiplot\n");
00117 fprintf(file, "unset output\n");
00118
00119 fclose(file);
00120
00121
00122 file = fopen("AdapterTiming3.plot", "w");
00123 fprintf(file, "set multiplot\n");
00124 fprintf(file, "set grid\n");
00125 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00126 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00127 fprintf(file, "set xlabel \"audio cycles\"\n");
00128 fprintf(file, "set ylabel \"frames\"\n");
00129 fprintf(file, "plot ");
00130 fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
00131 fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
00132
00133 fprintf(file, "\n unset multiplot\n");
00134 fprintf(file, "set output 'AdapterTiming3.svg\n");
00135 fprintf(file, "set terminal svg\n");
00136
00137 fprintf(file, "set multiplot\n");
00138 fprintf(file, "set grid\n");
00139 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00140 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00141 fprintf(file, "set xlabel \"audio cycles\"\n");
00142 fprintf(file, "set ylabel \"frames\"\n");
00143 fprintf(file, "plot ");
00144 fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
00145 fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines\n");
00146 fprintf(file, "unset multiplot\n");
00147 fprintf(file, "unset output\n");
00148
00149 fclose(file);
00150 }
00151
00152 #endif
00153
00154 void JackAudioAdapterInterface::GrowRingBufferSize()
00155 {
00156 fRingbufferCurSize *= 2;
00157 }
00158
00159 void JackAudioAdapterInterface::AdaptRingBufferSize()
00160 {
00161 if (fHostBufferSize > fAdaptedBufferSize) {
00162 fRingbufferCurSize = 4 * fHostBufferSize;
00163 } else {
00164 fRingbufferCurSize = 4 * fAdaptedBufferSize;
00165 }
00166 }
00167
00168 void JackAudioAdapterInterface::ResetRingBuffers()
00169 {
00170 if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
00171 fRingbufferCurSize = DEFAULT_RB_SIZE;
00172 }
00173
00174 for (int i = 0; i < fCaptureChannels; i++) {
00175 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
00176 }
00177 for (int i = 0; i < fPlaybackChannels; i++) {
00178 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
00179 }
00180 }
00181
00182 void JackAudioAdapterInterface::Reset()
00183 {
00184 ResetRingBuffers();
00185 fRunning = false;
00186 }
00187
00188 #ifdef MY_TARGET_OS_IPHONE
00189 void JackAudioAdapterInterface::Create()
00190 {}
00191 #else
00192 void JackAudioAdapterInterface::Create()
00193 {
00194
00195 fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
00196 fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
00197
00198 if (fAdaptative) {
00199 AdaptRingBufferSize();
00200 jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
00201 } else {
00202 if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
00203 fRingbufferCurSize = DEFAULT_RB_SIZE;
00204 }
00205 jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
00206 }
00207
00208 for (int i = 0; i < fCaptureChannels; i++ ) {
00209 fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
00210 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
00211 }
00212 for (int i = 0; i < fPlaybackChannels; i++ ) {
00213 fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
00214 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
00215 }
00216
00217 if (fCaptureChannels > 0) {
00218 jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
00219 }
00220 if (fPlaybackChannels > 0) {
00221 jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
00222 }
00223 }
00224 #endif
00225
00226 void JackAudioAdapterInterface::Destroy()
00227 {
00228 for (int i = 0; i < fCaptureChannels; i++) {
00229 delete(fCaptureRingBuffer[i]);
00230 }
00231 for (int i = 0; i < fPlaybackChannels; i++) {
00232 delete (fPlaybackRingBuffer[i]);
00233 }
00234
00235 delete[] fCaptureRingBuffer;
00236 delete[] fPlaybackRingBuffer;
00237 }
00238
00239 int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames)
00240 {
00241 bool failure = false;
00242 fRunning = true;
00243
00244
00245 int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0;
00246
00247 double ratio = 1;
00248
00249
00250 if (fCaptureChannels > 0) {
00251 ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
00252 } else if (fPlaybackChannels > 0) {
00253 ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames);
00254 }
00255
00256 #ifdef JACK_MONITOR
00257 if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL)
00258 fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
00259 #endif
00260
00261
00262 for (int i = 0; i < fCaptureChannels; i++) {
00263 fCaptureRingBuffer[i]->SetRatio(ratio);
00264 if (inputBuffer[i]) {
00265 if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames) {
00266 failure = true;
00267 }
00268 }
00269 }
00270
00271 for (int i = 0; i < fPlaybackChannels; i++) {
00272 fPlaybackRingBuffer[i]->SetRatio(1/ratio);
00273 if (outputBuffer[i]) {
00274 if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) {
00275 failure = true;
00276 }
00277 }
00278 }
00279
00280 if (failure) {
00281 jack_error("JackAudioAdapterInterface::PushAndPull ringbuffer failure... reset");
00282 if (fAdaptative) {
00283 GrowRingBufferSize();
00284 jack_info("Ringbuffer size = %d frames", fRingbufferCurSize);
00285 }
00286 ResetRingBuffers();
00287 return -1;
00288 } else {
00289 return 0;
00290 }
00291 }
00292
00293 int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
00294 {
00295 fPullAndPushTime = GetMicroSeconds();
00296 if (!fRunning) {
00297 return 0;
00298 }
00299
00300 int res = 0;
00301
00302
00303 for (int i = 0; i < fCaptureChannels; i++) {
00304 if (inputBuffer[i]) {
00305 if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) {
00306 res = -1;
00307 }
00308 }
00309 }
00310
00311 for (int i = 0; i < fPlaybackChannels; i++) {
00312 if (outputBuffer[i]) {
00313 if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) {
00314 res = -1;
00315 }
00316 }
00317 }
00318
00319 return res;
00320 }
00321
00322 int JackAudioAdapterInterface::SetHostBufferSize(jack_nframes_t buffer_size)
00323 {
00324 fHostBufferSize = buffer_size;
00325 if (fAdaptative) {
00326 AdaptRingBufferSize();
00327 }
00328 return 0;
00329 }
00330
00331 int JackAudioAdapterInterface::SetAdaptedBufferSize(jack_nframes_t buffer_size)
00332 {
00333 fAdaptedBufferSize = buffer_size;
00334 if (fAdaptative) {
00335 AdaptRingBufferSize();
00336 }
00337 return 0;
00338 }
00339
00340 int JackAudioAdapterInterface::SetBufferSize(jack_nframes_t buffer_size)
00341 {
00342 SetHostBufferSize(buffer_size);
00343 SetAdaptedBufferSize(buffer_size);
00344 return 0;
00345 }
00346
00347 int JackAudioAdapterInterface::SetHostSampleRate(jack_nframes_t sample_rate)
00348 {
00349 fHostSampleRate = sample_rate;
00350 fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
00351 return 0;
00352 }
00353
00354 int JackAudioAdapterInterface::SetAdaptedSampleRate(jack_nframes_t sample_rate)
00355 {
00356 fAdaptedSampleRate = sample_rate;
00357 fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
00358 return 0;
00359 }
00360
00361 int JackAudioAdapterInterface::SetSampleRate(jack_nframes_t sample_rate)
00362 {
00363 SetHostSampleRate(sample_rate);
00364 SetAdaptedSampleRate(sample_rate);
00365 return 0;
00366 }
00367
00368 void JackAudioAdapterInterface::SetInputs(int inputs)
00369 {
00370 jack_log("JackAudioAdapterInterface::SetInputs %d", inputs);
00371 fCaptureChannels = inputs;
00372 }
00373
00374 void JackAudioAdapterInterface::SetOutputs(int outputs)
00375 {
00376 jack_log("JackAudioAdapterInterface::SetOutputs %d", outputs);
00377 fPlaybackChannels = outputs;
00378 }
00379
00380 int JackAudioAdapterInterface::GetInputs()
00381 {
00382
00383 return fCaptureChannels;
00384 }
00385
00386 int JackAudioAdapterInterface::GetOutputs()
00387 {
00388
00389 return fPlaybackChannels;
00390 }
00391
00392
00393 }