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.

272 lines
10KB

  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. #ifdef __APPLE__
  17. #include <TargetConditionals.h>
  18. #endif
  19. #ifndef TARGET_OS_IPHONE
  20. #include "JackLibSampleRateResampler.h"
  21. #endif
  22. #include "JackTime.h"
  23. #include <stdio.h>
  24. namespace Jack
  25. {
  26. #ifdef JACK_MONITOR
  27. void MeasureTable::Write(int time1, int time2, float r1, float r2, int pos1, int pos2)
  28. {
  29. int pos = (++fCount) % TABLE_MAX;
  30. fTable[pos].time1 = time1;
  31. fTable[pos].time2 = time2;
  32. fTable[pos].r1 = r1;
  33. fTable[pos].r2 = r2;
  34. fTable[pos].pos1 = pos1;
  35. fTable[pos].pos2 = pos2;
  36. }
  37. void MeasureTable::Save(unsigned int fHostBufferSize, unsigned int fHostSampleRate, unsigned int fAdaptedSampleRate, unsigned int fAdaptedBufferSize)
  38. {
  39. char buffer[1024];
  40. FILE* file = fopen("JackAudioAdapter.log", "w");
  41. int max = (fCount) % TABLE_MAX - 1;
  42. for (int i = 1; i < max; i++)
  43. {
  44. fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n",
  45. fTable[i].delta, fTable[i+1].time1 - fTable[i].time1,
  46. fTable[i+1].time2 - fTable[i].time2,
  47. fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
  48. }
  49. fclose(file);
  50. /* No used for now
  51. // Adapter timing 1
  52. file = fopen("AdapterTiming1.plot", "w");
  53. fprintf(file, "set multiplot\n");
  54. fprintf(file, "set grid\n");
  55. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  56. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  57. fprintf(file, "set xlabel \"audio cycles\"\n");
  58. fprintf(file, "set ylabel \"frames\"\n");
  59. fprintf(file, "plot ");
  60. sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
  61. fprintf(file, buffer);
  62. sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines");
  63. fprintf(file, buffer);
  64. fprintf(file, "\n unset multiplot\n");
  65. fprintf(file, "set output 'AdapterTiming1.pdf\n");
  66. fprintf(file, "set terminal pdf\n");
  67. fprintf(file, "set multiplot\n");
  68. fprintf(file, "set grid\n");
  69. fprintf(file, "set title \"Audio adapter timing\"\n");
  70. fprintf(file, "set xlabel \"audio cycles\"\n");
  71. fprintf(file, "set ylabel \"frames\"\n");
  72. fprintf(file, "plot ");
  73. sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
  74. fprintf(file, buffer);
  75. sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines");
  76. fprintf(file, buffer);
  77. fclose(file);
  78. */
  79. // Adapter timing 2
  80. file = fopen("AdapterTiming2.plot", "w");
  81. fprintf(file, "set multiplot\n");
  82. fprintf(file, "set grid\n");
  83. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  84. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  85. fprintf(file, "set xlabel \"audio cycles\"\n");
  86. fprintf(file, "set ylabel \"resampling ratio\"\n");
  87. fprintf(file, "plot ");
  88. sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
  89. fprintf(file, buffer);
  90. sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
  91. fprintf(file, buffer);
  92. fprintf(file, "\n unset multiplot\n");
  93. fprintf(file, "set output 'AdapterTiming2.pdf\n");
  94. fprintf(file, "set terminal pdf\n");
  95. fprintf(file, "set multiplot\n");
  96. fprintf(file, "set grid\n");
  97. fprintf(file, "set title \"Audio adapter timing\"\n");
  98. fprintf(file, "set xlabel \"audio cycles\"\n");
  99. fprintf(file, "set ylabel \"resampling ratio\"\n");
  100. fprintf(file, "plot ");
  101. sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
  102. fprintf(file, buffer);
  103. sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
  104. fprintf(file, buffer);
  105. fclose(file);
  106. // Adapter timing 3
  107. file = fopen("AdapterTiming3.plot", "w");
  108. fprintf(file, "set multiplot\n");
  109. fprintf(file, "set grid\n");
  110. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  111. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  112. fprintf(file, "set xlabel \"audio cycles\"\n");
  113. fprintf(file, "set ylabel \"frames\"\n");
  114. fprintf(file, "plot ");
  115. sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
  116. fprintf(file, buffer);
  117. sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
  118. fprintf(file, buffer);
  119. fprintf(file, "\n unset multiplot\n");
  120. fprintf(file, "set output 'AdapterTiming3.pdf\n");
  121. fprintf(file, "set terminal pdf\n");
  122. fprintf(file, "set multiplot\n");
  123. fprintf(file, "set grid\n");
  124. fprintf(file, "set title \"Audio adapter timing\"\n");
  125. fprintf(file, "set xlabel \"audio cycles\"\n");
  126. fprintf(file, "set ylabel \"frames\"\n");
  127. fprintf(file, "plot ");
  128. sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
  129. fprintf(file, buffer);
  130. sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
  131. fprintf(file, buffer);
  132. fclose(file);
  133. }
  134. #endif
  135. void JackAudioAdapterInterface::ResetRingBuffers()
  136. {
  137. for (int i = 0; i < fCaptureChannels; i++)
  138. fCaptureRingBuffer[i]->Reset();
  139. for (int i = 0; i < fPlaybackChannels; i++)
  140. fPlaybackRingBuffer[i]->Reset();
  141. }
  142. void JackAudioAdapterInterface::Reset()
  143. {
  144. ResetRingBuffers();
  145. fRunning = false;
  146. }
  147. #ifdef TARGET_OS_IPHONE
  148. void JackAudioAdapterInterface::Create()
  149. {}
  150. #else
  151. void JackAudioAdapterInterface::Create()
  152. {
  153. //ringbuffers
  154. fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
  155. fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
  156. for (int i = 0; i < fCaptureChannels; i++ )
  157. fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality, fRingbufferSize);
  158. for (int i = 0; i < fPlaybackChannels; i++ )
  159. fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality, fRingbufferSize);
  160. if (fCaptureChannels > 0)
  161. jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
  162. if (fPlaybackChannels > 0)
  163. jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
  164. }
  165. #endif
  166. void JackAudioAdapterInterface::Destroy()
  167. {
  168. for (int i = 0; i < fCaptureChannels; i++ )
  169. delete ( fCaptureRingBuffer[i] );
  170. for (int i = 0; i < fPlaybackChannels; i++ )
  171. delete ( fPlaybackRingBuffer[i] );
  172. delete[] fCaptureRingBuffer;
  173. delete[] fPlaybackRingBuffer;
  174. }
  175. int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames)
  176. {
  177. bool failure = false;
  178. fRunning = true;
  179. /*
  180. Finer estimation of the position in the ringbuffer ??
  181. int delta_frames = (int)(float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f;
  182. double ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetOffset() - delta_frames);
  183. */
  184. double ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetOffset());
  185. // Push/pull from ringbuffer
  186. for (int i = 0; i < fCaptureChannels; i++) {
  187. fCaptureRingBuffer[i]->SetRatio(ratio);
  188. if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames)
  189. failure = true;
  190. }
  191. for (int i = 0; i < fPlaybackChannels; i++) {
  192. fPlaybackRingBuffer[i]->SetRatio(1 / ratio);
  193. if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames)
  194. failure = true;
  195. }
  196. #ifdef JACK_MONITOR
  197. fTable.Write(0, 0, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace());
  198. #endif
  199. // Reset all ringbuffers in case of failure
  200. if (failure) {
  201. jack_error("JackAudioAdapterInterface::PushAndPull ringbuffer failure... reset");
  202. ResetRingBuffers();
  203. return -1;
  204. } else {
  205. return 0;
  206. }
  207. }
  208. int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
  209. {
  210. bool failure = false;
  211. fPullAndPushTime = GetMicroSeconds();
  212. // Push/pull from ringbuffer
  213. for (int i = 0; i < fCaptureChannels; i++) {
  214. if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames)
  215. failure = true;
  216. }
  217. for (int i = 0; i < fPlaybackChannels; i++) {
  218. if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames)
  219. failure = true;
  220. }
  221. // Reset all ringbuffers in case of failure
  222. if (failure) {
  223. jack_error("JackCallbackAudioAdapter::PullAndPush ringbuffer failure... reset");
  224. Reset();
  225. return -1;
  226. } else {
  227. return 0;
  228. }
  229. }
  230. } // namespace