jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

296 lines
12KB

  1. /*
  2. Copyright (C) 2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackAudioAdapter.h"
  16. #include "JackLibSampleRateResampler.h"
  17. #include "JackTime.h"
  18. #include <stdio.h>
  19. namespace Jack
  20. {
  21. #ifdef JACK_MONITOR
  22. void MeasureTable::Write(int time1, int time2, float r1, float r2, int pos1, int pos2)
  23. {
  24. int pos = (++fCount) % TABLE_MAX;
  25. fTable[pos].time1 = time1;
  26. fTable[pos].time2 = time2;
  27. fTable[pos].r1 = r1;
  28. fTable[pos].r2 = r2;
  29. fTable[pos].pos1 = pos1;
  30. fTable[pos].pos2 = pos2;
  31. }
  32. void MeasureTable::Save(unsigned int fHostBufferSize, unsigned int fHostSampleRate, unsigned int fAdaptedSampleRate, unsigned int fAdaptedBufferSize)
  33. {
  34. char buffer[1024];
  35. FILE* file = fopen("JackAudioAdapter.log", "w");
  36. int max = (fCount) % TABLE_MAX - 1;
  37. for (int i = 1; i < max; i++)
  38. {
  39. fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n",
  40. fTable[i].delta, fTable[i].time1, fTable[i].time2,
  41. fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
  42. }
  43. fclose(file);
  44. // No used for now
  45. // Adapter timing 1
  46. file = fopen("AdapterTiming1.plot", "w");
  47. fprintf(file, "set multiplot\n");
  48. fprintf(file, "set grid\n");
  49. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  50. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  51. fprintf(file, "set xlabel \"audio cycles\"\n");
  52. fprintf(file, "set ylabel \"frames\"\n");
  53. fprintf(file, "plot ");
  54. sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,");
  55. fprintf(file, buffer);
  56. sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
  57. fprintf(file, buffer);
  58. fprintf(file, "\n unset multiplot\n");
  59. fprintf(file, "set output 'AdapterTiming1.pdf\n");
  60. fprintf(file, "set terminal pdf\n");
  61. fprintf(file, "set multiplot\n");
  62. fprintf(file, "set grid\n");
  63. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  64. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  65. fprintf(file, "set xlabel \"audio cycles\"\n");
  66. fprintf(file, "set ylabel \"frames\"\n");
  67. fprintf(file, "plot ");
  68. sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
  69. fprintf(file, buffer);
  70. sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines");
  71. fprintf(file, buffer);
  72. fclose(file);
  73. // Adapter timing 2
  74. file = fopen("AdapterTiming2.plot", "w");
  75. fprintf(file, "set multiplot\n");
  76. fprintf(file, "set grid\n");
  77. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  78. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  79. fprintf(file, "set xlabel \"audio cycles\"\n");
  80. fprintf(file, "set ylabel \"resampling ratio\"\n");
  81. fprintf(file, "plot ");
  82. sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
  83. fprintf(file, buffer);
  84. sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
  85. fprintf(file, buffer);
  86. fprintf(file, "\n unset multiplot\n");
  87. fprintf(file, "set output 'AdapterTiming2.pdf\n");
  88. fprintf(file, "set terminal pdf\n");
  89. fprintf(file, "set multiplot\n");
  90. fprintf(file, "set grid\n");
  91. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  92. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  93. fprintf(file, "set xlabel \"audio cycles\"\n");
  94. fprintf(file, "set ylabel \"resampling ratio\"\n");
  95. fprintf(file, "plot ");
  96. sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
  97. fprintf(file, buffer);
  98. sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
  99. fprintf(file, buffer);
  100. fclose(file);
  101. // Adapter timing 3
  102. file = fopen("AdapterTiming3.plot", "w");
  103. fprintf(file, "set multiplot\n");
  104. fprintf(file, "set grid\n");
  105. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  106. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  107. fprintf(file, "set xlabel \"audio cycles\"\n");
  108. fprintf(file, "set ylabel \"frames\"\n");
  109. fprintf(file, "plot ");
  110. sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
  111. fprintf(file, buffer);
  112. sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
  113. fprintf(file, buffer);
  114. fprintf(file, "\n unset multiplot\n");
  115. fprintf(file, "set output 'AdapterTiming3.pdf\n");
  116. fprintf(file, "set terminal pdf\n");
  117. fprintf(file, "set multiplot\n");
  118. fprintf(file, "set grid\n");
  119. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  120. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  121. fprintf(file, "set xlabel \"audio cycles\"\n");
  122. fprintf(file, "set ylabel \"frames\"\n");
  123. fprintf(file, "plot ");
  124. sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
  125. fprintf(file, buffer);
  126. sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
  127. fprintf(file, buffer);
  128. fclose(file);
  129. }
  130. #endif
  131. void JackAudioAdapterInterface::GrowRingBufferSize()
  132. {
  133. fRingbufferCurSize *= 2;
  134. }
  135. void JackAudioAdapterInterface::AdaptRingBufferSize()
  136. {
  137. if (fHostBufferSize > fAdaptedBufferSize)
  138. fRingbufferCurSize = 4 * fHostBufferSize;
  139. else
  140. fRingbufferCurSize = 4 * fAdaptedBufferSize;
  141. }
  142. void JackAudioAdapterInterface::ResetRingBuffers()
  143. {
  144. if (fRingbufferCurSize > DEFAULT_RB_SIZE)
  145. fRingbufferCurSize = DEFAULT_RB_SIZE;
  146. for (int i = 0; i < fCaptureChannels; i++)
  147. fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
  148. for (int i = 0; i < fPlaybackChannels; i++)
  149. fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
  150. }
  151. void JackAudioAdapterInterface::Reset()
  152. {
  153. ResetRingBuffers();
  154. fRunning = false;
  155. }
  156. void JackAudioAdapterInterface::Create()
  157. {
  158. //ringbuffers
  159. fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
  160. fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
  161. if (fAdaptative) {
  162. AdaptRingBufferSize();
  163. jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
  164. } else {
  165. if (fRingbufferCurSize > DEFAULT_RB_SIZE)
  166. fRingbufferCurSize = DEFAULT_RB_SIZE;
  167. jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
  168. }
  169. for (int i = 0; i < fCaptureChannels; i++ ) {
  170. fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
  171. fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
  172. }
  173. for (int i = 0; i < fPlaybackChannels; i++ ) {
  174. fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
  175. fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
  176. }
  177. if (fCaptureChannels > 0)
  178. jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
  179. if (fPlaybackChannels > 0)
  180. jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
  181. }
  182. void JackAudioAdapterInterface::Destroy()
  183. {
  184. for (int i = 0; i < fCaptureChannels; i++ )
  185. delete ( fCaptureRingBuffer[i] );
  186. for (int i = 0; i < fPlaybackChannels; i++ )
  187. delete ( fPlaybackRingBuffer[i] );
  188. delete[] fCaptureRingBuffer;
  189. delete[] fPlaybackRingBuffer;
  190. }
  191. int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames)
  192. {
  193. bool failure = false;
  194. fRunning = true;
  195. // Finer estimation of the position in the ringbuffer
  196. int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0;
  197. double ratio = 1;
  198. // TODO : done like this just to avoid crash when input only or output only...
  199. if (fCaptureChannels > 0)
  200. ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
  201. else if (fPlaybackChannels > 0)
  202. ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames);
  203. #ifdef JACK_MONITOR
  204. if (fCaptureRingBuffer[0] != NULL)
  205. fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
  206. #endif
  207. // Push/pull from ringbuffer
  208. for (int i = 0; i < fCaptureChannels; i++) {
  209. fCaptureRingBuffer[i]->SetRatio(ratio);
  210. if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames)
  211. failure = true;
  212. }
  213. for (int i = 0; i < fPlaybackChannels; i++) {
  214. fPlaybackRingBuffer[i]->SetRatio(1/ratio);
  215. if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames)
  216. failure = true;
  217. }
  218. // Reset all ringbuffers in case of failure
  219. if (failure) {
  220. jack_error("JackAudioAdapterInterface::PushAndPull ringbuffer failure... reset");
  221. if (fAdaptative) {
  222. GrowRingBufferSize();
  223. jack_info("Ringbuffer size = %d frames", fRingbufferCurSize);
  224. }
  225. ResetRingBuffers();
  226. return -1;
  227. } else {
  228. return 0;
  229. }
  230. }
  231. int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
  232. {
  233. fPullAndPushTime = GetMicroSeconds();
  234. if (!fRunning)
  235. return 0;
  236. int res = 0;
  237. // Push/pull from ringbuffer
  238. for (int i = 0; i < fCaptureChannels; i++) {
  239. if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames)
  240. res = -1;
  241. }
  242. for (int i = 0; i < fPlaybackChannels; i++) {
  243. if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames)
  244. res = -1;
  245. }
  246. return res;
  247. }
  248. } // namespace