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 <stdio.h>
00030
00031 namespace Jack
00032 {
00033
00034 #ifdef JACK_MONITOR
00035
00036 void MeasureTable::Write(int time1, int time2, float r1, float r2, int pos1, int pos2)
00037 {
00038 int pos = (++fCount) % TABLE_MAX;
00039 fTable[pos].time1 = time1;
00040 fTable[pos].time2 = time2;
00041 fTable[pos].r1 = r1;
00042 fTable[pos].r2 = r2;
00043 fTable[pos].pos1 = pos1;
00044 fTable[pos].pos2 = pos2;
00045 }
00046
00047 void MeasureTable::Save(unsigned int fHostBufferSize, unsigned int fHostSampleRate, unsigned int fAdaptedSampleRate, unsigned int fAdaptedBufferSize)
00048 {
00049 FILE* file = fopen("JackAudioAdapter.log", "w");
00050
00051 int max = (fCount) % TABLE_MAX - 1;
00052 for (int i = 1; i < max; i++) {
00053 fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n",
00054 fTable[i].delta, fTable[i].time1, fTable[i].time2,
00055 fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
00056 }
00057 fclose(file);
00058
00059
00060
00061 file = fopen("AdapterTiming1.plot", "w");
00062 fprintf(file, "set multiplot\n");
00063 fprintf(file, "set grid\n");
00064 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00065 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00066 fprintf(file, "set xlabel \"audio cycles\"\n");
00067 fprintf(file, "set ylabel \"frames\"\n");
00068 fprintf(file, "plot ");
00069 fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,");
00070 fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
00071
00072 fprintf(file, "\n unset multiplot\n");
00073 fprintf(file, "set output 'AdapterTiming1.svg\n");
00074 fprintf(file, "set terminal svg\n");
00075
00076 fprintf(file, "set multiplot\n");
00077 fprintf(file, "set grid\n");
00078 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00079 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00080 fprintf(file, "set xlabel \"audio cycles\"\n");
00081 fprintf(file, "set ylabel \"frames\"\n");
00082 fprintf(file, "plot ");
00083 fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
00084 fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines\n");
00085 fprintf(file, "unset multiplot\n");
00086 fprintf(file, "unset output\n");
00087
00088 fclose(file);
00089
00090
00091 file = fopen("AdapterTiming2.plot", "w");
00092 fprintf(file, "set multiplot\n");
00093 fprintf(file, "set grid\n");
00094 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00095 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00096 fprintf(file, "set xlabel \"audio cycles\"\n");
00097 fprintf(file, "set ylabel \"resampling ratio\"\n");
00098 fprintf(file, "plot ");
00099 fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
00100 fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
00101
00102 fprintf(file, "\n unset multiplot\n");
00103 fprintf(file, "set output 'AdapterTiming2.svg\n");
00104 fprintf(file, "set terminal svg\n");
00105
00106 fprintf(file, "set multiplot\n");
00107 fprintf(file, "set grid\n");
00108 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00109 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00110 fprintf(file, "set xlabel \"audio cycles\"\n");
00111 fprintf(file, "set ylabel \"resampling ratio\"\n");
00112 fprintf(file, "plot ");
00113 fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
00114 fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines\n");
00115 fprintf(file, "unset multiplot\n");
00116 fprintf(file, "unset output\n");
00117
00118 fclose(file);
00119
00120
00121 file = fopen("AdapterTiming3.plot", "w");
00122 fprintf(file, "set multiplot\n");
00123 fprintf(file, "set grid\n");
00124 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00125 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00126 fprintf(file, "set xlabel \"audio cycles\"\n");
00127 fprintf(file, "set ylabel \"frames\"\n");
00128 fprintf(file, "plot ");
00129 fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
00130 fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
00131
00132 fprintf(file, "\n unset multiplot\n");
00133 fprintf(file, "set output 'AdapterTiming3.svg\n");
00134 fprintf(file, "set terminal svg\n");
00135
00136 fprintf(file, "set multiplot\n");
00137 fprintf(file, "set grid\n");
00138 fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
00139 ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
00140 fprintf(file, "set xlabel \"audio cycles\"\n");
00141 fprintf(file, "set ylabel \"frames\"\n");
00142 fprintf(file, "plot ");
00143 fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
00144 fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines\n");
00145 fprintf(file, "unset multiplot\n");
00146 fprintf(file, "unset output\n");
00147
00148 fclose(file);
00149 }
00150
00151 #endif
00152
00153 void JackAudioAdapterInterface::GrowRingBufferSize()
00154 {
00155 fRingbufferCurSize *= 2;
00156 }
00157
00158 void JackAudioAdapterInterface::AdaptRingBufferSize()
00159 {
00160 if (fHostBufferSize > fAdaptedBufferSize) {
00161 fRingbufferCurSize = 4 * fHostBufferSize;
00162 } else {
00163 fRingbufferCurSize = 4 * fAdaptedBufferSize;
00164 }
00165 }
00166
00167 void JackAudioAdapterInterface::ResetRingBuffers()
00168 {
00169 if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
00170 fRingbufferCurSize = DEFAULT_RB_SIZE;
00171 }
00172
00173 for (int i = 0; i < fCaptureChannels; i++) {
00174 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
00175 }
00176 for (int i = 0; i < fPlaybackChannels; i++) {
00177 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
00178 }
00179 }
00180
00181 void JackAudioAdapterInterface::Reset()
00182 {
00183 ResetRingBuffers();
00184 fRunning = false;
00185 }
00186
00187 #ifdef MY_TARGET_OS_IPHONE
00188 void JackAudioAdapterInterface::Create()
00189 {}
00190 #else
00191 void JackAudioAdapterInterface::Create()
00192 {
00193
00194 fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
00195 fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
00196
00197 if (fAdaptative) {
00198 AdaptRingBufferSize();
00199 jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
00200 } else {
00201 if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
00202 fRingbufferCurSize = DEFAULT_RB_SIZE;
00203 }
00204 jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
00205 }
00206
00207 for (int i = 0; i < fCaptureChannels; i++ ) {
00208 fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
00209 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
00210 }
00211 for (int i = 0; i < fPlaybackChannels; i++ ) {
00212 fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
00213 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
00214 }
00215
00216 if (fCaptureChannels > 0) {
00217 jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
00218 }
00219 if (fPlaybackChannels > 0) {
00220 jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
00221 }
00222 }
00223 #endif
00224
00225 void JackAudioAdapterInterface::Destroy()
00226 {
00227 for (int i = 0; i < fCaptureChannels; i++) {
00228 delete(fCaptureRingBuffer[i]);
00229 }
00230 for (int i = 0; i < fPlaybackChannels; i++) {
00231 delete (fPlaybackRingBuffer[i]);
00232 }
00233
00234 delete[] fCaptureRingBuffer;
00235 delete[] fPlaybackRingBuffer;
00236 }
00237
00238 int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames)
00239 {
00240 bool failure = false;
00241 fRunning = true;
00242
00243
00244 int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0;
00245
00246 double ratio = 1;
00247
00248
00249 if (fCaptureChannels > 0) {
00250 ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
00251 } else if (fPlaybackChannels > 0) {
00252 ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames);
00253 }
00254
00255 #ifdef JACK_MONITOR
00256 if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL)
00257 fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
00258 #endif
00259
00260
00261 for (int i = 0; i < fCaptureChannels; i++) {
00262 fCaptureRingBuffer[i]->SetRatio(ratio);
00263 if (inputBuffer[i]) {
00264 if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames) {
00265 failure = true;
00266 }
00267 }
00268 }
00269
00270 for (int i = 0; i < fPlaybackChannels; i++) {
00271 fPlaybackRingBuffer[i]->SetRatio(1/ratio);
00272 if (outputBuffer[i]) {
00273 if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) {
00274 failure = true;
00275 }
00276 }
00277 }
00278
00279 if (failure) {
00280 jack_error("JackAudioAdapterInterface::PushAndPull ringbuffer failure... reset");
00281 if (fAdaptative) {
00282 GrowRingBufferSize();
00283 jack_info("Ringbuffer size = %d frames", fRingbufferCurSize);
00284 }
00285 ResetRingBuffers();
00286 return -1;
00287 } else {
00288 return 0;
00289 }
00290 }
00291
00292 int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
00293 {
00294 fPullAndPushTime = GetMicroSeconds();
00295 if (!fRunning)
00296 return 0;
00297
00298 int res = 0;
00299
00300
00301 for (int i = 0; i < fCaptureChannels; i++) {
00302 if (inputBuffer[i]) {
00303 if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) {
00304 res = -1;
00305 }
00306 }
00307 }
00308
00309 for (int i = 0; i < fPlaybackChannels; i++) {
00310 if (outputBuffer[i]) {
00311 if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) {
00312 res = -1;
00313 }
00314 }
00315 }
00316
00317 return res;
00318 }
00319
00320 }