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.

568 lines
20KB

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