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.

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