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.

146 lines
5.4KB

  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. char* buffer;
  29. jack_log("JackPortAudioIOAdapter::Render");
  30. paBuffer = (float**)inputBuffer;
  31. for (int i = 0; i < adapter->fCaptureChannels; i++) {
  32. buffer = (char*)paBuffer[i];
  33. size_t len = jack_ringbuffer_read_space(adapter->fCaptureRingBuffer);
  34. if (len < framesPerBuffer * sizeof(float)) {
  35. jack_error("JackPortAudioIOAdapter::Process : producer too slow, skip frames...");
  36. jack_ringbuffer_read(adapter->fCaptureRingBuffer, buffer, len);
  37. } else {
  38. jack_ringbuffer_read(adapter->fCaptureRingBuffer, buffer, framesPerBuffer * sizeof(float));
  39. }
  40. }
  41. paBuffer = (float**)outputBuffer;
  42. for (int i = 0; i < adapter->fPlaybackChannels; i++) {
  43. buffer = (char*)paBuffer[i];
  44. size_t len = jack_ringbuffer_write_space(adapter->fPlaybackRingBuffer);
  45. if (len < framesPerBuffer * sizeof(float)) {
  46. jack_error("JackPortAudioIOAdapter::Process : consumer too slow, skip frames...");
  47. jack_ringbuffer_write(adapter->fPlaybackRingBuffer, buffer, len);
  48. } else {
  49. jack_ringbuffer_write(adapter->fPlaybackRingBuffer, buffer, framesPerBuffer * sizeof(float));
  50. }
  51. }
  52. return paContinue;
  53. }
  54. int JackPortAudioIOAdapter::Open()
  55. {
  56. PaError err;
  57. PaStreamParameters inputParameters;
  58. PaStreamParameters outputParameters;
  59. PaDeviceIndex inputDevice;
  60. PaDeviceIndex outputDevice;
  61. err = Pa_Initialize();
  62. if (err != paNoError) {
  63. jack_error("JackPortAudioIOAdapter::Pa_Initialize error = %s\n", Pa_GetErrorText(err));
  64. goto error;
  65. }
  66. jack_log("JackPortAudioIOAdapter::Pa_GetDefaultInputDevice %ld", Pa_GetDefaultInputDevice());
  67. jack_log("JackPortAudioIOAdapter::Pa_GetDefaultOutputDevice %ld", Pa_GetDefaultOutputDevice());
  68. jack_log("JackPortAudioIOAdapter::Open fBufferSize = %ld fSampleRate %f", fBufferSize, fSampleRate);
  69. inputDevice = Pa_GetDefaultInputDevice();
  70. outputDevice = Pa_GetDefaultOutputDevice();
  71. inputParameters.device = inputDevice;
  72. inputParameters.channelCount = fCaptureChannels;
  73. inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
  74. inputParameters.suggestedLatency = (inputDevice != paNoDevice) // TODO: check how to setup this on ASIO
  75. ? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency
  76. : 0;
  77. inputParameters.hostApiSpecificStreamInfo = NULL;
  78. outputParameters.device = outputDevice;
  79. outputParameters.channelCount = fPlaybackChannels;
  80. outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
  81. outputParameters.suggestedLatency = (outputDevice != paNoDevice) // TODO: check how to setup this on ASIO
  82. ? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency
  83. : 0;
  84. outputParameters.hostApiSpecificStreamInfo = NULL;
  85. err = Pa_OpenStream(&fStream,
  86. (inputDevice == paNoDevice) ? 0 : &inputParameters,
  87. (outputDevice == paNoDevice) ? 0 : &outputParameters,
  88. fSampleRate,
  89. fBufferSize,
  90. paNoFlag, // Clipping is on...
  91. Render,
  92. this);
  93. if (err != paNoError) {
  94. jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
  95. goto error;
  96. }
  97. err = Pa_StartStream(fStream);
  98. if (err != paNoError) {
  99. jack_error("Pa_StartStream error = %s", Pa_GetErrorText(err));
  100. goto error;
  101. }
  102. jack_log("JackPortAudioIOAdapter::Open OK");
  103. return 0;
  104. error:
  105. Pa_Terminate();
  106. return -1;
  107. }
  108. int JackPortAudioIOAdapter::Close()
  109. {
  110. jack_log("JackPortAudioIOAdapter::Close");
  111. Pa_StopStream(fStream);
  112. jack_log("JackPortAudioIOAdapter:: Pa_StopStream");
  113. Pa_CloseStream(fStream);
  114. jack_log("JackPortAudioIOAdapter:: Pa_CloseStream");
  115. Pa_Terminate();
  116. jack_log("JackPortAudioIOAdapter:: Pa_Terminate");
  117. return 0;
  118. }
  119. } // namespace