00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __JackAlsaAdapter__
00021 #define __JackAlsaAdapter__
00022
00023 #include <math.h>
00024 #include <limits.h>
00025 #include <assert.h>
00026 #include <alsa/asoundlib.h>
00027 #include "JackAudioAdapterInterface.h"
00028 #include "JackPlatformPlug.h"
00029 #include "JackError.h"
00030 #include "jack.h"
00031 #include "jslist.h"
00032
00033 namespace Jack
00034 {
00035
00036 inline void* aligned_calloc ( size_t nmemb, size_t size ) { return ( void* ) calloc ( nmemb, size ); }
00037
00038 #define max(x,y) (((x)>(y)) ? (x) : (y))
00039 #define min(x,y) (((x)<(y)) ? (x) : (y))
00040
00041 #define check_error(err) if (err) { jack_error("%s:%d, alsa error %d : %s", __FILE__, __LINE__, err, snd_strerror(err)); return err; }
00042 #define check_error_msg(err,msg) if (err) { jack_error("%s:%d, %s : %s(%d)", __FILE__, __LINE__, msg, snd_strerror(err), err); return err; }
00043 #define display_error_msg(err,msg) if (err) { jack_error("%s:%d, %s : %s(%d)", __FILE__, __LINE__, msg, snd_strerror(err), err); }
00044
00048 class AudioParam
00049 {
00050 public:
00051 const char* fCardName;
00052 unsigned int fFrequency;
00053 int fBuffering;
00054
00055 unsigned int fSoftInputs;
00056 unsigned int fSoftOutputs;
00057
00058 public:
00059 AudioParam() :
00060 fCardName ( "hw:0" ),
00061 fFrequency ( 44100 ),
00062 fBuffering ( 512 ),
00063 fSoftInputs ( 2 ),
00064 fSoftOutputs ( 2 )
00065 {}
00066
00067 AudioParam ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) :
00068 fCardName ( "hw:0" ),
00069 fFrequency ( sample_rate ),
00070 fBuffering ( buffer_size ),
00071 fSoftInputs ( 2 ),
00072 fSoftOutputs ( 2 )
00073 {}
00074
00075 AudioParam& cardName ( const char* n )
00076 {
00077 fCardName = n;
00078 return *this;
00079 }
00080
00081 AudioParam& frequency ( int f )
00082 {
00083 fFrequency = f;
00084 return *this;
00085 }
00086
00087 AudioParam& buffering ( int fpb )
00088 {
00089 fBuffering = fpb;
00090 return *this;
00091 }
00092
00093 void setInputs ( int inputs )
00094 {
00095 fSoftInputs = inputs;
00096 }
00097
00098 AudioParam& inputs ( int n )
00099 {
00100 fSoftInputs = n;
00101 return *this;
00102 }
00103
00104 void setOutputs ( int outputs )
00105 {
00106 fSoftOutputs = outputs;
00107 }
00108
00109 AudioParam& outputs ( int n )
00110 {
00111 fSoftOutputs = n;
00112 return *this;
00113 }
00114 };
00115
00119 class AudioInterface : public AudioParam
00120 {
00121 public:
00122
00123 snd_pcm_t* fOutputDevice;
00124 snd_pcm_t* fInputDevice;
00125 snd_pcm_hw_params_t* fInputParams;
00126 snd_pcm_hw_params_t* fOutputParams;
00127
00128
00129 snd_pcm_format_t fSampleFormat;
00130 snd_pcm_access_t fSampleAccess;
00131
00132
00133 unsigned int fCardInputs;
00134 unsigned int fCardOutputs;
00135
00136
00137 unsigned int fPeriod;
00138
00139
00140 void* fInputCardBuffer;
00141 void* fOutputCardBuffer;
00142
00143
00144 void* fInputCardChannels[256];
00145 void* fOutputCardChannels[256];
00146
00147
00148 float* fInputSoftChannels[256];
00149 float* fOutputSoftChannels[256];
00150
00151
00152
00153 const char* cardName()
00154 {
00155 return fCardName;
00156 }
00157
00158 int frequency()
00159 {
00160 return fFrequency;
00161 }
00162
00163 int buffering()
00164 {
00165 return fBuffering;
00166 }
00167
00168 float** inputSoftChannels()
00169 {
00170 return fInputSoftChannels;
00171 }
00172
00173 float** outputSoftChannels()
00174 {
00175 return fOutputSoftChannels;
00176 }
00177
00178 AudioInterface ( const AudioParam& ap = AudioParam() ) : AudioParam ( ap )
00179 {
00180 fInputDevice = 0;
00181 fOutputDevice = 0;
00182 fInputParams = 0;
00183 fOutputParams = 0;
00184 fPeriod = 2;
00185
00186 fInputCardBuffer = 0;
00187 fOutputCardBuffer = 0;
00188
00189 for ( int i = 0; i < 256; i++ )
00190 {
00191 fInputCardChannels[i] = 0;
00192 fOutputCardChannels[i] = 0;
00193 fInputSoftChannels[i] = 0;
00194 fOutputSoftChannels[i] = 0;
00195 }
00196 }
00197
00198 AudioInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) :
00199 AudioParam ( buffer_size, sample_rate )
00200 {
00201 fInputCardBuffer = 0;
00202 fOutputCardBuffer = 0;
00203
00204 for ( int i = 0; i < 256; i++ )
00205 {
00206 fInputCardChannels[i] = 0;
00207 fOutputCardChannels[i] = 0;
00208 fInputSoftChannels[i] = 0;
00209 fOutputSoftChannels[i] = 0;
00210 }
00211 }
00212
00216 int open()
00217 {
00218
00219 check_error ( snd_pcm_open ( &fInputDevice, fCardName, SND_PCM_STREAM_CAPTURE, 0 ) );
00220 check_error ( snd_pcm_open ( &fOutputDevice, fCardName, SND_PCM_STREAM_PLAYBACK, 0 ) );
00221
00222
00223 check_error ( snd_pcm_hw_params_malloc ( &fInputParams ) );
00224 setAudioParams ( fInputDevice, fInputParams );
00225
00226
00227 check_error ( snd_pcm_hw_params_malloc ( &fOutputParams ) )
00228 setAudioParams ( fOutputDevice, fOutputParams );
00229
00230
00231 fCardInputs = fSoftInputs;
00232 fCardOutputs = fSoftOutputs;
00233
00234 snd_pcm_hw_params_set_channels_near(fInputDevice, fInputParams, &fCardInputs);
00235 snd_pcm_hw_params_set_channels_near(fOutputDevice, fOutputParams, &fCardOutputs);
00236
00237
00238 check_error ( snd_pcm_hw_params ( fInputDevice, fInputParams ) );
00239 check_error ( snd_pcm_hw_params ( fOutputDevice, fOutputParams ) );
00240
00241
00242 if ( fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED )
00243 {
00244 fInputCardBuffer = aligned_calloc ( interleavedBufferSize ( fInputParams ), 1 );
00245 fOutputCardBuffer = aligned_calloc ( interleavedBufferSize ( fOutputParams ), 1 );
00246 }
00247 else
00248 {
00249 for ( unsigned int i = 0; i < fCardInputs; i++ )
00250 fInputCardChannels[i] = aligned_calloc ( noninterleavedBufferSize ( fInputParams ), 1 );
00251 for ( unsigned int i = 0; i < fCardOutputs; i++ )
00252 fOutputCardChannels[i] = aligned_calloc ( noninterleavedBufferSize ( fOutputParams ), 1 );
00253 }
00254
00255
00256 fSoftInputs = max ( fSoftInputs, fCardInputs );
00257 assert ( fSoftInputs < 256 );
00258 fSoftOutputs = max ( fSoftOutputs, fCardOutputs );
00259 assert ( fSoftOutputs < 256 );
00260
00261 for ( unsigned int i = 0; i < fSoftInputs; i++ )
00262 {
00263 fInputSoftChannels[i] = ( float* ) aligned_calloc ( fBuffering, sizeof ( float ) );
00264 for ( int j = 0; j < fBuffering; j++ )
00265 fInputSoftChannels[i][j] = 0.0;
00266 }
00267
00268 for ( unsigned int i = 0; i < fSoftOutputs; i++ )
00269 {
00270 fOutputSoftChannels[i] = ( float* ) aligned_calloc ( fBuffering, sizeof ( float ) );
00271 for ( int j = 0; j < fBuffering; j++ )
00272 fOutputSoftChannels[i][j] = 0.0;
00273 }
00274 return 0;
00275 }
00276
00277 int close()
00278 {
00279 snd_pcm_hw_params_free ( fInputParams );
00280 snd_pcm_hw_params_free ( fOutputParams );
00281 snd_pcm_close ( fInputDevice );
00282 snd_pcm_close ( fOutputDevice );
00283
00284 for ( unsigned int i = 0; i < fSoftInputs; i++ )
00285 if ( fInputSoftChannels[i] )
00286 free ( fInputSoftChannels[i] );
00287
00288 for ( unsigned int i = 0; i < fSoftOutputs; i++ )
00289 if ( fOutputSoftChannels[i] )
00290 free ( fOutputSoftChannels[i] );
00291
00292 for ( unsigned int i = 0; i < fCardInputs; i++ )
00293 if ( fInputCardChannels[i] )
00294 free ( fInputCardChannels[i] );
00295
00296 for ( unsigned int i = 0; i < fCardOutputs; i++ )
00297 if ( fOutputCardChannels[i] )
00298 free ( fOutputCardChannels[i] );
00299
00300 if ( fInputCardBuffer )
00301 free ( fInputCardBuffer );
00302 if ( fOutputCardBuffer )
00303 free ( fOutputCardBuffer );
00304
00305 return 0;
00306 }
00307
00308 int setAudioParams ( snd_pcm_t* stream, snd_pcm_hw_params_t* params )
00309 {
00310
00311 check_error_msg ( snd_pcm_hw_params_any ( stream, params ), "unable to init parameters" )
00312
00313
00314 if ( snd_pcm_hw_params_set_access ( stream, params, SND_PCM_ACCESS_RW_NONINTERLEAVED ) )
00315 check_error_msg ( snd_pcm_hw_params_set_access ( stream, params, SND_PCM_ACCESS_RW_INTERLEAVED ),
00316 "unable to set access mode neither to non-interleaved or to interleaved" );
00317 snd_pcm_hw_params_get_access ( params, &fSampleAccess );
00318
00319
00320 if ( snd_pcm_hw_params_set_format ( stream, params, SND_PCM_FORMAT_S32 ) )
00321 check_error_msg ( snd_pcm_hw_params_set_format ( stream, params, SND_PCM_FORMAT_S16 ),
00322 "unable to set format to either 32-bits or 16-bits" );
00323 snd_pcm_hw_params_get_format ( params, &fSampleFormat );
00324
00325
00326 snd_pcm_hw_params_set_rate_near ( stream, params, &fFrequency, 0 );
00327
00328
00329 check_error_msg ( snd_pcm_hw_params_set_period_size ( stream, params, fBuffering, 0 ), "period size not available" );
00330 check_error_msg ( snd_pcm_hw_params_set_periods ( stream, params, fPeriod, 0 ), "number of periods not available" );
00331
00332 return 0;
00333 }
00334
00335 ssize_t interleavedBufferSize ( snd_pcm_hw_params_t* params )
00336 {
00337 _snd_pcm_format format;
00338 unsigned int channels;
00339 snd_pcm_hw_params_get_format ( params, &format );
00340 snd_pcm_uframes_t psize;
00341 snd_pcm_hw_params_get_period_size ( params, &psize, NULL );
00342 snd_pcm_hw_params_get_channels ( params, &channels );
00343 ssize_t bsize = snd_pcm_format_size ( format, psize * channels );
00344 return bsize;
00345 }
00346
00347 ssize_t noninterleavedBufferSize ( snd_pcm_hw_params_t* params )
00348 {
00349 _snd_pcm_format format;
00350 snd_pcm_hw_params_get_format ( params, &format );
00351 snd_pcm_uframes_t psize;
00352 snd_pcm_hw_params_get_period_size ( params, &psize, NULL );
00353 ssize_t bsize = snd_pcm_format_size ( format, psize );
00354 return bsize;
00355 }
00356
00361 int read()
00362 {
00363 int count, s;
00364 unsigned int c;
00365 switch ( fSampleAccess )
00366 {
00367 case SND_PCM_ACCESS_RW_INTERLEAVED :
00368 count = snd_pcm_readi ( fInputDevice, fInputCardBuffer, fBuffering );
00369 if ( count < 0 )
00370 {
00371 display_error_msg ( count, "reading samples" );
00372 check_error_msg ( snd_pcm_prepare ( fInputDevice ), "preparing input stream" );
00373 }
00374 if ( fSampleFormat == SND_PCM_FORMAT_S16 )
00375 {
00376 short* buffer16b = ( short* ) fInputCardBuffer;
00377 for ( s = 0; s < fBuffering; s++ )
00378 for ( c = 0; c < fCardInputs; c++ )
00379 fInputSoftChannels[c][s] = float ( buffer16b[c + s*fCardInputs] ) * ( 1.0/float ( SHRT_MAX ) );
00380 }
00381 else
00382 {
00383 int32_t* buffer32b = ( int32_t* ) fInputCardBuffer;
00384 for ( s = 0; s < fBuffering; s++ )
00385 for ( c = 0; c < fCardInputs; c++ )
00386 fInputSoftChannels[c][s] = float ( buffer32b[c + s*fCardInputs] ) * ( 1.0/float ( INT_MAX ) );
00387 }
00388 break;
00389 case SND_PCM_ACCESS_RW_NONINTERLEAVED :
00390 count = snd_pcm_readn ( fInputDevice, fInputCardChannels, fBuffering );
00391 if ( count < 0 )
00392 {
00393 display_error_msg ( count, "reading samples" );
00394 check_error_msg ( snd_pcm_prepare ( fInputDevice ), "preparing input stream" );
00395 }
00396 if ( fSampleFormat == SND_PCM_FORMAT_S16 )
00397 {
00398 short* chan16b;
00399 for ( c = 0; c < fCardInputs; c++ )
00400 {
00401 chan16b = ( short* ) fInputCardChannels[c];
00402 for ( s = 0; s < fBuffering; s++ )
00403 fInputSoftChannels[c][s] = float ( chan16b[s] ) * ( 1.0/float ( SHRT_MAX ) );
00404 }
00405 }
00406 else
00407 {
00408 int32_t* chan32b;
00409 for ( c = 0; c < fCardInputs; c++ )
00410 {
00411 chan32b = ( int32_t* ) fInputCardChannels[c];
00412 for ( s = 0; s < fBuffering; s++ )
00413 fInputSoftChannels[c][s] = float ( chan32b[s] ) * ( 1.0/float ( INT_MAX ) );
00414 }
00415 }
00416 break;
00417 default :
00418 check_error_msg ( -10000, "unknow access mode" );
00419 break;
00420 }
00421 return 0;
00422 }
00423
00428 int write()
00429 {
00430 int count, f;
00431 unsigned int c;
00432 recovery:
00433 switch ( fSampleAccess )
00434 {
00435 case SND_PCM_ACCESS_RW_INTERLEAVED :
00436 if ( fSampleFormat == SND_PCM_FORMAT_S16 )
00437 {
00438 short* buffer16b = ( short* ) fOutputCardBuffer;
00439 for ( f = 0; f < fBuffering; f++ )
00440 {
00441 for ( unsigned int c = 0; c < fCardOutputs; c++ )
00442 {
00443 float x = fOutputSoftChannels[c][f];
00444 buffer16b[c + f * fCardOutputs] = short ( max ( min ( x, 1.0 ), -1.0 ) * float ( SHRT_MAX ) );
00445 }
00446 }
00447 }
00448 else
00449 {
00450 int32_t* buffer32b = ( int32_t* ) fOutputCardBuffer;
00451 for ( f = 0; f < fBuffering; f++ )
00452 {
00453 for ( unsigned int c = 0; c < fCardOutputs; c++ )
00454 {
00455 float x = fOutputSoftChannels[c][f];
00456 buffer32b[c + f * fCardOutputs] = int32_t ( max ( min ( x, 1.0 ), -1.0 ) * float ( INT_MAX ) );
00457 }
00458 }
00459 }
00460 count = snd_pcm_writei ( fOutputDevice, fOutputCardBuffer, fBuffering );
00461 if ( count < 0 )
00462 {
00463 display_error_msg ( count, "w3" );
00464 int err = snd_pcm_prepare ( fOutputDevice );
00465 check_error_msg ( err, "preparing output stream" );
00466 goto recovery;
00467 }
00468 break;
00469 case SND_PCM_ACCESS_RW_NONINTERLEAVED :
00470 if ( fSampleFormat == SND_PCM_FORMAT_S16 )
00471 {
00472 for ( c = 0; c < fCardOutputs; c++ )
00473 {
00474 short* chan16b = ( short* ) fOutputCardChannels[c];
00475 for ( f = 0; f < fBuffering; f++ )
00476 {
00477 float x = fOutputSoftChannels[c][f];
00478 chan16b[f] = short ( max ( min ( x,1.0 ), -1.0 ) * float ( SHRT_MAX ) ) ;
00479 }
00480 }
00481 }
00482 else
00483 {
00484 for ( c = 0; c < fCardOutputs; c++ )
00485 {
00486 int32_t* chan32b = ( int32_t* ) fOutputCardChannels[c];
00487 for ( f = 0; f < fBuffering; f++ )
00488 {
00489 float x = fOutputSoftChannels[c][f];
00490 chan32b[f] = int32_t ( max ( min ( x,1.0 ),-1.0 ) * float ( INT_MAX ) ) ;
00491 }
00492 }
00493 }
00494 count = snd_pcm_writen ( fOutputDevice, fOutputCardChannels, fBuffering );
00495 if ( count<0 )
00496 {
00497 display_error_msg ( count, "w3" );
00498 int err = snd_pcm_prepare ( fOutputDevice );
00499 check_error_msg ( err, "preparing output stream" );
00500 goto recovery;
00501 }
00502 break;
00503 default :
00504 check_error_msg ( -10000, "unknow access mode" );
00505 break;
00506 }
00507 return 0;
00508 }
00509
00513 int shortinfo()
00514 {
00515 int err;
00516 snd_ctl_card_info_t* card_info;
00517 snd_ctl_t* ctl_handle;
00518 err = snd_ctl_open ( &ctl_handle, fCardName, 0 ); check_error ( err );
00519 snd_ctl_card_info_alloca ( &card_info );
00520 err = snd_ctl_card_info ( ctl_handle, card_info ); check_error ( err );
00521 jack_info ( "%s|%d|%d|%d|%d|%s",
00522 snd_ctl_card_info_get_driver ( card_info ),
00523 fCardInputs, fCardOutputs,
00524 fFrequency, fBuffering,
00525 snd_pcm_format_name ( ( _snd_pcm_format ) fSampleFormat ) );
00526 }
00527
00531 int longinfo()
00532 {
00533 snd_ctl_card_info_t* card_info;
00534 snd_ctl_t* ctl_handle;
00535
00536
00537 jack_info ( "Audio Interface Description :" );
00538 jack_info ( "Sampling Frequency : %d, Sample Format : %s, buffering : %d, nperiod : %d",
00539 fFrequency, snd_pcm_format_name ( ( _snd_pcm_format ) fSampleFormat ), fBuffering, fPeriod );
00540 jack_info ( "Software inputs : %2d, Software outputs : %2d", fSoftInputs, fSoftOutputs );
00541 jack_info ( "Hardware inputs : %2d, Hardware outputs : %2d", fCardInputs, fCardOutputs );
00542
00543
00544 check_error ( snd_ctl_open ( &ctl_handle, fCardName, 0 ) );
00545 snd_ctl_card_info_alloca ( &card_info );
00546 check_error ( snd_ctl_card_info ( ctl_handle, card_info ) );
00547 printCardInfo ( card_info );
00548
00549
00550 if ( fSoftInputs > 0 )
00551 printHWParams ( fInputParams );
00552 if ( fSoftOutputs > 0 )
00553 printHWParams ( fOutputParams );
00554
00555 return 0;
00556 }
00557
00558 void printCardInfo ( snd_ctl_card_info_t* ci )
00559 {
00560 jack_info ( "Card info (address : %p)", ci );
00561 jack_info ( "\tID = %s", snd_ctl_card_info_get_id ( ci ) );
00562 jack_info ( "\tDriver = %s", snd_ctl_card_info_get_driver ( ci ) );
00563 jack_info ( "\tName = %s", snd_ctl_card_info_get_name ( ci ) );
00564 jack_info ( "\tLongName = %s", snd_ctl_card_info_get_longname ( ci ) );
00565 jack_info ( "\tMixerName = %s", snd_ctl_card_info_get_mixername ( ci ) );
00566 jack_info ( "\tComponents = %s", snd_ctl_card_info_get_components ( ci ) );
00567 jack_info ( "--------------" );
00568 }
00569
00570 void printHWParams ( snd_pcm_hw_params_t* params )
00571 {
00572 jack_info ( "HW Params info (address : %p)\n", params );
00573 #if 0
00574 jack_info ( "\tChannels = %d", snd_pcm_hw_params_get_channels ( params, NULL ) );
00575 jack_info ( "\tFormat = %s", snd_pcm_format_name ( ( _snd_pcm_format ) snd_pcm_hw_params_get_format ( params, NULL ) ) );
00576 jack_info ( "\tAccess = %s", snd_pcm_access_name ( ( _snd_pcm_access ) snd_pcm_hw_params_get_access ( params, NULL ) ) );
00577 jack_info ( "\tRate = %d", snd_pcm_hw_params_get_rate ( params, NULL, NULL ) );
00578 jack_info ( "\tPeriods = %d", snd_pcm_hw_params_get_periods ( params, NULL, NULL ) );
00579 jack_info ( "\tPeriod size = %d", ( int ) snd_pcm_hw_params_get_period_size ( params, NULL, NULL ) );
00580 jack_info ( "\tPeriod time = %d", snd_pcm_hw_params_get_period_time ( params, NULL, NULL ) );
00581 jack_info ( "\tBuffer size = %d", ( int ) snd_pcm_hw_params_get_buffer_size ( params, NULL ) );
00582 jack_info ( "\tBuffer time = %d", snd_pcm_hw_params_get_buffer_time ( params, NULL, NULL ) );
00583 #endif
00584 jack_info ( "--------------" );
00585 }
00586 };
00587
00592 class JackAlsaAdapter : public JackAudioAdapterInterface, public JackRunnableInterface
00593 {
00594
00595 private:
00596 JackThread fThread;
00597 AudioInterface fAudioInterface;
00598
00599 public:
00600 JackAlsaAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params );
00601 ~JackAlsaAdapter()
00602 {}
00603
00604 virtual int Open();
00605 virtual int Close();
00606
00607 virtual int SetSampleRate ( jack_nframes_t sample_rate );
00608 virtual int SetBufferSize ( jack_nframes_t buffer_size );
00609
00610 virtual bool Init();
00611 virtual bool Execute();
00612
00613 };
00614
00615 }
00616
00617 #ifdef __cplusplus
00618 extern "C"
00619 {
00620 #endif
00621
00622 #include "JackCompilerDeps.h"
00623 #include "driver_interface.h"
00624
00625 EXPORT jack_driver_desc_t* jack_get_descriptor();
00626
00627 #ifdef __cplusplus
00628 }
00629 #endif
00630
00631 #endif