jack1 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.

467 lines
16KB

  1. /*
  2. Copyright © Grame 2003
  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. Grame Research Laboratory, 9, rue du Garet 69001 Lyon - France
  15. grame@rd.grame.fr
  16. */
  17. #include <stdio.h>
  18. #include <jack/engine.h>
  19. #include "portaudio_driver.h"
  20. static int
  21. paCallback(void *inputBuffer, void *outputBuffer,
  22. unsigned long framesPerBuffer,
  23. PaTimestamp outTime, void *userData)
  24. {
  25. portaudio_driver_t * driver = (portaudio_driver_t*)userData;
  26. driver->inPortAudio = (float*)inputBuffer;
  27. driver->outPortAudio = (float*)outputBuffer;
  28. return driver->engine->run_cycle(driver->engine, framesPerBuffer, 0);
  29. }
  30. static int
  31. portaudio_driver_attach (portaudio_driver_t *driver, jack_engine_t *engine)
  32. {
  33. jack_port_t *port;
  34. int port_flags;
  35. channel_t chn;
  36. char buf[32];
  37. driver->engine = engine;
  38. driver->engine->set_buffer_size (engine, driver->frames_per_cycle);
  39. driver->engine->set_sample_rate (engine, driver->frame_rate);
  40. port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal;
  41. /*
  42. if (driver->has_hw_monitoring) {
  43. port_flags |= JackPortCanMonitor;
  44. }
  45. */
  46. for (chn = 0; chn < driver->capture_nchannels; chn++) {
  47. snprintf (buf, sizeof(buf) - 1, "capture_%lu", chn+1);
  48. if ((port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0)) == NULL) {
  49. jack_error ("portaudio: cannot register port for %s", buf);
  50. break;
  51. }
  52. /* XXX fix this so that it can handle: systemic (external) latency
  53. */
  54. jack_port_set_latency (port, driver->frames_per_cycle);
  55. driver->capture_ports = jack_slist_append (driver->capture_ports, port);
  56. }
  57. port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal;
  58. for (chn = 0; chn < driver->playback_nchannels; chn++) {
  59. snprintf (buf, sizeof(buf) - 1, "playback_%lu", chn+1);
  60. if ((port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0)) == NULL) {
  61. jack_error ("portaudio: cannot register port for %s", buf);
  62. break;
  63. }
  64. /* XXX fix this so that it can handle: systemic (external) latency
  65. */
  66. jack_port_set_latency (port, driver->frames_per_cycle);
  67. driver->playback_ports = jack_slist_append (driver->playback_ports, port);
  68. }
  69. jack_activate (driver->client);
  70. return 0;
  71. }
  72. static int
  73. portaudio_driver_detach (portaudio_driver_t *driver, jack_engine_t *engine)
  74. {
  75. JSList *node;
  76. if (driver->engine == 0) {
  77. return -1;
  78. }
  79. for (node = driver->capture_ports; node; node = jack_slist_next (node)) {
  80. jack_port_unregister (driver->client, ((jack_port_t *) node->data));
  81. }
  82. jack_slist_free (driver->capture_ports);
  83. driver->capture_ports = 0;
  84. for (node = driver->playback_ports; node; node = jack_slist_next (node)) {
  85. jack_port_unregister (driver->client, ((jack_port_t *) node->data));
  86. }
  87. jack_slist_free (driver->playback_ports);
  88. driver->playback_ports = 0;
  89. driver->engine = 0;
  90. return 0;
  91. }
  92. static jack_nframes_t
  93. portaudio_driver_wait (portaudio_driver_t *driver, int extra_fd, int *status, float *delayed_usecs)
  94. {
  95. *status = 0;
  96. *delayed_usecs = 0;
  97. return driver->frames_per_cycle;
  98. }
  99. static int
  100. portaudio_driver_null_cycle (portaudio_driver_t* driver, jack_nframes_t nframes)
  101. {
  102. memset(driver->outPortAudio, 0, (driver->playback_nchannels * nframes * sizeof(float)));
  103. return 0;
  104. }
  105. static int
  106. portaudio_driver_read (portaudio_driver_t *driver, jack_nframes_t nframes)
  107. {
  108. jack_default_audio_sample_t *buf;
  109. channel_t chn;
  110. jack_port_t *port;
  111. JSList *node;
  112. int i;
  113. for (chn = 0, node = driver->capture_ports; node; node = jack_slist_next (node), chn++) {
  114. port = (jack_port_t *)node->data;
  115. if (jack_port_connected (port) && (driver->inPortAudio != NULL)) {
  116. buf = jack_port_get_buffer (port, nframes);
  117. int channels = driver->capture_nchannels;
  118. float* in = driver->inPortAudio;
  119. for (i = 0; i< nframes; i++) buf[i] = in[channels*i+chn];
  120. }
  121. }
  122. driver->engine->transport_cycle_start (driver->engine,
  123. jack_get_microseconds ());
  124. return 0;
  125. }
  126. static int
  127. portaudio_driver_write (portaudio_driver_t *driver, jack_nframes_t nframes)
  128. {
  129. jack_default_audio_sample_t *buf;
  130. channel_t chn;
  131. jack_port_t *port;
  132. JSList *node;
  133. int i;
  134. /* Clear in case of nothing is connected */
  135. memset(driver->outPortAudio, 0, (driver->playback_nchannels * nframes * sizeof(float)));
  136. for (chn = 0, node = driver->playback_ports; node; node = jack_slist_next (node), chn++) {
  137. port = (jack_port_t *)node->data;
  138. if (jack_port_connected (port) && (driver->outPortAudio != NULL)) {
  139. buf = jack_port_get_buffer (port, nframes);
  140. int channels = driver->playback_nchannels;
  141. float* out = driver->outPortAudio;
  142. for (i = 0; i< nframes; i++) out[channels*i+chn] = buf[i];
  143. }
  144. }
  145. return 0;
  146. }
  147. static int
  148. portaudio_driver_audio_start (portaudio_driver_t *driver)
  149. {
  150. PaError err = Pa_StartStream(driver->stream);
  151. return (err != paNoError) ? -1 : 0;
  152. }
  153. static int
  154. portaudio_driver_audio_stop (portaudio_driver_t *driver)
  155. {
  156. PaError err = Pa_StopStream(driver->stream);
  157. return (err != paNoError) ? -1 : 0;
  158. }
  159. //== instance creation/destruction =============================================
  160. /** create a new driver instance
  161. */
  162. static jack_driver_t *
  163. portaudio_driver_new (char *name,
  164. jack_client_t* client,
  165. jack_nframes_t frames_per_cycle,
  166. jack_nframes_t rate,
  167. int capturing,
  168. int playing,
  169. int chan,
  170. DitherAlgorithm dither)
  171. {
  172. portaudio_driver_t *driver;
  173. PaError err;
  174. const PaDeviceInfo *pdi;
  175. int numDevices;
  176. int i,j;
  177. printf ("creating portaudio driver ... %lu|%lu|%lu\n", frames_per_cycle, rate);
  178. driver = (portaudio_driver_t *) calloc (1, sizeof (portaudio_driver_t));
  179. jack_driver_init ((jack_driver_t *) driver);
  180. driver->frame_rate = rate;
  181. driver->frames_per_cycle = frames_per_cycle;
  182. driver->attach = (JackDriverAttachFunction) portaudio_driver_attach;
  183. driver->detach = (JackDriverDetachFunction) portaudio_driver_detach;
  184. driver->wait = (JackDriverWaitFunction) portaudio_driver_wait;
  185. driver->read = (JackDriverReadFunction) portaudio_driver_read;
  186. driver->write = (JackDriverReadFunction) portaudio_driver_write;
  187. driver->null_cycle = (JackDriverNullCycleFunction) portaudio_driver_null_cycle;
  188. driver->start = (JackDriverStartFunction) portaudio_driver_audio_start;
  189. driver->stop = (JackDriverStopFunction) portaudio_driver_audio_stop;
  190. err = Pa_Initialize();
  191. numDevices = Pa_CountDevices();
  192. if( numDevices < 0 )
  193. {
  194. printf("ERROR: Pa_CountDevices returned 0x%x\n", numDevices );
  195. err = numDevices;
  196. goto error;
  197. }
  198. printf("Number of devices = %d\n", numDevices );
  199. for( i=0; i<numDevices; i++ )
  200. {
  201. pdi = Pa_GetDeviceInfo( i );
  202. printf("---------------------------------------------- #%d", i );
  203. if( i == Pa_GetDefaultInputDeviceID() ) {
  204. driver->capture_nchannels = (capturing) ? pdi->maxInputChannels : 0;
  205. }
  206. if( i == Pa_GetDefaultOutputDeviceID() ){
  207. driver->playback_nchannels = (playing) ? pdi->maxOutputChannels : 0;
  208. }
  209. printf("\nName = %s\n", pdi->name);
  210. printf("Max Inputs = %d ", pdi->maxInputChannels);
  211. printf("Max Outputs = %d\n", pdi->maxOutputChannels);
  212. if( pdi->numSampleRates == -1 ){
  213. printf("Sample Rate Range = %f to %f\n", pdi->sampleRates[0], pdi->sampleRates[1] );
  214. }else{
  215. printf("Sample Rates =");
  216. for(j=0; j<pdi->numSampleRates; j++){
  217. printf(" %8.2f,", pdi->sampleRates[j] );
  218. }
  219. printf("\n");
  220. }
  221. printf("Native Sample Formats = ");
  222. if( pdi->nativeSampleFormats & paInt8 ) printf("paInt8, ");
  223. if( pdi->nativeSampleFormats & paUInt8 ) printf("paUInt8, ");
  224. if( pdi->nativeSampleFormats & paInt16 ) printf("paInt16, ");
  225. if( pdi->nativeSampleFormats & paInt32 ) printf("paInt32, ");
  226. if( pdi->nativeSampleFormats & paFloat32 ) printf("paFloat32, ");
  227. if( pdi->nativeSampleFormats & paInt24 ) printf("paInt24, ");
  228. if( pdi->nativeSampleFormats & paPackedInt24 ) printf("paPackedInt24, ");
  229. printf("\n");
  230. }
  231. if(err != paNoError) goto error;
  232. printf("Pa_GetDefaultOutputDeviceID() %ld\n", Pa_GetDefaultOutputDeviceID());
  233. printf("Pa_GetDefaultInputDeviceID() %ld\n", Pa_GetDefaultInputDeviceID());
  234. if (chan > 0) {
  235. driver->capture_nchannels = (driver->capture_nchannels < chan) ? driver->capture_nchannels : chan;
  236. driver->playback_nchannels = (driver->playback_nchannels < chan) ? driver->playback_nchannels : chan;
  237. }
  238. err = Pa_OpenStream(&driver->stream,
  239. ((capturing) ? Pa_GetDefaultInputDeviceID() : paNoDevice),
  240. ((capturing) ? driver->capture_nchannels : 0),
  241. paFloat32, /* 32 bit floating point input */
  242. NULL,
  243. ((playing) ? Pa_GetDefaultOutputDeviceID() : paNoDevice),
  244. ((playing) ? driver->playback_nchannels : 0),
  245. paFloat32, /* 32 bit floating point output */
  246. NULL,
  247. rate,
  248. frames_per_cycle, /* frames per buffer */
  249. 0, /* number of buffers, if zero then use default minimum */
  250. paClipOff, /* we won't output out of range samples so don't bother clipping them */
  251. paCallback,
  252. driver);
  253. if (err != paNoError) goto error;
  254. driver->client = client;
  255. driver->period_usecs = (((float) driver->frames_per_cycle) / driver->frame_rate) * 1000000.0f;
  256. jack_init_time();
  257. return((jack_driver_t *) driver);
  258. error:
  259. Pa_Terminate();
  260. fprintf(stderr, "An error occured while using the portaudio stream\n");
  261. fprintf(stderr, "Error number: %d\n", err);
  262. fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
  263. free(driver);
  264. return NULL;
  265. }
  266. /** free all memory allocated by a driver instance
  267. */
  268. static void
  269. portaudio_driver_delete (portaudio_driver_t *driver)
  270. {
  271. /* Close PortAudio stream and terminate */
  272. Pa_CloseStream(driver->stream);
  273. Pa_Terminate();
  274. free(driver);
  275. }
  276. //== driver "plugin" interface =================================================
  277. /* DRIVER "PLUGIN" INTERFACE */
  278. const char driver_client_name[] = "portaudio";
  279. static void
  280. portaudio_usage ()
  281. {
  282. fprintf (stderr, "\n"
  283. "portaudio PCM driver args:\n"
  284. " -r sample-rate (default: 44.1kHz)\n"
  285. " -c chan (default: harware)\n"
  286. " -p frames-per-period (default: 128)\n"
  287. " -D (duplex, default: yes)\n"
  288. " -C (capture, default: duplex)\n"
  289. " -P (playback, default: duplex)\n"
  290. " -z[r|t|s|-] (dither, rect|tri|shaped|off, default: off)\n"
  291. );
  292. }
  293. jack_driver_t *
  294. driver_initialize (jack_client_t *client, int argc, char **argv)
  295. {
  296. jack_nframes_t srate = 44100;
  297. jack_nframes_t frames_per_interrupt = 128;
  298. int capture = FALSE;
  299. int playback = FALSE;
  300. int chan = -1;
  301. DitherAlgorithm dither = None;
  302. int i;
  303. for (i = 1; i < argc; i++) {
  304. if (argv[i][0] == '-') {
  305. switch (argv[i][1]) {
  306. case 'D':
  307. capture = TRUE;
  308. playback = TRUE;
  309. break;
  310. case 'c':
  311. chan = atoi (argv[i+1]);
  312. i++;
  313. break;
  314. case 'C':
  315. capture = TRUE;
  316. break;
  317. case 'P':
  318. playback = TRUE;
  319. break;
  320. case 'r':
  321. srate = atoi (argv[i+1]);
  322. i++;
  323. break;
  324. case 'p':
  325. frames_per_interrupt = atoi (argv[i+1]);
  326. i++;
  327. break;
  328. case 'z':
  329. switch (argv[i][2]) {
  330. case '-':
  331. dither = None;
  332. break;
  333. case 'r':
  334. dither = Rectangular;
  335. break;
  336. case 's':
  337. dither = Shaped;
  338. break;
  339. case 't':
  340. default:
  341. dither = Triangular;
  342. break;
  343. }
  344. break;
  345. default:
  346. portaudio_usage ();
  347. return NULL;
  348. }
  349. } else {
  350. portaudio_usage ();
  351. return NULL;
  352. }
  353. }
  354. /* duplex is the default */
  355. if (!capture && !playback) {
  356. capture = TRUE;
  357. playback = TRUE;
  358. }
  359. return portaudio_driver_new ("portaudio", client, frames_per_interrupt, srate, capture, playback, chan, dither);
  360. }
  361. void
  362. driver_finish (jack_driver_t *driver)
  363. {
  364. portaudio_driver_delete ((portaudio_driver_t *) driver);
  365. }