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.

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