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