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.

247 lines
9.6KB

  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 "JackPortAudioIOAdapter.h"
  16. #include "portaudio.h"
  17. #include "JackError.h"
  18. namespace Jack
  19. {
  20. static inline float Range(float min, float max, float val)
  21. {
  22. return (val < min) ? min : ((val > max) ? max : val);
  23. }
  24. /*
  25. int JackPortAudioIOAdapter::Render(const void* inputBuffer, void* outputBuffer,
  26. unsigned long framesPerBuffer,
  27. const PaStreamCallbackTimeInfo* timeInfo,
  28. PaStreamCallbackFlags statusFlags,
  29. void* userData)
  30. {
  31. JackPortAudioIOAdapter* adapter = static_cast<JackPortAudioIOAdapter*>(userData);
  32. float** paBuffer;
  33. char* buffer;
  34. if (!adapter->fRunning) {
  35. adapter->fRunning = true;
  36. adapter->fFirstCallbackTime = jack_get_time();
  37. }
  38. double src_ratio = double(jack_get_time() - adapter->fFirstCallbackTime) / double( adapter->fCallbackTime - adapter->fFirstCallbackTime);
  39. jack_log("Callback resampler coeff %f", src_ratio);
  40. paBuffer = (float**)inputBuffer;
  41. for (int i = 0; i < adapter->fCaptureChannels; i++) {
  42. buffer = (char*)paBuffer[i];
  43. size_t len = jack_ringbuffer_write_space(adapter->fCaptureRingBuffer[i]);
  44. if (len < framesPerBuffer * sizeof(float)) {
  45. jack_error("JackPortAudioIOAdapter::Process : producer too slow, missing frames = %d", framesPerBuffer - len / sizeof(float));
  46. jack_ringbuffer_write(adapter->fCaptureRingBuffer[i], buffer, len);
  47. } else {
  48. jack_ringbuffer_write(adapter->fCaptureRingBuffer[i], buffer, framesPerBuffer * sizeof(float));
  49. }
  50. }
  51. paBuffer = (float**)outputBuffer;
  52. for (int i = 0; i < adapter->fPlaybackChannels; i++) {
  53. buffer = (char*)paBuffer[i];
  54. size_t len = jack_ringbuffer_read_space(adapter->fPlaybackRingBuffer[i]);
  55. if (len < framesPerBuffer * sizeof(float)) {
  56. jack_error("JackPortAudioIOAdapter::Process : consumer too slow, skip frames = %d", framesPerBuffer - len / sizeof(float));
  57. jack_ringbuffer_read(adapter->fPlaybackRingBuffer[i], buffer, len);
  58. } else {
  59. jack_ringbuffer_read(adapter->fPlaybackRingBuffer[i], buffer, framesPerBuffer * sizeof(float));
  60. }
  61. }
  62. return paContinue;
  63. }
  64. */
  65. int JackPortAudioIOAdapter::Render(const void* inputBuffer, void* outputBuffer,
  66. unsigned long framesPerBuffer,
  67. const PaStreamCallbackTimeInfo* timeInfo,
  68. PaStreamCallbackFlags statusFlags,
  69. void* userData)
  70. {
  71. JackPortAudioIOAdapter* adapter = static_cast<JackPortAudioIOAdapter*>(userData);
  72. float** paBuffer;
  73. float* buffer;
  74. int res;
  75. adapter->fLastCallbackTime = adapter->fCurCallbackTime;
  76. adapter->fCurCallbackTime = jack_get_time();
  77. adapter->fConsumerFilter.AddValue(adapter->fCurCallbackTime - adapter->fLastCallbackTime);
  78. adapter->fProducerFilter.AddValue(adapter->fDeltaTime);
  79. jack_log("JackPortAudioIOAdapter::Render delta %ld", adapter->fCurCallbackTime - adapter->fLastCallbackTime);
  80. if (!adapter->fRunning) {
  81. adapter->fRunning = true;
  82. paBuffer = (float**)inputBuffer;
  83. for (int i = 0; i < adapter->fCaptureChannels; i++) {
  84. buffer = static_cast<float*>(paBuffer[i]);
  85. adapter->fCaptureRingBuffer[i].Read(buffer, framesPerBuffer);
  86. adapter->fCaptureRingBuffer[i].Read(buffer, framesPerBuffer);
  87. adapter->fCaptureRingBuffer[i].Read(buffer, framesPerBuffer);
  88. }
  89. paBuffer = (float**)outputBuffer;
  90. for (int i = 0; i < adapter->fPlaybackChannels; i++) {
  91. buffer = static_cast<float*>(paBuffer[i]);
  92. adapter->fPlaybackRingBuffer[i].Write(buffer, framesPerBuffer);
  93. adapter->fPlaybackRingBuffer[i].Write(buffer, framesPerBuffer);
  94. adapter->fPlaybackRingBuffer[i].Write(buffer, framesPerBuffer);
  95. }
  96. }
  97. /*
  98. double src_ratio_output = double(adapter->fCurCallbackTime - adapter->fLastCallbackTime) / double(adapter->fDeltaTime);
  99. double src_ratio_input = double(adapter->fDeltaTime) / double(adapter->fCurCallbackTime - adapter->fLastCallbackTime);
  100. */
  101. jack_time_t val1 = adapter->fConsumerFilter.GetVal();
  102. jack_time_t val2 = adapter->fProducerFilter.GetVal();
  103. double src_ratio_output = double(val1) / double(val2);
  104. double src_ratio_input = double(val2) / double(val1);
  105. if (src_ratio_input < 0.8f || src_ratio_input > 1.2f)
  106. jack_error("src_ratio_input = %f", src_ratio_input);
  107. if (src_ratio_output < 0.8f || src_ratio_output > 1.2f)
  108. jack_error("src_ratio_output = %f", src_ratio_output);
  109. src_ratio_input = Range(0.8f, 1.2f, src_ratio_input);
  110. src_ratio_output = Range(0.8f, 1.2f, src_ratio_output);
  111. jack_log("Callback resampler src_ratio_input = %f src_ratio_output = %f", src_ratio_input, src_ratio_output);
  112. paBuffer = (float**)inputBuffer;
  113. for (int i = 0; i < adapter->fCaptureChannels; i++) {
  114. buffer = (float*)paBuffer[i];
  115. adapter->fCaptureRingBuffer[i].SetRatio(src_ratio_input);
  116. int len = adapter->fCaptureRingBuffer[i].WriteResample(buffer, framesPerBuffer);
  117. //int len = adapter->fCaptureRingBuffer[i].Write(buffer, framesPerBuffer);
  118. }
  119. paBuffer = (float**)outputBuffer;
  120. for (int i = 0; i < adapter->fPlaybackChannels; i++) {
  121. buffer = (float*)paBuffer[i];
  122. adapter->fPlaybackRingBuffer[i].SetRatio(src_ratio_output);
  123. int len = adapter->fPlaybackRingBuffer[i].ReadResample(buffer, framesPerBuffer);
  124. //int len = adapter->fPlaybackRingBuffer[i].Read(buffer, framesPerBuffer);
  125. }
  126. return paContinue;
  127. }
  128. int JackPortAudioIOAdapter::Open()
  129. {
  130. PaError err;
  131. PaStreamParameters inputParameters;
  132. PaStreamParameters outputParameters;
  133. PaDeviceIndex inputDevice;
  134. PaDeviceIndex outputDevice;
  135. if (JackIOAdapterInterface::Open() < 0)
  136. return -1;
  137. err = Pa_Initialize();
  138. if (err != paNoError) {
  139. jack_error("JackPortAudioIOAdapter::Pa_Initialize error = %s\n", Pa_GetErrorText(err));
  140. goto error;
  141. }
  142. jack_log("JackPortAudioIOAdapter::Pa_GetDefaultInputDevice %ld", Pa_GetDefaultInputDevice());
  143. jack_log("JackPortAudioIOAdapter::Pa_GetDefaultOutputDevice %ld", Pa_GetDefaultOutputDevice());
  144. jack_log("JackPortAudioIOAdapter::Open fBufferSize = %ld fSampleRate %f", fBufferSize, fSampleRate);
  145. inputDevice = Pa_GetDefaultInputDevice();
  146. outputDevice = Pa_GetDefaultOutputDevice();
  147. inputParameters.device = inputDevice;
  148. inputParameters.channelCount = fCaptureChannels;
  149. inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
  150. inputParameters.suggestedLatency = (inputDevice != paNoDevice) // TODO: check how to setup this on ASIO
  151. ? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency
  152. : 0;
  153. inputParameters.hostApiSpecificStreamInfo = NULL;
  154. outputParameters.device = outputDevice;
  155. outputParameters.channelCount = fPlaybackChannels;
  156. outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
  157. outputParameters.suggestedLatency = (outputDevice != paNoDevice) // TODO: check how to setup this on ASIO
  158. ? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency
  159. : 0;
  160. outputParameters.hostApiSpecificStreamInfo = NULL;
  161. err = Pa_OpenStream(&fStream,
  162. (inputDevice == paNoDevice) ? 0 : &inputParameters,
  163. (outputDevice == paNoDevice) ? 0 : &outputParameters,
  164. fSampleRate,
  165. fBufferSize,
  166. paNoFlag, // Clipping is on...
  167. Render,
  168. this);
  169. if (err != paNoError) {
  170. jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
  171. goto error;
  172. }
  173. err = Pa_StartStream(fStream);
  174. if (err != paNoError) {
  175. jack_error("Pa_StartStream error = %s", Pa_GetErrorText(err));
  176. goto error;
  177. }
  178. jack_log("JackPortAudioIOAdapter::Open OK");
  179. return 0;
  180. error:
  181. Pa_Terminate();
  182. return -1;
  183. }
  184. int JackPortAudioIOAdapter::Close()
  185. {
  186. jack_log("JackPortAudioIOAdapter::Close");
  187. Pa_StopStream(fStream);
  188. jack_log("JackPortAudioIOAdapter:: Pa_StopStream");
  189. Pa_CloseStream(fStream);
  190. jack_log("JackPortAudioIOAdapter:: Pa_CloseStream");
  191. Pa_Terminate();
  192. jack_log("JackPortAudioIOAdapter:: Pa_Terminate");
  193. return JackIOAdapterInterface::Close();
  194. }
  195. void JackPortAudioIOAdapter::SetBufferSize(int buffer_size)
  196. {
  197. JackIOAdapterInterface::SetBufferSize(buffer_size);
  198. Close();
  199. Open();
  200. }
  201. } // namespace