Jack2 1.9.10

JackAudioAdapterInterface.cpp

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