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.

191 lines
7.3KB

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