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.

325 lines
13KB

  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. #ifdef __APPLE__
  16. #include <TargetConditionals.h>
  17. #endif
  18. #include "JackAudioAdapter.h"
  19. #ifndef MY_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].time1, fTable[i].time2,
  46. fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
  47. }
  48. fclose(file);
  49. // No used for now
  50. // Adapter timing 1
  51. file = fopen("AdapterTiming1.plot", "w");
  52. fprintf(file, "set multiplot\n");
  53. fprintf(file, "set grid\n");
  54. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  55. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  56. fprintf(file, "set xlabel \"audio cycles\"\n");
  57. fprintf(file, "set ylabel \"frames\"\n");
  58. fprintf(file, "plot ");
  59. sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,");
  60. fprintf(file, buffer);
  61. sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
  62. fprintf(file, buffer);
  63. fprintf(file, "\n unset multiplot\n");
  64. fprintf(file, "set output 'AdapterTiming1.svg\n");
  65. fprintf(file, "set terminal svg\n");
  66. fprintf(file, "set multiplot\n");
  67. fprintf(file, "set grid\n");
  68. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  69. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  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\n");
  76. fprintf(file, buffer);
  77. fprintf(file, "unset multiplot\n");
  78. fprintf(file, "unset output\n");
  79. fclose(file);
  80. // Adapter timing 2
  81. file = fopen("AdapterTiming2.plot", "w");
  82. fprintf(file, "set multiplot\n");
  83. fprintf(file, "set grid\n");
  84. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  85. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  86. fprintf(file, "set xlabel \"audio cycles\"\n");
  87. fprintf(file, "set ylabel \"resampling ratio\"\n");
  88. fprintf(file, "plot ");
  89. sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
  90. fprintf(file, buffer);
  91. sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
  92. fprintf(file, buffer);
  93. fprintf(file, "\n unset multiplot\n");
  94. fprintf(file, "set output 'AdapterTiming2.svg\n");
  95. fprintf(file, "set terminal svg\n");
  96. fprintf(file, "set multiplot\n");
  97. fprintf(file, "set grid\n");
  98. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  99. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  100. fprintf(file, "set xlabel \"audio cycles\"\n");
  101. fprintf(file, "set ylabel \"resampling ratio\"\n");
  102. fprintf(file, "plot ");
  103. sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
  104. fprintf(file, buffer);
  105. sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines\n");
  106. fprintf(file, buffer);
  107. fprintf(file, "unset multiplot\n");
  108. fprintf(file, "unset output\n");
  109. fclose(file);
  110. // Adapter timing 3
  111. file = fopen("AdapterTiming3.plot", "w");
  112. fprintf(file, "set multiplot\n");
  113. fprintf(file, "set grid\n");
  114. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  115. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  116. fprintf(file, "set xlabel \"audio cycles\"\n");
  117. fprintf(file, "set ylabel \"frames\"\n");
  118. fprintf(file, "plot ");
  119. sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
  120. fprintf(file, buffer);
  121. sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
  122. fprintf(file, buffer);
  123. fprintf(file, "\n unset multiplot\n");
  124. fprintf(file, "set output 'AdapterTiming3.svg\n");
  125. fprintf(file, "set terminal svg\n");
  126. fprintf(file, "set multiplot\n");
  127. fprintf(file, "set grid\n");
  128. fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
  129. ,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize);
  130. fprintf(file, "set xlabel \"audio cycles\"\n");
  131. fprintf(file, "set ylabel \"frames\"\n");
  132. fprintf(file, "plot ");
  133. sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
  134. fprintf(file, buffer);
  135. sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines\n");
  136. fprintf(file, buffer);
  137. fprintf(file, "unset multiplot\n");
  138. fprintf(file, "unset output\n");
  139. fclose(file);
  140. }
  141. #endif
  142. void JackAudioAdapterInterface::GrowRingBufferSize()
  143. {
  144. fRingbufferCurSize *= 2;
  145. }
  146. void JackAudioAdapterInterface::AdaptRingBufferSize()
  147. {
  148. if (fHostBufferSize > fAdaptedBufferSize)
  149. fRingbufferCurSize = 4 * fHostBufferSize;
  150. else
  151. fRingbufferCurSize = 4 * fAdaptedBufferSize;
  152. }
  153. void JackAudioAdapterInterface::ResetRingBuffers()
  154. {
  155. if (fRingbufferCurSize > DEFAULT_RB_SIZE)
  156. fRingbufferCurSize = DEFAULT_RB_SIZE;
  157. for (int i = 0; i < fCaptureChannels; i++)
  158. fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
  159. for (int i = 0; i < fPlaybackChannels; i++)
  160. fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
  161. }
  162. void JackAudioAdapterInterface::Reset()
  163. {
  164. ResetRingBuffers();
  165. fRunning = false;
  166. }
  167. #ifdef MY_TARGET_OS_IPHONE
  168. void JackAudioAdapterInterface::Create()
  169. {}
  170. #else
  171. void JackAudioAdapterInterface::Create()
  172. {
  173. //ringbuffers
  174. fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
  175. fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
  176. if (fAdaptative) {
  177. AdaptRingBufferSize();
  178. jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
  179. } else {
  180. if (fRingbufferCurSize > DEFAULT_RB_SIZE)
  181. fRingbufferCurSize = DEFAULT_RB_SIZE;
  182. jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
  183. }
  184. for (int i = 0; i < fCaptureChannels; i++ ) {
  185. fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
  186. fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
  187. }
  188. for (int i = 0; i < fPlaybackChannels; i++ ) {
  189. fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
  190. fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
  191. }
  192. if (fCaptureChannels > 0)
  193. jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
  194. if (fPlaybackChannels > 0)
  195. jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
  196. }
  197. #endif
  198. void JackAudioAdapterInterface::Destroy()
  199. {
  200. for (int i = 0; i < fCaptureChannels; i++ )
  201. delete ( fCaptureRingBuffer[i] );
  202. for (int i = 0; i < fPlaybackChannels; i++ )
  203. delete ( fPlaybackRingBuffer[i] );
  204. delete[] fCaptureRingBuffer;
  205. delete[] fPlaybackRingBuffer;
  206. }
  207. int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames)
  208. {
  209. bool failure = false;
  210. fRunning = true;
  211. // Finer estimation of the position in the ringbuffer
  212. int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0;
  213. double ratio = 1;
  214. // TODO : done like this just to avoid crash when input only or output only...
  215. if (fCaptureChannels > 0)
  216. ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
  217. else if (fPlaybackChannels > 0)
  218. ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames);
  219. #ifdef JACK_MONITOR
  220. if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL)
  221. fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
  222. #endif
  223. // Push/pull from ringbuffer
  224. for (int i = 0; i < fCaptureChannels; i++) {
  225. fCaptureRingBuffer[i]->SetRatio(ratio);
  226. if (inputBuffer[i]) {
  227. if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames) {
  228. failure = true;
  229. }
  230. }
  231. }
  232. for (int i = 0; i < fPlaybackChannels; i++) {
  233. fPlaybackRingBuffer[i]->SetRatio(1/ratio);
  234. if (outputBuffer[i]) {
  235. if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) {
  236. failure = true;
  237. }
  238. }
  239. }
  240. // Reset all ringbuffers in case of failure
  241. if (failure) {
  242. jack_error("JackAudioAdapterInterface::PushAndPull ringbuffer failure... reset");
  243. if (fAdaptative) {
  244. GrowRingBufferSize();
  245. jack_info("Ringbuffer size = %d frames", fRingbufferCurSize);
  246. }
  247. ResetRingBuffers();
  248. return -1;
  249. } else {
  250. return 0;
  251. }
  252. }
  253. int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
  254. {
  255. fPullAndPushTime = GetMicroSeconds();
  256. if (!fRunning)
  257. return 0;
  258. int res = 0;
  259. // Push/pull from ringbuffer
  260. for (int i = 0; i < fCaptureChannels; i++) {
  261. if (inputBuffer[i]) {
  262. if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) {
  263. res = -1;
  264. }
  265. }
  266. }
  267. for (int i = 0; i < fPlaybackChannels; i++) {
  268. if (outputBuffer[i]) {
  269. if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) {
  270. res = -1;
  271. }
  272. }
  273. }
  274. return res;
  275. }
  276. } // namespace