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.

201 lines
7.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. int JackPortAudioIOAdapter::Render(const void* inputBuffer, void* outputBuffer,
  21. unsigned long framesPerBuffer,
  22. const PaStreamCallbackTimeInfo* timeInfo,
  23. PaStreamCallbackFlags statusFlags,
  24. void* userData)
  25. {
  26. JackPortAudioIOAdapter* adapter = static_cast<JackPortAudioIOAdapter*>(userData);
  27. float** paBuffer;
  28. float* buffer;
  29. adapter->fLastCallbackTime = adapter->fCurCallbackTime;
  30. adapter->fCurCallbackTime = jack_get_time();
  31. adapter->fConsumerFilter.AddValue(adapter->fCurCallbackTime - adapter->fLastCallbackTime);
  32. adapter->fProducerFilter.AddValue(adapter->fDeltaTime);
  33. jack_log("JackPortAudioIOAdapter::Render delta %ld", adapter->fCurCallbackTime - adapter->fLastCallbackTime);
  34. if (!adapter->fRunning) {
  35. adapter->fRunning = true;
  36. jack_time_t time = jack_get_time();
  37. adapter->fProducerDLL.Init(time);
  38. adapter->fConsumerDLL.Init(time);
  39. adapter->fCurFrames = 0;
  40. }
  41. /*
  42. double src_ratio_output = double(adapter->fCurCallbackTime - adapter->fLastCallbackTime) / double(adapter->fDeltaTime);
  43. double src_ratio_input = double(adapter->fDeltaTime) / double(adapter->fCurCallbackTime - adapter->fLastCallbackTime);
  44. */
  45. // DLL based
  46. //adapter->fConsumerDLL.IncFrame(adapter->fConsumerTime);
  47. jack_time_t time = jack_get_time();
  48. adapter->fProducerDLL.IncFrame(time);
  49. jack_nframes_t time1 = adapter->fConsumerDLL.Time2Frames(time);
  50. jack_nframes_t time2 = adapter->fProducerDLL.Time2Frames(time);
  51. //printf("time1 %ld time2 %ld\n",time1, time2);
  52. double src_ratio_output = double(time2) / double(time1);
  53. double src_ratio_input = double(time1) / double(time2);
  54. /*
  55. jack_time_t val2 = adapter->fConsumerFilter.GetVal();
  56. jack_time_t val1 = adapter->fProducerFilter.GetVal();
  57. double src_ratio_output = double(val1) / double(val2);
  58. double src_ratio_input = double(val2) / double(val1);
  59. */
  60. if (src_ratio_input < 0.8f || src_ratio_input > 1.2f) {
  61. jack_error("src_ratio_input = %f", src_ratio_input);
  62. src_ratio_input = 1;
  63. }
  64. if (src_ratio_output < 0.8f || src_ratio_output > 1.2f) {
  65. jack_error("src_ratio_output = %f", src_ratio_output);
  66. src_ratio_output = 1;
  67. }
  68. src_ratio_input = Range(0.8f, 1.2f, src_ratio_input);
  69. src_ratio_output = Range(0.8f, 1.2f, src_ratio_output);
  70. //jack_log("Callback resampler src_ratio_input = %f src_ratio_output = %f", src_ratio_input, src_ratio_output);
  71. paBuffer = (float**)inputBuffer;
  72. for (int i = 0; i < adapter->fCaptureChannels; i++) {
  73. buffer = (float*)paBuffer[i];
  74. adapter->fCaptureRingBuffer[i].SetRatio(time1, time2);
  75. //adapter->fCaptureRingBuffer[i].WriteResample(buffer, framesPerBuffer);
  76. //adapter->fCaptureRingBuffer[i].SetRatio(double(adapter->fNum) * adapter->fError1, adapter->fDenom);
  77. adapter->fCaptureRingBuffer[i].Write(buffer, framesPerBuffer);
  78. }
  79. paBuffer = (float**)outputBuffer;
  80. for (int i = 0; i < adapter->fPlaybackChannels; i++) {
  81. buffer = (float*)paBuffer[i];
  82. adapter->fPlaybackRingBuffer[i].SetRatio(time2, time1);
  83. //adapter->fPlaybackRingBuffer[i].ReadResample(buffer, framesPerBuffer);
  84. //adapter->fCaptureRingBuffer[i].SetRatio(double(adapter->fDenom) * adapter->fError1, adapter->fNum);
  85. adapter->fPlaybackRingBuffer[i].Read(buffer, framesPerBuffer);
  86. }
  87. printf("Callback resampler src_ratio_input = %f src_ratio_output = %f\n", double(time1) / double(time2), double(time2) / double(time1));
  88. return paContinue;
  89. }
  90. int JackPortAudioIOAdapter::Open()
  91. {
  92. PaError err;
  93. PaStreamParameters inputParameters;
  94. PaStreamParameters outputParameters;
  95. PaDeviceIndex inputDevice;
  96. PaDeviceIndex outputDevice;
  97. if (JackIOAdapterInterface::Open() < 0)
  98. return -1;
  99. err = Pa_Initialize();
  100. if (err != paNoError) {
  101. jack_error("JackPortAudioIOAdapter::Pa_Initialize error = %s\n", Pa_GetErrorText(err));
  102. goto error;
  103. }
  104. jack_log("JackPortAudioIOAdapter::Pa_GetDefaultInputDevice %ld", Pa_GetDefaultInputDevice());
  105. jack_log("JackPortAudioIOAdapter::Pa_GetDefaultOutputDevice %ld", Pa_GetDefaultOutputDevice());
  106. jack_log("JackPortAudioIOAdapter::Open fBufferSize = %ld fSampleRate %f", fBufferSize, fSampleRate);
  107. inputDevice = Pa_GetDefaultInputDevice();
  108. outputDevice = Pa_GetDefaultOutputDevice();
  109. inputParameters.device = inputDevice;
  110. inputParameters.channelCount = fCaptureChannels;
  111. inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
  112. inputParameters.suggestedLatency = (inputDevice != paNoDevice) // TODO: check how to setup this on ASIO
  113. ? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency
  114. : 0;
  115. inputParameters.hostApiSpecificStreamInfo = NULL;
  116. outputParameters.device = outputDevice;
  117. outputParameters.channelCount = fPlaybackChannels;
  118. outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
  119. outputParameters.suggestedLatency = (outputDevice != paNoDevice) // TODO: check how to setup this on ASIO
  120. ? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency
  121. : 0;
  122. outputParameters.hostApiSpecificStreamInfo = NULL;
  123. err = Pa_OpenStream(&fStream,
  124. (inputDevice == paNoDevice) ? 0 : &inputParameters,
  125. (outputDevice == paNoDevice) ? 0 : &outputParameters,
  126. fSampleRate,
  127. fBufferSize,
  128. paNoFlag, // Clipping is on...
  129. Render,
  130. this);
  131. if (err != paNoError) {
  132. jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
  133. goto error;
  134. }
  135. err = Pa_StartStream(fStream);
  136. if (err != paNoError) {
  137. jack_error("Pa_StartStream error = %s", Pa_GetErrorText(err));
  138. goto error;
  139. }
  140. jack_log("JackPortAudioIOAdapter::Open OK");
  141. return 0;
  142. error:
  143. Pa_Terminate();
  144. return -1;
  145. }
  146. int JackPortAudioIOAdapter::Close()
  147. {
  148. jack_log("JackPortAudioIOAdapter::Close");
  149. Pa_StopStream(fStream);
  150. jack_log("JackPortAudioIOAdapter:: Pa_StopStream");
  151. Pa_CloseStream(fStream);
  152. jack_log("JackPortAudioIOAdapter:: Pa_CloseStream");
  153. Pa_Terminate();
  154. jack_log("JackPortAudioIOAdapter:: Pa_Terminate");
  155. return JackIOAdapterInterface::Close();
  156. }
  157. void JackPortAudioIOAdapter::SetBufferSize(int buffer_size)
  158. {
  159. JackIOAdapterInterface::SetBufferSize(buffer_size);
  160. Close();
  161. Open();
  162. }
  163. } // namespace