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.

616 lines
25KB

  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 "JackPlatformPlug.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 ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) :
  54. fCardName ( "hw:0" ),
  55. fFrequency ( sample_rate ),
  56. fBuffering ( buffer_size ),
  57. fSoftInputs ( 2 ),
  58. fSoftOutputs ( 2 )
  59. {}
  60. AudioParam& cardName ( const char* n )
  61. {
  62. fCardName = n;
  63. return *this;
  64. }
  65. AudioParam& frequency ( int f )
  66. {
  67. fFrequency = f;
  68. return *this;
  69. }
  70. AudioParam& buffering ( int fpb )
  71. {
  72. fBuffering = fpb;
  73. return *this;
  74. }
  75. void setInputs ( int inputs )
  76. {
  77. fSoftInputs = inputs;
  78. }
  79. AudioParam& inputs ( int n )
  80. {
  81. fSoftInputs = n;
  82. return *this;
  83. }
  84. void setOutputs ( int outputs )
  85. {
  86. fSoftOutputs = outputs;
  87. }
  88. AudioParam& outputs ( int n )
  89. {
  90. fSoftOutputs = n;
  91. return *this;
  92. }
  93. };
  94. /**
  95. * An ALSA audio interface
  96. */
  97. class AudioInterface : public AudioParam
  98. {
  99. public:
  100. //device info
  101. snd_pcm_t* fOutputDevice;
  102. snd_pcm_t* fInputDevice;
  103. snd_pcm_hw_params_t* fInputParams;
  104. snd_pcm_hw_params_t* fOutputParams;
  105. //samples info
  106. snd_pcm_format_t fSampleFormat;
  107. snd_pcm_access_t fSampleAccess;
  108. //channels
  109. unsigned int fCardInputs;
  110. unsigned int fCardOutputs;
  111. //stream parameters
  112. unsigned int fPeriod;
  113. //interleaved mode audiocard buffers
  114. void* fInputCardBuffer;
  115. void* fOutputCardBuffer;
  116. //non-interleaved mode audiocard buffers
  117. void* fInputCardChannels[256];
  118. void* fOutputCardChannels[256];
  119. //non-interleaved mod, floating point software buffers
  120. float* fInputSoftChannels[256];
  121. float* fOutputSoftChannels[256];
  122. //public methods ---------------------------------------------------------
  123. const char* cardName()
  124. {
  125. return fCardName;
  126. }
  127. int frequency()
  128. {
  129. return fFrequency;
  130. }
  131. int buffering()
  132. {
  133. return fBuffering;
  134. }
  135. float** inputSoftChannels()
  136. {
  137. return fInputSoftChannels;
  138. }
  139. float** outputSoftChannels()
  140. {
  141. return fOutputSoftChannels;
  142. }
  143. AudioInterface ( const AudioParam& ap = AudioParam() ) : AudioParam ( ap )
  144. {
  145. fInputDevice = 0;
  146. fOutputDevice = 0;
  147. fInputParams = 0;
  148. fOutputParams = 0;
  149. fPeriod = 2;
  150. }
  151. AudioInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) :
  152. AudioParam ( buffer_size, sample_rate )
  153. {
  154. fInputCardBuffer = 0;
  155. fOutputCardBuffer = 0;
  156. for ( int i = 0; i < 256; i++ )
  157. {
  158. fInputCardChannels[i] = 0;
  159. fOutputCardChannels[i] = 0;
  160. fInputSoftChannels[i] = 0;
  161. fOutputSoftChannels[i] = 0;
  162. }
  163. }
  164. /**
  165. * Open the audio interface
  166. */
  167. int open()
  168. {
  169. //open input/output streams
  170. check_error ( snd_pcm_open ( &fInputDevice, fCardName, SND_PCM_STREAM_CAPTURE, 0 ) );
  171. check_error ( snd_pcm_open ( &fOutputDevice, fCardName, SND_PCM_STREAM_PLAYBACK, 0 ) );
  172. //get hardware input parameters
  173. check_error ( snd_pcm_hw_params_malloc ( &fInputParams ) );
  174. setAudioParams ( fInputDevice, fInputParams );
  175. snd_pcm_hw_params_get_channels ( fInputParams, &fCardInputs );
  176. //get hardware output parameters
  177. check_error ( snd_pcm_hw_params_malloc ( &fOutputParams ) )
  178. setAudioParams ( fOutputDevice, fOutputParams );
  179. snd_pcm_hw_params_get_channels ( fOutputParams, &fCardOutputs );
  180. //set input/output param
  181. check_error ( snd_pcm_hw_params ( fInputDevice, fInputParams ) );
  182. check_error ( snd_pcm_hw_params ( fOutputDevice, fOutputParams ) );
  183. //set hardware buffers
  184. if ( fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED )
  185. {
  186. fInputCardBuffer = aligned_calloc ( interleavedBufferSize ( fInputParams ), 1 );
  187. fOutputCardBuffer = aligned_calloc ( interleavedBufferSize ( fOutputParams ), 1 );
  188. }
  189. else
  190. {
  191. for ( unsigned int i = 0; i < fCardInputs; i++ )
  192. fInputCardChannels[i] = aligned_calloc ( noninterleavedBufferSize ( fInputParams ), 1 );
  193. for ( unsigned int i = 0; i < fCardOutputs; i++ )
  194. fOutputCardChannels[i] = aligned_calloc ( noninterleavedBufferSize ( fOutputParams ), 1 );
  195. }
  196. //set floating point buffers needed by the dsp code
  197. fSoftInputs = max ( fSoftInputs, fCardInputs );
  198. assert ( fSoftInputs < 256 );
  199. fSoftOutputs = max ( fSoftOutputs, fCardOutputs );
  200. assert ( fSoftOutputs < 256 );
  201. for ( unsigned int i = 0; i < fSoftInputs; i++ )
  202. {
  203. fInputSoftChannels[i] = ( float* ) aligned_calloc ( fBuffering, sizeof ( float ) );
  204. for ( int j = 0; j < fBuffering; j++ )
  205. fInputSoftChannels[i][j] = 0.0;
  206. }
  207. for ( unsigned int i = 0; i < fSoftOutputs; i++ )
  208. {
  209. fOutputSoftChannels[i] = ( float* ) aligned_calloc ( fBuffering, sizeof ( float ) );
  210. for ( int j = 0; j < fBuffering; j++ )
  211. fOutputSoftChannels[i][j] = 0.0;
  212. }
  213. return 0;
  214. }
  215. int close()
  216. {
  217. snd_pcm_hw_params_free ( fInputParams );
  218. snd_pcm_hw_params_free ( fOutputParams );
  219. snd_pcm_close ( fInputDevice );
  220. snd_pcm_close ( fOutputDevice );
  221. for ( unsigned int i = 0; i < fSoftInputs; i++ )
  222. if ( fInputSoftChannels[i] )
  223. free ( fInputSoftChannels[i] );
  224. for ( unsigned int i = 0; i < fSoftOutputs; i++ )
  225. if ( fOutputSoftChannels[i] )
  226. free ( fOutputSoftChannels[i] );
  227. for ( unsigned int i = 0; i < fCardInputs; i++ )
  228. if ( fInputCardChannels[i] )
  229. free ( fInputCardChannels[i] );
  230. for ( unsigned int i = 0; i < fCardOutputs; i++ )
  231. if ( fOutputCardChannels[i] )
  232. free ( fOutputCardChannels[i] );
  233. if ( fInputCardBuffer )
  234. free ( fInputCardBuffer );
  235. if ( fOutputCardBuffer )
  236. free ( fOutputCardBuffer );
  237. return 0;
  238. }
  239. int setAudioParams ( snd_pcm_t* stream, snd_pcm_hw_params_t* params )
  240. {
  241. //set params record with initial values
  242. check_error_msg ( snd_pcm_hw_params_any ( stream, params ), "unable to init parameters" )
  243. //set alsa access mode (and fSampleAccess field) either to non interleaved or interleaved
  244. if ( snd_pcm_hw_params_set_access ( stream, params, SND_PCM_ACCESS_RW_NONINTERLEAVED ) )
  245. check_error_msg ( snd_pcm_hw_params_set_access ( stream, params, SND_PCM_ACCESS_RW_INTERLEAVED ),
  246. "unable to set access mode neither to non-interleaved or to interleaved" );
  247. snd_pcm_hw_params_get_access ( params, &fSampleAccess );
  248. //search for 32-bits or 16-bits format
  249. if ( snd_pcm_hw_params_set_format ( stream, params, SND_PCM_FORMAT_S32 ) )
  250. check_error_msg ( snd_pcm_hw_params_set_format ( stream, params, SND_PCM_FORMAT_S16 ),
  251. "unable to set format to either 32-bits or 16-bits" );
  252. snd_pcm_hw_params_get_format ( params, &fSampleFormat );
  253. //set sample frequency
  254. snd_pcm_hw_params_set_rate_near ( stream, params, &fFrequency, 0 );
  255. //set period and period size (buffering)
  256. check_error_msg ( snd_pcm_hw_params_set_period_size ( stream, params, fBuffering, 0 ), "period size not available" );
  257. check_error_msg ( snd_pcm_hw_params_set_periods ( stream, params, fPeriod, 0 ), "number of periods not available" );
  258. return 0;
  259. }
  260. ssize_t interleavedBufferSize ( snd_pcm_hw_params_t* params )
  261. {
  262. _snd_pcm_format format;
  263. unsigned int channels;
  264. snd_pcm_hw_params_get_format ( params, &format );
  265. snd_pcm_uframes_t psize;
  266. snd_pcm_hw_params_get_period_size ( params, &psize, NULL );
  267. snd_pcm_hw_params_get_channels ( params, &channels );
  268. ssize_t bsize = snd_pcm_format_size ( format, psize * channels );
  269. return bsize;
  270. }
  271. ssize_t noninterleavedBufferSize ( snd_pcm_hw_params_t* params )
  272. {
  273. _snd_pcm_format format;
  274. snd_pcm_hw_params_get_format ( params, &format );
  275. snd_pcm_uframes_t psize;
  276. snd_pcm_hw_params_get_period_size ( params, &psize, NULL );
  277. ssize_t bsize = snd_pcm_format_size ( format, psize );
  278. return bsize;
  279. }
  280. /**
  281. * Read audio samples from the audio card. Convert samples to floats and take
  282. * care of interleaved buffers
  283. */
  284. int read()
  285. {
  286. int count, s;
  287. unsigned int c;
  288. switch ( fSampleAccess )
  289. {
  290. case SND_PCM_ACCESS_RW_INTERLEAVED :
  291. count = snd_pcm_readi ( fInputDevice, fInputCardBuffer, fBuffering );
  292. if ( count < 0 )
  293. {
  294. display_error_msg ( count, "reading samples" );
  295. check_error_msg ( snd_pcm_prepare ( fInputDevice ), "preparing input stream" );
  296. }
  297. if ( fSampleFormat == SND_PCM_FORMAT_S16 )
  298. {
  299. short* buffer16b = ( short* ) fInputCardBuffer;
  300. for ( s = 0; s < fBuffering; s++ )
  301. for ( c = 0; c < fCardInputs; c++ )
  302. fInputSoftChannels[c][s] = float ( buffer16b[c + s*fCardInputs] ) * ( 1.0/float ( SHRT_MAX ) );
  303. }
  304. else // SND_PCM_FORMAT_S32
  305. {
  306. long* buffer32b = ( long* ) fInputCardBuffer;
  307. for ( s = 0; s < fBuffering; s++ )
  308. for ( c = 0; c < fCardInputs; c++ )
  309. fInputSoftChannels[c][s] = float ( buffer32b[c + s*fCardInputs] ) * ( 1.0/float ( LONG_MAX ) );
  310. }
  311. break;
  312. case SND_PCM_ACCESS_RW_NONINTERLEAVED :
  313. count = snd_pcm_readn ( fInputDevice, fInputCardChannels, fBuffering );
  314. if ( count < 0 )
  315. {
  316. display_error_msg ( count, "reading samples" );
  317. check_error_msg ( snd_pcm_prepare ( fInputDevice ), "preparing input stream" );
  318. }
  319. if ( fSampleFormat == SND_PCM_FORMAT_S16 )
  320. {
  321. short* chan16b;
  322. for ( c = 0; c < fCardInputs; c++ )
  323. {
  324. chan16b = ( short* ) fInputCardChannels[c];
  325. for ( s = 0; s < fBuffering; s++ )
  326. fInputSoftChannels[c][s] = float ( chan16b[s] ) * ( 1.0/float ( SHRT_MAX ) );
  327. }
  328. }
  329. else // SND_PCM_FORMAT_S32
  330. {
  331. long* chan32b;
  332. for ( c = 0; c < fCardInputs; c++ )
  333. {
  334. chan32b = ( long* ) fInputCardChannels[c];
  335. for ( s = 0; s < fBuffering; s++ )
  336. fInputSoftChannels[c][s] = float ( chan32b[s] ) * ( 1.0/float ( LONG_MAX ) );
  337. }
  338. }
  339. break;
  340. default :
  341. check_error_msg ( -10000, "unknow access mode" );
  342. break;
  343. }
  344. return 0;
  345. }
  346. /**
  347. * write the output soft channels to the audio card. Convert sample
  348. * format and interleaves buffers when needed
  349. */
  350. int write()
  351. {
  352. int count, f;
  353. unsigned int c;
  354. recovery:
  355. switch ( fSampleAccess )
  356. {
  357. case SND_PCM_ACCESS_RW_INTERLEAVED :
  358. if ( fSampleFormat == SND_PCM_FORMAT_S16 )
  359. {
  360. short* buffer16b = ( short* ) fOutputCardBuffer;
  361. for ( f = 0; f < fBuffering; f++ )
  362. {
  363. for ( unsigned int c = 0; c < fCardOutputs; c++ )
  364. {
  365. float x = fOutputSoftChannels[c][f];
  366. buffer16b[c + f * fCardOutputs] = short ( max ( min ( x, 1.0 ), -1.0 ) * float ( SHRT_MAX ) );
  367. }
  368. }
  369. }
  370. else // SND_PCM_FORMAT_S32
  371. {
  372. long* buffer32b = ( long* ) fOutputCardBuffer;
  373. for ( f = 0; f < fBuffering; f++ )
  374. {
  375. for ( unsigned int c = 0; c < fCardOutputs; c++ )
  376. {
  377. float x = fOutputSoftChannels[c][f];
  378. buffer32b[c + f * fCardOutputs] = long ( max ( min ( x, 1.0 ), -1.0 ) * float ( LONG_MAX ) );
  379. }
  380. }
  381. }
  382. count = snd_pcm_writei ( fOutputDevice, fOutputCardBuffer, fBuffering );
  383. if ( count < 0 )
  384. {
  385. display_error_msg ( count, "w3" );
  386. int err = snd_pcm_prepare ( fOutputDevice );
  387. check_error_msg ( err, "preparing output stream" );
  388. goto recovery;
  389. }
  390. break;
  391. case SND_PCM_ACCESS_RW_NONINTERLEAVED :
  392. if ( fSampleFormat == SND_PCM_FORMAT_S16 )
  393. {
  394. for ( c = 0; c < fCardOutputs; c++ )
  395. {
  396. short* chan16b = ( short* ) fOutputCardChannels[c];
  397. for ( f = 0; f < fBuffering; f++ )
  398. {
  399. float x = fOutputSoftChannels[c][f];
  400. chan16b[f] = short ( max ( min ( x,1.0 ), -1.0 ) * float ( SHRT_MAX ) ) ;
  401. }
  402. }
  403. }
  404. else
  405. {
  406. for ( c = 0; c < fCardOutputs; c++ )
  407. {
  408. long* chan32b = ( long* ) fOutputCardChannels[c];
  409. for ( f = 0; f < fBuffering; f++ )
  410. {
  411. float x = fOutputSoftChannels[c][f];
  412. chan32b[f] = long ( max ( min ( x,1.0 ),-1.0 ) * float ( LONG_MAX ) ) ;
  413. }
  414. }
  415. }
  416. count = snd_pcm_writen ( fOutputDevice, fOutputCardChannels, fBuffering );
  417. if ( count<0 )
  418. {
  419. display_error_msg ( count, "w3" );
  420. int err = snd_pcm_prepare ( fOutputDevice );
  421. check_error_msg ( err, "preparing output stream" );
  422. goto recovery;
  423. }
  424. break;
  425. default :
  426. check_error_msg ( -10000, "unknow access mode" );
  427. break;
  428. }
  429. return 0;
  430. }
  431. /**
  432. * print short information on the audio device
  433. */
  434. int shortinfo()
  435. {
  436. int err;
  437. snd_ctl_card_info_t* card_info;
  438. snd_ctl_t* ctl_handle;
  439. err = snd_ctl_open ( &ctl_handle, fCardName, 0 ); check_error ( err );
  440. snd_ctl_card_info_alloca ( &card_info );
  441. err = snd_ctl_card_info ( ctl_handle, card_info ); check_error ( err );
  442. jack_info ( "%s|%d|%d|%d|%d|%s",
  443. snd_ctl_card_info_get_driver ( card_info ),
  444. fCardInputs, fCardOutputs,
  445. fFrequency, fBuffering,
  446. snd_pcm_format_name ( ( _snd_pcm_format ) fSampleFormat ) );
  447. }
  448. /**
  449. * print more detailled information on the audio device
  450. */
  451. int longinfo()
  452. {
  453. snd_ctl_card_info_t* card_info;
  454. snd_ctl_t* ctl_handle;
  455. //display info
  456. jack_info ( "Audio Interface Description :" );
  457. jack_info ( "Sampling Frequency : %d, Sample Format : %s, buffering : %d, nperiod : %d",
  458. fFrequency, snd_pcm_format_name ( ( _snd_pcm_format ) fSampleFormat ), fBuffering, fPeriod );
  459. jack_info ( "Software inputs : %2d, Software outputs : %2d", fSoftInputs, fSoftOutputs );
  460. jack_info ( "Hardware inputs : %2d, Hardware outputs : %2d", fCardInputs, fCardOutputs );
  461. //get audio card info and display
  462. check_error ( snd_ctl_open ( &ctl_handle, fCardName, 0 ) );
  463. snd_ctl_card_info_alloca ( &card_info );
  464. check_error ( snd_ctl_card_info ( ctl_handle, card_info ) );
  465. printCardInfo ( card_info );
  466. //display input/output streams info
  467. if ( fSoftInputs > 0 )
  468. printHWParams ( fInputParams );
  469. if ( fSoftOutputs > 0 )
  470. printHWParams ( fOutputParams );
  471. return 0;
  472. }
  473. void printCardInfo ( snd_ctl_card_info_t* ci )
  474. {
  475. jack_info ( "Card info (address : %p)", ci );
  476. jack_info ( "\tID = %s", snd_ctl_card_info_get_id ( ci ) );
  477. jack_info ( "\tDriver = %s", snd_ctl_card_info_get_driver ( ci ) );
  478. jack_info ( "\tName = %s", snd_ctl_card_info_get_name ( ci ) );
  479. jack_info ( "\tLongName = %s", snd_ctl_card_info_get_longname ( ci ) );
  480. jack_info ( "\tMixerName = %s", snd_ctl_card_info_get_mixername ( ci ) );
  481. jack_info ( "\tComponents = %s", snd_ctl_card_info_get_components ( ci ) );
  482. jack_info ( "--------------" );
  483. }
  484. void printHWParams ( snd_pcm_hw_params_t* params )
  485. {
  486. jack_info ( "HW Params info (address : %p)\n", params );
  487. #if 0
  488. jack_info ( "\tChannels = %d", snd_pcm_hw_params_get_channels ( params, NULL ) );
  489. jack_info ( "\tFormat = %s", snd_pcm_format_name ( ( _snd_pcm_format ) snd_pcm_hw_params_get_format ( params, NULL ) ) );
  490. jack_info ( "\tAccess = %s", snd_pcm_access_name ( ( _snd_pcm_access ) snd_pcm_hw_params_get_access ( params, NULL ) ) );
  491. jack_info ( "\tRate = %d", snd_pcm_hw_params_get_rate ( params, NULL, NULL ) );
  492. jack_info ( "\tPeriods = %d", snd_pcm_hw_params_get_periods ( params, NULL, NULL ) );
  493. jack_info ( "\tPeriod size = %d", ( int ) snd_pcm_hw_params_get_period_size ( params, NULL, NULL ) );
  494. jack_info ( "\tPeriod time = %d", snd_pcm_hw_params_get_period_time ( params, NULL, NULL ) );
  495. jack_info ( "\tBuffer size = %d", ( int ) snd_pcm_hw_params_get_buffer_size ( params, NULL ) );
  496. jack_info ( "\tBuffer time = %d", snd_pcm_hw_params_get_buffer_time ( params, NULL, NULL ) );
  497. #endif
  498. jack_info ( "--------------" );
  499. }
  500. };
  501. /*!
  502. \brief Audio adapter using ALSA API.
  503. */
  504. class JackAlsaAdapter : public JackAudioAdapterInterface, public JackRunnableInterface
  505. {
  506. private:
  507. JackThread fThread;
  508. AudioInterface fAudioInterface;
  509. public:
  510. JackAlsaAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params );
  511. ~JackAlsaAdapter()
  512. {}
  513. virtual int Open();
  514. virtual int Close();
  515. virtual int SetSampleRate ( jack_nframes_t sample_rate );
  516. virtual int SetBufferSize ( jack_nframes_t buffer_size );
  517. virtual bool Init();
  518. virtual bool Execute();
  519. };
  520. }
  521. #ifdef __cplusplus
  522. extern "C"
  523. {
  524. #endif
  525. #include "JackCompilerDeps.h"
  526. #include "driver_interface.h"
  527. EXPORT jack_driver_desc_t* jack_get_descriptor();
  528. #ifdef __cplusplus
  529. }
  530. #endif
  531. #endif