Jack2 1.9.10
|
00001 /* 00002 Copyright (C) 2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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 // No used for now 00061 // Adapter timing 1 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 // Adapter timing 2 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 // Adapter timing 3 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 //ringbuffers 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 // Finer estimation of the position in the ringbuffer 00245 int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0; 00246 00247 double ratio = 1; 00248 00249 // TODO : done like this just to avoid crash when input only or output only... 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 // Push/pull from ringbuffer 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 // Reset all ringbuffers in case of failure 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 // Push/pull from ringbuffer 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 //jack_log("JackAudioAdapterInterface::GetInputs %d", fCaptureChannels); 00383 return fCaptureChannels; 00384 } 00385 00386 int JackAudioAdapterInterface::GetOutputs() 00387 { 00388 //jack_log ("JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels); 00389 return fPlaybackChannels; 00390 } 00391 00392 00393 } // namespace