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.

252 lines
10KB

  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 "JackPortAudioAdapter.h"
  16. #include "JackError.h"
  17. namespace Jack
  18. {
  19. int JackPortAudioAdapter::Render(const void* inputBuffer,
  20. void* outputBuffer,
  21. unsigned long framesPerBuffer,
  22. const PaStreamCallbackTimeInfo* timeInfo,
  23. PaStreamCallbackFlags statusFlags,
  24. void* userData)
  25. {
  26. static_cast<JackPortAudioAdapter*>(userData)->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, framesPerBuffer);
  27. return paContinue;
  28. }
  29. JackPortAudioAdapter::JackPortAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
  30. : JackAudioAdapterInterface(buffer_size, sample_rate)
  31. {
  32. jack_log("JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate);
  33. const JSList* node;
  34. const jack_driver_param_t* param;
  35. int in_max = 0;
  36. int out_max = 0;
  37. fInputDevice = Pa_GetDefaultInputDevice();
  38. fOutputDevice = Pa_GetDefaultOutputDevice();
  39. for (node = params; node; node = jack_slist_next(node)) {
  40. param = (const jack_driver_param_t*) node->data;
  41. switch (param->character)
  42. {
  43. case 'i' :
  44. fCaptureChannels = param->value.ui;
  45. break;
  46. case 'o' :
  47. fPlaybackChannels = param->value.ui;
  48. break;
  49. case 'C' :
  50. if (fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0) {
  51. jack_error("Can't use %s, taking default input device", param->value.str);
  52. fInputDevice = Pa_GetDefaultInputDevice();
  53. }
  54. break;
  55. case 'P' :
  56. if (fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0) {
  57. jack_error("Can't use %s, taking default output device", param->value.str);
  58. fOutputDevice = Pa_GetDefaultOutputDevice();
  59. }
  60. break;
  61. case 'r' :
  62. SetAdaptedSampleRate(param->value.ui);
  63. break;
  64. case 'p' :
  65. SetAdaptedBufferSize(param->value.ui);
  66. break;
  67. case 'd' :
  68. if (fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0)
  69. jack_error("Can't use %s, taking default input device", param->value.str);
  70. if (fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0)
  71. jack_error("Can't use %s, taking default output device", param->value.str);
  72. break;
  73. case 'l' :
  74. fPaDevices.DisplayDevicesNames();
  75. break;
  76. case 'q':
  77. fQuality = param->value.ui;
  78. break;
  79. case 'g':
  80. fRingbufferCurSize = param->value.ui;
  81. fAdaptative = false;
  82. break;
  83. case 'R':
  84. fResampleRatioPerChannel = true;
  85. break;
  86. }
  87. }
  88. //max channels
  89. if (in_max == 0 && fInputDevice != paNoDevice)
  90. in_max = fPaDevices.GetDeviceInfo(fInputDevice)->maxInputChannels;
  91. if (out_max == 0 && fOutputDevice != paNoDevice)
  92. out_max = fPaDevices.GetDeviceInfo(fOutputDevice)->maxOutputChannels;
  93. //effective channels
  94. if ((fCaptureChannels == 0) || (fCaptureChannels > in_max))
  95. fCaptureChannels = in_max;
  96. if ((fPlaybackChannels == 0) || (fPlaybackChannels > out_max))
  97. fPlaybackChannels = out_max;
  98. //set adapter interface channels
  99. SetInputs(fCaptureChannels);
  100. SetOutputs(fPlaybackChannels);
  101. }
  102. int JackPortAudioAdapter::Open()
  103. {
  104. PaError err;
  105. PaStreamParameters inputParameters;
  106. PaStreamParameters outputParameters;
  107. if (fInputDevice == paNoDevice && fOutputDevice == paNoDevice) {
  108. jack_error("No input and output device!!");
  109. return -1;
  110. }
  111. jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str());
  112. jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str());
  113. jack_log("JackPortAudioAdapter::Open fAdaptedBufferSize = %u fAdaptedSampleRate %u", fAdaptedBufferSize, fAdaptedSampleRate);
  114. inputParameters.device = fInputDevice;
  115. inputParameters.channelCount = fCaptureChannels;
  116. inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
  117. inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO
  118. ? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency
  119. : 0;
  120. inputParameters.hostApiSpecificStreamInfo = NULL;
  121. outputParameters.device = fOutputDevice;
  122. outputParameters.channelCount = fPlaybackChannels;
  123. outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
  124. outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO
  125. ? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency
  126. : 0;
  127. outputParameters.hostApiSpecificStreamInfo = NULL;
  128. err = Pa_OpenStream( &fStream,
  129. (fInputDevice == paNoDevice) ? 0 : &inputParameters,
  130. (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
  131. fAdaptedSampleRate,
  132. fAdaptedBufferSize,
  133. paNoFlag, // Clipping is on...
  134. Render,
  135. this);
  136. if (err != paNoError) {
  137. jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
  138. return -1;
  139. }
  140. err = Pa_StartStream(fStream);
  141. if (err != paNoError) {
  142. jack_error("Pa_StartStream error = %s", Pa_GetErrorText(err));
  143. return -1;
  144. }
  145. jack_log("JackPortAudioAdapter::Open OK");
  146. return 0;
  147. }
  148. int JackPortAudioAdapter::Close()
  149. {
  150. #ifdef JACK_MONITOR
  151. fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
  152. #endif
  153. jack_log("JackPortAudioAdapter::Close");
  154. Pa_StopStream(fStream);
  155. jack_log("JackPortAudioAdapter:: Pa_StopStream");
  156. Pa_CloseStream(fStream);
  157. jack_log("JackPortAudioAdapter:: Pa_CloseStream");
  158. return 0;
  159. }
  160. int JackPortAudioAdapter::SetSampleRate(jack_nframes_t sample_rate)
  161. {
  162. JackAudioAdapterInterface::SetHostSampleRate(sample_rate);
  163. Close();
  164. return Open();
  165. }
  166. int JackPortAudioAdapter::SetBufferSize(jack_nframes_t buffer_size)
  167. {
  168. JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
  169. Close();
  170. return Open();
  171. }
  172. } // namespace
  173. #ifdef __cplusplus
  174. extern "C"
  175. {
  176. #endif
  177. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  178. {
  179. jack_driver_desc_t * desc;
  180. jack_driver_desc_filler_t filler;
  181. jack_driver_param_value_t value;
  182. desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler);
  183. value.ui = 0;
  184. jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamUInt, &value, NULL, "Maximum number of input channels", NULL);
  185. jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamUInt, &value, NULL, "Maximum number of output channels", NULL);
  186. jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set PortAudio device name", NULL);
  187. jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Provide playback ports. Optionally set PortAudio device name", NULL);
  188. value.ui = 44100U;
  189. jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
  190. value.ui = 512U;
  191. jack_driver_descriptor_add_parameter(desc, &filler, "periodsize", 'p', JackDriverParamUInt, &value, NULL, "Period size", NULL);
  192. jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "PortAudio device name", NULL);
  193. value.i = true;
  194. jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available PortAudio devices", NULL);
  195. value.ui = 0;
  196. jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamUInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
  197. value.ui = 32768;
  198. jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamUInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
  199. value.i = false;
  200. jack_driver_descriptor_add_parameter(desc, &filler, "multi-ratios", 'R', JackDriverParamBool, &value, NULL, "Calculate resample ratio per channel"
  201. , "Calculate resample ratio per channel in case of repeated ringbuffer errors because of clock drift between the channels from the same device.");
  202. return desc;
  203. }
  204. #ifdef __cplusplus
  205. }
  206. #endif