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.

552 lines
22KB

  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. #ifndef __JackAlsaIOAdapter__
  16. #define __JackAlsaIOAdapter__
  17. #include <math.h>
  18. #include <limits.h>
  19. #include <alsa/asoundlib.h>
  20. #include "JackIOAdapter.h"
  21. #include "JackPlatformThread.h"
  22. #include "jack.h"
  23. #include "JackError.h"
  24. namespace Jack
  25. {
  26. //inline void* aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb * size) + 15, sizeof(char))) + 15 & ~15); }
  27. inline void* aligned_calloc(size_t nmemb, size_t size) { return (void*)calloc(nmemb, size); }
  28. #define max(x,y) (((x)>(y)) ? (x) : (y))
  29. #define min(x,y) (((x)<(y)) ? (x) : (y))
  30. #define check_error(err) if (err) { jack_error("%s:%d, alsa error %d : %s", __FILE__, __LINE__, err, snd_strerror(err)); return err; }
  31. #define check_error_msg(err,msg) if (err) { jack_error("%s:%d, %s : %s(%d)", __FILE__, __LINE__, msg, snd_strerror(err), err); return err; }
  32. #define display_error_msg(err,msg) if (err) { jack_error("%s:%d, %s : %s(%d)", __FILE__, __LINE__, msg, snd_strerror(err), err); }
  33. /**
  34. * A convenient class to pass parameters to AudioInterface
  35. */
  36. class AudioParam
  37. {
  38. public:
  39. const char* fCardName;
  40. unsigned int fFrequency;
  41. int fBuffering;
  42. unsigned int fSoftInputs;
  43. unsigned int fSoftOutputs;
  44. public:
  45. AudioParam() :
  46. fCardName("hw:0"),
  47. fFrequency(44100),
  48. fBuffering(512),
  49. fSoftInputs(2),
  50. fSoftOutputs(2)
  51. {}
  52. AudioParam(int input, int output, jack_nframes_t buffer_size, jack_nframes_t sample_rate) :
  53. fCardName("hw:0"),
  54. fFrequency(sample_rate),
  55. fBuffering(buffer_size),
  56. fSoftInputs(input),
  57. fSoftOutputs(output)
  58. {}
  59. AudioParam& cardName(const char* n) { fCardName = n; return *this; }
  60. AudioParam& frequency(int f) { fFrequency = f; return *this; }
  61. AudioParam& buffering(int fpb) { fBuffering = fpb; return *this; }
  62. AudioParam& inputs(int n) { fSoftInputs = n; return *this; }
  63. AudioParam& outputs(int n) { fSoftOutputs = n; return *this; }
  64. };
  65. /**
  66. * An ALSA audio interface
  67. */
  68. class AudioInterface : public AudioParam
  69. {
  70. public:
  71. snd_pcm_t* fOutputDevice;
  72. snd_pcm_t* fInputDevice;
  73. snd_pcm_hw_params_t* fInputParams;
  74. snd_pcm_hw_params_t* fOutputParams;
  75. snd_pcm_format_t fSampleFormat;
  76. snd_pcm_access_t fSampleAccess;
  77. unsigned int fCardInputs;
  78. unsigned int fCardOutputs;
  79. unsigned int fChanInputs;
  80. unsigned int fChanOutputs;
  81. // interleaved mode audiocard buffers
  82. void* fInputCardBuffer;
  83. void* fOutputCardBuffer;
  84. // non interleaved mode audiocard buffers
  85. void* fInputCardChannels[256];
  86. void* fOutputCardChannels[256];
  87. // non interleaved mod, floating point software buffers
  88. float* fInputSoftChannels[256];
  89. float* fOutputSoftChannels[256];
  90. public:
  91. const char* cardName() { return fCardName; }
  92. int frequency() { return fFrequency; }
  93. int buffering() { return fBuffering; }
  94. float** inputSoftChannels() { return fInputSoftChannels; }
  95. float** outputSoftChannels() { return fOutputSoftChannels; }
  96. AudioInterface(const AudioParam& ap = AudioParam()) : AudioParam(ap)
  97. {
  98. fInputDevice = 0;
  99. fOutputDevice = 0;
  100. fInputParams = 0;
  101. fOutputParams = 0;
  102. }
  103. AudioInterface(int input, int output, jack_nframes_t buffer_size, jack_nframes_t sample_rate) :
  104. AudioParam(input, output, buffer_size, sample_rate)
  105. {
  106. fInputCardBuffer = 0;
  107. fOutputCardBuffer = 0;
  108. for (int i = 0; i < 256; i++) {
  109. fInputCardChannels[i] = 0;
  110. fOutputCardChannels[i] = 0;
  111. fInputSoftChannels[i] = 0;
  112. fOutputSoftChannels[i] = 0;
  113. }
  114. }
  115. /**
  116. * Open the audio interface
  117. */
  118. int open()
  119. {
  120. int err;
  121. // allocation d'un stream d'entree et d'un stream de sortie
  122. err = snd_pcm_open(&fInputDevice, fCardName, SND_PCM_STREAM_CAPTURE, 0); check_error(err)
  123. err = snd_pcm_open(&fOutputDevice, fCardName, SND_PCM_STREAM_PLAYBACK, 0); check_error(err)
  124. // recherche des parametres d'entree
  125. err = snd_pcm_hw_params_malloc(&fInputParams); check_error(err);
  126. setAudioParams(fInputDevice, fInputParams);
  127. snd_pcm_hw_params_get_channels(fInputParams, &fCardInputs);
  128. // recherche des parametres de sortie
  129. err = snd_pcm_hw_params_malloc(&fOutputParams); check_error(err)
  130. setAudioParams(fOutputDevice, fOutputParams);
  131. snd_pcm_hw_params_get_channels(fOutputParams, &fCardOutputs);
  132. jack_info("inputs : %ud, outputs : %ud", fCardInputs, fCardOutputs);
  133. // enregistrement des parametres d'entree-sortie
  134. err = snd_pcm_hw_params(fInputDevice, fInputParams); check_error (err);
  135. err = snd_pcm_hw_params(fOutputDevice, fOutputParams); check_error (err);
  136. //assert(snd_pcm_hw_params_get_period_size(fInputParams,NULL) == snd_pcm_hw_params_get_period_size(fOutputParams,NULL));
  137. // allocation of alsa buffers
  138. if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) {
  139. fInputCardBuffer = aligned_calloc(interleavedBufferSize(fInputParams), 1);
  140. fOutputCardBuffer = aligned_calloc(interleavedBufferSize(fOutputParams), 1);
  141. } else {
  142. for (unsigned int i = 0; i < fCardInputs; i++) {
  143. fInputCardChannels[i] = aligned_calloc(noninterleavedBufferSize(fInputParams), 1);
  144. }
  145. for (unsigned int i = 0; i < fCardOutputs; i++) {
  146. fOutputCardChannels[i] = aligned_calloc(noninterleavedBufferSize(fOutputParams), 1);
  147. }
  148. }
  149. // allocation of floating point buffers needed by the dsp code
  150. fChanInputs = max(fSoftInputs, fCardInputs); assert (fChanInputs < 256);
  151. fChanOutputs = max(fSoftOutputs, fCardOutputs); assert (fChanOutputs < 256);
  152. for (unsigned int i = 0; i < fChanInputs; i++) {
  153. fInputSoftChannels[i] = (float*) aligned_calloc (fBuffering, sizeof(float));
  154. for (int j = 0; j < fBuffering; j++) {
  155. fInputSoftChannels[i][j] = 0.0;
  156. }
  157. }
  158. for (unsigned int i = 0; i < fChanOutputs; i++) {
  159. fOutputSoftChannels[i] = (float*) aligned_calloc (fBuffering, sizeof(float));
  160. for (int j = 0; j < fBuffering; j++) {
  161. fOutputSoftChannels[i][j] = 0.0;
  162. }
  163. }
  164. return 0;
  165. }
  166. int close()
  167. {
  168. snd_pcm_hw_params_free(fInputParams);
  169. snd_pcm_hw_params_free(fOutputParams);
  170. snd_pcm_close(fInputDevice);
  171. snd_pcm_close(fOutputDevice);
  172. for (unsigned int i = 0; i < fChanInputs; i++) {
  173. if (fInputSoftChannels[i])
  174. free(fInputSoftChannels[i]);
  175. }
  176. for (unsigned int i = 0; i < fChanOutputs; i++) {
  177. if (fOutputSoftChannels[i])
  178. free(fOutputSoftChannels[i]);
  179. }
  180. for (unsigned int i = 0; i < fCardInputs; i++) {
  181. if (fInputCardChannels[i])
  182. free(fInputCardChannels[i]);
  183. }
  184. for (unsigned int i = 0; i < fCardOutputs; i++) {
  185. if (fOutputCardChannels[i])
  186. free(fOutputCardChannels[i]);
  187. }
  188. if (fInputCardBuffer)
  189. free(fInputCardBuffer);
  190. if (fOutputCardBuffer)
  191. free(fOutputCardBuffer);
  192. return 0;
  193. }
  194. int setAudioParams(snd_pcm_t* stream, snd_pcm_hw_params_t* params)
  195. {
  196. int err;
  197. // set params record with initial values
  198. err = snd_pcm_hw_params_any ( stream, params );
  199. check_error_msg(err, "unable to init parameters")
  200. // set alsa access mode (and fSampleAccess field) either to non interleaved or interleaved
  201. err = snd_pcm_hw_params_set_access (stream, params, SND_PCM_ACCESS_RW_NONINTERLEAVED );
  202. if (err) {
  203. err = snd_pcm_hw_params_set_access (stream, params, SND_PCM_ACCESS_RW_INTERLEAVED );
  204. check_error_msg(err, "unable to set access mode neither to non-interleaved or to interleaved");
  205. }
  206. snd_pcm_hw_params_get_access(params, &fSampleAccess);
  207. // search for 32-bits or 16-bits format
  208. err = snd_pcm_hw_params_set_format (stream, params, SND_PCM_FORMAT_S32);
  209. if (err) {
  210. err = snd_pcm_hw_params_set_format (stream, params, SND_PCM_FORMAT_S16);
  211. check_error_msg(err, "unable to set format to either 32-bits or 16-bits");
  212. }
  213. snd_pcm_hw_params_get_format(params, &fSampleFormat);
  214. // set sample frequency
  215. snd_pcm_hw_params_set_rate_near (stream, params, &fFrequency, 0);
  216. // set period and period size (buffering)
  217. err = snd_pcm_hw_params_set_period_size (stream, params, fBuffering, 0);
  218. check_error_msg(err, "period size not available");
  219. err = snd_pcm_hw_params_set_periods (stream, params, 2, 0);
  220. check_error_msg(err, "number of periods not available");
  221. return 0;
  222. }
  223. ssize_t interleavedBufferSize(snd_pcm_hw_params_t* params)
  224. {
  225. _snd_pcm_format format; snd_pcm_hw_params_get_format(params, &format);
  226. snd_pcm_uframes_t psize; snd_pcm_hw_params_get_period_size(params, &psize, NULL);
  227. unsigned int channels; snd_pcm_hw_params_get_channels(params, &channels);
  228. ssize_t bsize = snd_pcm_format_size(format, psize * channels);
  229. return bsize;
  230. }
  231. ssize_t noninterleavedBufferSize(snd_pcm_hw_params_t* params)
  232. {
  233. _snd_pcm_format format; snd_pcm_hw_params_get_format(params, &format);
  234. snd_pcm_uframes_t psize; snd_pcm_hw_params_get_period_size(params, &psize, NULL);
  235. ssize_t bsize = snd_pcm_format_size(format, psize);
  236. return bsize;
  237. }
  238. /**
  239. * Read audio samples from the audio card. Convert samples to floats and take
  240. * care of interleaved buffers
  241. */
  242. int read()
  243. {
  244. if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) {
  245. int count = snd_pcm_readi(fInputDevice, fInputCardBuffer, fBuffering);
  246. if (count<0) {
  247. display_error_msg(count, "reading samples");
  248. int err = snd_pcm_prepare(fInputDevice);
  249. check_error_msg(err, "preparing input stream");
  250. }
  251. if (fSampleFormat == SND_PCM_FORMAT_S16) {
  252. short* buffer16b = (short*) fInputCardBuffer;
  253. for (int s = 0; s < fBuffering; s++) {
  254. for (unsigned int c = 0; c < fCardInputs; c++) {
  255. fInputSoftChannels[c][s] = float(buffer16b[c + s*fCardInputs])*(1.0/float(SHRT_MAX));
  256. }
  257. }
  258. } else { // SND_PCM_FORMAT_S32
  259. long* buffer32b = (long*) fInputCardBuffer;
  260. for (int s = 0; s < fBuffering; s++) {
  261. for (unsigned int c = 0; c < fCardInputs; c++) {
  262. fInputSoftChannels[c][s] = float(buffer32b[c + s*fCardInputs])*(1.0/float(LONG_MAX));
  263. }
  264. }
  265. }
  266. } else if (fSampleAccess == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
  267. int count = snd_pcm_readn(fInputDevice, fInputCardChannels, fBuffering);
  268. if (count < 0) {
  269. display_error_msg(count, "reading samples");
  270. int err = snd_pcm_prepare(fInputDevice);
  271. check_error_msg(err, "preparing input stream");
  272. }
  273. if (fSampleFormat == SND_PCM_FORMAT_S16) {
  274. for (unsigned int c = 0; c < fCardInputs; c++) {
  275. short* chan16b = (short*) fInputCardChannels[c];
  276. for (int s = 0; s < fBuffering; s++) {
  277. fInputSoftChannels[c][s] = float(chan16b[s])*(1.0/float(SHRT_MAX));
  278. }
  279. }
  280. } else { // SND_PCM_FORMAT_S32
  281. for (unsigned int c = 0; c < fCardInputs; c++) {
  282. long* chan32b = (long*) fInputCardChannels[c];
  283. for (int s = 0; s < fBuffering; s++) {
  284. fInputSoftChannels[c][s] = float(chan32b[s])*(1.0/float(LONG_MAX));
  285. }
  286. }
  287. }
  288. } else {
  289. check_error_msg(-10000, "unknow access mode");
  290. }
  291. return 0;
  292. }
  293. /**
  294. * write the output soft channels to the audio card. Convert sample
  295. * format and interleaves buffers when needed
  296. */
  297. int write()
  298. {
  299. recovery:
  300. if (fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED) {
  301. if (fSampleFormat == SND_PCM_FORMAT_S16) {
  302. short* buffer16b = (short*) fOutputCardBuffer;
  303. for (int f = 0; f < fBuffering; f++) {
  304. for (unsigned int c = 0; c < fCardOutputs; c++) {
  305. float x = fOutputSoftChannels[c][f];
  306. buffer16b[c + f * fCardOutputs] = short(max(min(x, 1.0), -1.0) * float(SHRT_MAX));
  307. }
  308. }
  309. } else { // SND_PCM_FORMAT_S32
  310. long* buffer32b = (long*) fOutputCardBuffer;
  311. for (int f = 0; f < fBuffering; f++) {
  312. for (unsigned int c = 0; c < fCardOutputs; c++) {
  313. float x = fOutputSoftChannels[c][f];
  314. buffer32b[c + f * fCardOutputs] = long( max(min(x, 1.0), -1.0) * float(LONG_MAX));
  315. }
  316. }
  317. }
  318. int count = snd_pcm_writei(fOutputDevice, fOutputCardBuffer, fBuffering);
  319. if (count < 0) {
  320. display_error_msg(count, "w3");
  321. int err = snd_pcm_prepare(fOutputDevice);
  322. check_error_msg(err, "preparing output stream");
  323. goto recovery;
  324. }
  325. } else if (fSampleAccess == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
  326. if (fSampleFormat == SND_PCM_FORMAT_S16) {
  327. for (unsigned int c = 0; c < fCardOutputs; c++) {
  328. short* chan16b = (short*) fOutputCardChannels[c];
  329. for (int f = 0; f < fBuffering; f++) {
  330. float x = fOutputSoftChannels[c][f];
  331. chan16b[f] = short(max(min(x,1.0), -1.0) * float(SHRT_MAX)) ;
  332. }
  333. }
  334. } else { // SND_PCM_FORMAT_S32
  335. for (unsigned int c = 0; c < fCardOutputs; c++) {
  336. long* chan32b = (long*) fOutputCardChannels[c];
  337. for (int f = 0; f < fBuffering; f++) {
  338. float x = fOutputSoftChannels[c][f];
  339. chan32b[f] = long(max(min(x,1.0),-1.0) * float(LONG_MAX)) ;
  340. }
  341. }
  342. }
  343. int count = snd_pcm_writen(fOutputDevice, fOutputCardChannels, fBuffering);
  344. if (count<0) {
  345. display_error_msg(count, "w3");
  346. int err = snd_pcm_prepare(fOutputDevice);
  347. check_error_msg(err, "preparing output stream");
  348. goto recovery;
  349. }
  350. } else {
  351. check_error_msg(-10000, "unknow access mode");
  352. }
  353. return 0;
  354. }
  355. /**
  356. * print short information on the audio device
  357. */
  358. int shortinfo()
  359. {
  360. int err;
  361. snd_ctl_card_info_t* card_info;
  362. snd_ctl_t* ctl_handle;
  363. err = snd_ctl_open(&ctl_handle, fCardName, 0); check_error(err);
  364. snd_ctl_card_info_alloca(&card_info);
  365. err = snd_ctl_card_info(ctl_handle, card_info); check_error(err);
  366. printf("%s|%d|%d|%d|%d|%s\n",
  367. snd_ctl_card_info_get_driver(card_info),
  368. fCardInputs, fCardOutputs,
  369. fFrequency, fBuffering,
  370. snd_pcm_format_name((_snd_pcm_format)fSampleFormat));
  371. }
  372. /**
  373. * print more detailled information on the audio device
  374. */
  375. int longinfo()
  376. {
  377. int err;
  378. snd_ctl_card_info_t* card_info;
  379. snd_ctl_t* ctl_handle;
  380. printf("Audio Interface Description :\n");
  381. printf("Sampling Frequency : %d, Sample Format : %s, buffering : %d\n",
  382. fFrequency, snd_pcm_format_name((_snd_pcm_format)fSampleFormat), fBuffering);
  383. printf("Software inputs : %2d, Software outputs : %2d\n", fSoftInputs, fSoftOutputs);
  384. printf("Hardware inputs : %2d, Hardware outputs : %2d\n", fCardInputs, fCardOutputs);
  385. printf("Channel inputs : %2d, Channel outputs : %2d\n", fChanInputs, fChanOutputs);
  386. // affichage des infos de la carte
  387. err = snd_ctl_open (&ctl_handle, fCardName, 0); check_error(err);
  388. snd_ctl_card_info_alloca (&card_info);
  389. err = snd_ctl_card_info(ctl_handle, card_info); check_error(err);
  390. printCardInfo(card_info);
  391. // affichage des infos liees aux streams d'entree-sortie
  392. if (fSoftInputs > 0) printHWParams(fInputParams);
  393. if (fSoftOutputs > 0) printHWParams(fOutputParams);
  394. return 0;
  395. }
  396. void printCardInfo(snd_ctl_card_info_t* ci)
  397. {
  398. printf("Card info (address : %p)\n", ci);
  399. printf("\tID = %s\n", snd_ctl_card_info_get_id(ci));
  400. printf("\tDriver = %s\n", snd_ctl_card_info_get_driver(ci));
  401. printf("\tName = %s\n", snd_ctl_card_info_get_name(ci));
  402. printf("\tLongName = %s\n", snd_ctl_card_info_get_longname(ci));
  403. printf("\tMixerName = %s\n", snd_ctl_card_info_get_mixername(ci));
  404. printf("\tComponents = %s\n", snd_ctl_card_info_get_components(ci));
  405. printf("--------------\n");
  406. }
  407. void printHWParams(snd_pcm_hw_params_t* params)
  408. {
  409. printf("HW Params info (address : %p)\n", params);
  410. #if 0
  411. printf("\tChannels = %d\n", snd_pcm_hw_params_get_channels(params));
  412. printf("\tFormat = %s\n", snd_pcm_format_name((_snd_pcm_format)snd_pcm_hw_params_get_format(params)));
  413. printf("\tAccess = %s\n", snd_pcm_access_name((_snd_pcm_access)snd_pcm_hw_params_get_access(params)));
  414. printf("\tRate = %d\n", snd_pcm_hw_params_get_rate(params, NULL));
  415. printf("\tPeriods = %d\n", snd_pcm_hw_params_get_periods(params, NULL));
  416. printf("\tPeriod size = %d\n", (int)snd_pcm_hw_params_get_period_size(params, NULL));
  417. printf("\tPeriod time = %d\n", snd_pcm_hw_params_get_period_time(params, NULL));
  418. printf("\tBuffer size = %d\n", (int)snd_pcm_hw_params_get_buffer_size(params));
  419. printf("\tBuffer time = %d\n", snd_pcm_hw_params_get_buffer_time(params, NULL));
  420. #endif
  421. printf("--------------\n");
  422. }
  423. };
  424. class JackAlsaIOAdapter : public JackIOAdapterInterface, public JackRunnableInterface
  425. {
  426. private:
  427. JackThread fThread;
  428. AudioInterface fAudioInterface;
  429. public:
  430. JackAlsaIOAdapter(int input, int output, jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  431. :JackIOAdapterInterface(input, output, buffer_size, sample_rate)
  432. ,fThread(this), fAudioInterface(input, output, buffer_size, sample_rate)
  433. {}
  434. ~JackAlsaIOAdapter()
  435. {}
  436. virtual int Open();
  437. virtual int Close();
  438. virtual int SetBufferSize(jack_nframes_t buffer_size);
  439. virtual bool Init();
  440. virtual bool Execute();
  441. };
  442. }
  443. #endif