20 #ifndef __JackAlsaAdapter__
21 #define __JackAlsaAdapter__
26 #include <alsa/asoundlib.h>
27 #include "JackAudioAdapterInterface.h"
28 #include "JackPlatformPlug.h"
29 #include "JackError.h"
36 inline void* aligned_calloc (
size_t nmemb,
size_t size ) {
return (
void* ) calloc ( nmemb, size ); }
38 #define max(x,y) (((x)>(y)) ? (x) : (y))
39 #define min(x,y) (((x)<(y)) ? (x) : (y))
41 #define check_error(err) if (err) { jack_error("%s:%d, alsa error %d : %s", __FILE__, __LINE__, err, snd_strerror(err)); return err; }
42 #define check_error_msg(err,msg) if (err) { jack_error("%s:%d, %s : %s(%d)", __FILE__, __LINE__, msg, snd_strerror(err), err); return err; }
43 #define display_error_msg(err,msg) if (err) { jack_error("%s:%d, %s : %s(%d)", __FILE__, __LINE__, msg, snd_strerror(err), err); }
51 const char* fCardName;
52 unsigned int fFrequency;
55 unsigned int fSoftInputs;
56 unsigned int fSoftOutputs;
67 AudioParam ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) :
69 fFrequency ( sample_rate ),
70 fBuffering ( buffer_size ),
93 void setInputs (
int inputs )
104 void setOutputs (
int outputs )
106 fSoftOutputs = outputs;
123 snd_pcm_t* fOutputDevice;
124 snd_pcm_t* fInputDevice;
125 snd_pcm_hw_params_t* fInputParams;
126 snd_pcm_hw_params_t* fOutputParams;
129 snd_pcm_format_t fSampleFormat;
130 snd_pcm_access_t fSampleAccess;
133 const char* fCaptureName;
134 const char* fPlaybackName;
135 unsigned int fCardInputs;
136 unsigned int fCardOutputs;
139 unsigned int fPeriod;
142 void* fInputCardBuffer;
143 void* fOutputCardBuffer;
146 void* fInputCardChannels[256];
147 void* fOutputCardChannels[256];
150 jack_default_audio_sample_t* fInputSoftChannels[256];
151 jack_default_audio_sample_t* fOutputSoftChannels[256];
155 const char* cardName()
170 jack_default_audio_sample_t** inputSoftChannels()
172 return fInputSoftChannels;
175 jack_default_audio_sample_t** outputSoftChannels()
177 return fOutputSoftChannels;
188 fPlaybackName = NULL;
190 fInputCardBuffer = 0;
191 fOutputCardBuffer = 0;
193 for (
int i = 0; i < 256; i++ )
195 fInputCardChannels[i] = 0;
196 fOutputCardChannels[i] = 0;
197 fInputSoftChannels[i] = 0;
198 fOutputSoftChannels[i] = 0;
202 AudioInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) :
205 fInputCardBuffer = 0;
206 fOutputCardBuffer = 0;
208 fPlaybackName = NULL;
210 for (
int i = 0; i < 256; i++ )
212 fInputCardChannels[i] = 0;
213 fOutputCardChannels[i] = 0;
214 fInputSoftChannels[i] = 0;
215 fOutputSoftChannels[i] = 0;
225 check_error ( snd_pcm_open ( &fInputDevice, (fCaptureName == NULL) ? fCardName : fCaptureName, SND_PCM_STREAM_CAPTURE, 0 ) );
226 check_error ( snd_pcm_open ( &fOutputDevice, (fPlaybackName == NULL) ? fCardName : fPlaybackName, SND_PCM_STREAM_PLAYBACK, 0 ) );
229 check_error ( snd_pcm_hw_params_malloc ( &fInputParams ) );
230 setAudioParams ( fInputDevice, fInputParams );
233 check_error ( snd_pcm_hw_params_malloc ( &fOutputParams ) )
234 setAudioParams ( fOutputDevice, fOutputParams );
237 fCardInputs = fSoftInputs;
238 fCardOutputs = fSoftOutputs;
240 snd_pcm_hw_params_set_channels_near(fInputDevice, fInputParams, &fCardInputs);
241 snd_pcm_hw_params_set_channels_near(fOutputDevice, fOutputParams, &fCardOutputs);
244 check_error ( snd_pcm_hw_params ( fInputDevice, fInputParams ) );
245 check_error ( snd_pcm_hw_params ( fOutputDevice, fOutputParams ) );
248 if ( fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED )
250 fInputCardBuffer = aligned_calloc ( interleavedBufferSize ( fInputParams ), 1 );
251 fOutputCardBuffer = aligned_calloc ( interleavedBufferSize ( fOutputParams ), 1 );
255 for (
unsigned int i = 0; i < fCardInputs; i++ )
256 fInputCardChannels[i] = aligned_calloc ( noninterleavedBufferSize ( fInputParams ), 1 );
257 for (
unsigned int i = 0; i < fCardOutputs; i++ )
258 fOutputCardChannels[i] = aligned_calloc ( noninterleavedBufferSize ( fOutputParams ), 1 );
262 fSoftInputs = max ( fSoftInputs, fCardInputs );
263 assert ( fSoftInputs < 256 );
264 fSoftOutputs = max ( fSoftOutputs, fCardOutputs );
265 assert ( fSoftOutputs < 256 );
267 for (
unsigned int i = 0; i < fSoftInputs; i++ )
269 fInputSoftChannels[i] = ( jack_default_audio_sample_t* ) aligned_calloc ( fBuffering,
sizeof ( jack_default_audio_sample_t ) );
270 for (
int j = 0; j < fBuffering; j++ )
271 fInputSoftChannels[i][j] = 0.0;
274 for (
unsigned int i = 0; i < fSoftOutputs; i++ )
276 fOutputSoftChannels[i] = ( jack_default_audio_sample_t* ) aligned_calloc ( fBuffering,
sizeof ( jack_default_audio_sample_t ) );
277 for (
int j = 0; j < fBuffering; j++ )
278 fOutputSoftChannels[i][j] = 0.0;
285 snd_pcm_hw_params_free ( fInputParams );
286 snd_pcm_hw_params_free ( fOutputParams );
287 snd_pcm_close ( fInputDevice );
288 snd_pcm_close ( fOutputDevice );
290 for (
unsigned int i = 0; i < fSoftInputs; i++ )
291 if ( fInputSoftChannels[i] )
292 free ( fInputSoftChannels[i] );
294 for (
unsigned int i = 0; i < fSoftOutputs; i++ )
295 if ( fOutputSoftChannels[i] )
296 free ( fOutputSoftChannels[i] );
298 for (
unsigned int i = 0; i < fCardInputs; i++ )
299 if ( fInputCardChannels[i] )
300 free ( fInputCardChannels[i] );
302 for (
unsigned int i = 0; i < fCardOutputs; i++ )
303 if ( fOutputCardChannels[i] )
304 free ( fOutputCardChannels[i] );
306 if ( fInputCardBuffer )
307 free ( fInputCardBuffer );
308 if ( fOutputCardBuffer )
309 free ( fOutputCardBuffer );
314 int setAudioParams ( snd_pcm_t* stream, snd_pcm_hw_params_t* params )
317 check_error_msg ( snd_pcm_hw_params_any ( stream, params ),
"unable to init parameters" )
320 if ( snd_pcm_hw_params_set_access ( stream, params, SND_PCM_ACCESS_RW_NONINTERLEAVED ) )
321 check_error_msg ( snd_pcm_hw_params_set_access ( stream, params, SND_PCM_ACCESS_RW_INTERLEAVED ),
322 "unable to set access mode neither to non-interleaved or to interleaved" );
323 snd_pcm_hw_params_get_access ( params, &fSampleAccess );
326 if ( snd_pcm_hw_params_set_format ( stream, params, SND_PCM_FORMAT_S32 ) )
327 check_error_msg ( snd_pcm_hw_params_set_format ( stream, params, SND_PCM_FORMAT_S16 ),
328 "unable to set format to either 32-bits or 16-bits" );
329 snd_pcm_hw_params_get_format ( params, &fSampleFormat );
332 snd_pcm_hw_params_set_rate_near ( stream, params, &fFrequency, 0 );
335 check_error_msg ( snd_pcm_hw_params_set_period_size ( stream, params, fBuffering, 0 ), "period size not available" );
336 check_error_msg ( snd_pcm_hw_params_set_periods ( stream, params, fPeriod, 0 ), "number of periods not available" );
341 ssize_t interleavedBufferSize ( snd_pcm_hw_params_t* params )
343 _snd_pcm_format format;
344 unsigned int channels;
345 snd_pcm_hw_params_get_format ( params, &format );
346 snd_pcm_uframes_t psize;
347 snd_pcm_hw_params_get_period_size ( params, &psize, NULL );
348 snd_pcm_hw_params_get_channels ( params, &channels );
349 ssize_t bsize = snd_pcm_format_size ( format, psize * channels );
353 ssize_t noninterleavedBufferSize ( snd_pcm_hw_params_t* params )
355 _snd_pcm_format format;
356 snd_pcm_hw_params_get_format ( params, &format );
357 snd_pcm_uframes_t psize;
358 snd_pcm_hw_params_get_period_size ( params, &psize, NULL );
359 ssize_t bsize = snd_pcm_format_size ( format, psize );
371 switch ( fSampleAccess )
373 case SND_PCM_ACCESS_RW_INTERLEAVED :
374 count = snd_pcm_readi ( fInputDevice, fInputCardBuffer, fBuffering );
377 display_error_msg ( count,
"reading samples" );
378 check_error_msg ( snd_pcm_prepare ( fInputDevice ),
"preparing input stream" );
380 if ( fSampleFormat == SND_PCM_FORMAT_S16 )
382 short* buffer16b = (
short* ) fInputCardBuffer;
383 for ( s = 0; s < fBuffering; s++ )
384 for ( c = 0; c < fCardInputs; c++ )
385 fInputSoftChannels[c][s] = jack_default_audio_sample_t(buffer16b[c + s*fCardInputs]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(SHRT_MAX));
389 int32_t* buffer32b = ( int32_t* ) fInputCardBuffer;
390 for ( s = 0; s < fBuffering; s++ )
391 for ( c = 0; c < fCardInputs; c++ )
392 fInputSoftChannels[c][s] = jack_default_audio_sample_t(buffer32b[c + s*fCardInputs]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(INT_MAX));
395 case SND_PCM_ACCESS_RW_NONINTERLEAVED :
396 count = snd_pcm_readn ( fInputDevice, fInputCardChannels, fBuffering );
399 display_error_msg ( count,
"reading samples" );
400 check_error_msg ( snd_pcm_prepare ( fInputDevice ),
"preparing input stream" );
402 if ( fSampleFormat == SND_PCM_FORMAT_S16 )
405 for ( c = 0; c < fCardInputs; c++ )
407 chan16b = (
short* ) fInputCardChannels[c];
408 for ( s = 0; s < fBuffering; s++ )
409 fInputSoftChannels[c][s] = jack_default_audio_sample_t(chan16b[s]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(SHRT_MAX));
415 for ( c = 0; c < fCardInputs; c++ )
417 chan32b = ( int32_t* ) fInputCardChannels[c];
418 for ( s = 0; s < fBuffering; s++ )
419 fInputSoftChannels[c][s] = jack_default_audio_sample_t(chan32b[s]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(INT_MAX));
424 check_error_msg ( -10000,
"unknow access mode" );
439 switch ( fSampleAccess )
441 case SND_PCM_ACCESS_RW_INTERLEAVED :
442 if ( fSampleFormat == SND_PCM_FORMAT_S16 )
444 short* buffer16b = (
short* ) fOutputCardBuffer;
445 for ( f = 0; f < fBuffering; f++ )
447 for (
unsigned int c = 0; c < fCardOutputs; c++ )
449 jack_default_audio_sample_t x = fOutputSoftChannels[c][f];
450 buffer16b[c + f * fCardOutputs] = short(max(min (x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(SHRT_MAX));
456 int32_t* buffer32b = ( int32_t* ) fOutputCardBuffer;
457 for ( f = 0; f < fBuffering; f++ )
459 for (
unsigned int c = 0; c < fCardOutputs; c++ )
461 jack_default_audio_sample_t x = fOutputSoftChannels[c][f];
462 buffer32b[c + f * fCardOutputs] = int32_t(max(min(x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(INT_MAX));
466 count = snd_pcm_writei ( fOutputDevice, fOutputCardBuffer, fBuffering );
469 display_error_msg ( count,
"w3" );
470 int err = snd_pcm_prepare ( fOutputDevice );
471 check_error_msg ( err,
"preparing output stream" );
475 case SND_PCM_ACCESS_RW_NONINTERLEAVED :
476 if ( fSampleFormat == SND_PCM_FORMAT_S16 )
478 for ( c = 0; c < fCardOutputs; c++ )
480 short* chan16b = (
short* ) fOutputCardChannels[c];
481 for ( f = 0; f < fBuffering; f++ )
483 jack_default_audio_sample_t x = fOutputSoftChannels[c][f];
484 chan16b[f] = short(max(min (x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(SHRT_MAX));
490 for ( c = 0; c < fCardOutputs; c++ )
492 int32_t* chan32b = ( int32_t* ) fOutputCardChannels[c];
493 for ( f = 0; f < fBuffering; f++ )
495 jack_default_audio_sample_t x = fOutputSoftChannels[c][f];
496 chan32b[f] = int32_t(max(min(x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(INT_MAX));
500 count = snd_pcm_writen ( fOutputDevice, fOutputCardChannels, fBuffering );
503 display_error_msg ( count,
"w3" );
504 int err = snd_pcm_prepare ( fOutputDevice );
505 check_error_msg ( err,
"preparing output stream" );
510 check_error_msg ( -10000,
"unknow access mode" );
522 snd_ctl_card_info_t* card_info;
523 snd_ctl_t* ctl_handle;
524 err = snd_ctl_open ( &ctl_handle, fCardName, 0 ); check_error ( err );
525 snd_ctl_card_info_alloca ( &card_info );
526 err = snd_ctl_card_info ( ctl_handle, card_info ); check_error ( err );
528 snd_ctl_card_info_get_driver ( card_info ),
529 fCardInputs, fCardOutputs,
530 fFrequency, fBuffering,
531 snd_pcm_format_name ( ( _snd_pcm_format ) fSampleFormat ) );
532 snd_ctl_close(ctl_handle);
540 snd_ctl_card_info_t* card_info;
541 snd_ctl_t* ctl_handle;
544 jack_info (
"Audio Interface Description :" );
545 jack_info (
"Sampling Frequency : %d, Sample Format : %s, buffering : %d, nperiod : %d",
546 fFrequency, snd_pcm_format_name ( ( _snd_pcm_format ) fSampleFormat ), fBuffering, fPeriod );
547 jack_info (
"Software inputs : %2d, Software outputs : %2d", fSoftInputs, fSoftOutputs );
548 jack_info (
"Hardware inputs : %2d, Hardware outputs : %2d", fCardInputs, fCardOutputs );
551 check_error ( snd_ctl_open ( &ctl_handle, fCardName, 0 ) );
552 snd_ctl_card_info_alloca ( &card_info );
553 check_error ( snd_ctl_card_info ( ctl_handle, card_info ) );
554 printCardInfo ( card_info );
557 if ( fSoftInputs > 0 )
558 printHWParams ( fInputParams );
559 if ( fSoftOutputs > 0 )
560 printHWParams ( fOutputParams );
561 snd_ctl_close(ctl_handle);
565 void printCardInfo ( snd_ctl_card_info_t* ci )
567 jack_info (
"Card info (address : %p)", ci );
568 jack_info (
"\tID = %s", snd_ctl_card_info_get_id ( ci ) );
569 jack_info (
"\tDriver = %s", snd_ctl_card_info_get_driver ( ci ) );
570 jack_info (
"\tName = %s", snd_ctl_card_info_get_name ( ci ) );
571 jack_info (
"\tLongName = %s", snd_ctl_card_info_get_longname ( ci ) );
572 jack_info (
"\tMixerName = %s", snd_ctl_card_info_get_mixername ( ci ) );
573 jack_info (
"\tComponents = %s", snd_ctl_card_info_get_components ( ci ) );
577 void printHWParams ( snd_pcm_hw_params_t* params )
579 jack_info (
"HW Params info (address : %p)\n", params );
581 jack_info (
"\tChannels = %d", snd_pcm_hw_params_get_channels ( params, NULL ) );
582 jack_info (
"\tFormat = %s", snd_pcm_format_name ( ( _snd_pcm_format ) snd_pcm_hw_params_get_format ( params, NULL ) ) );
583 jack_info (
"\tAccess = %s", snd_pcm_access_name ( ( _snd_pcm_access ) snd_pcm_hw_params_get_access ( params, NULL ) ) );
584 jack_info (
"\tRate = %d", snd_pcm_hw_params_get_rate ( params, NULL, NULL ) );
585 jack_info (
"\tPeriods = %d", snd_pcm_hw_params_get_periods ( params, NULL, NULL ) );
586 jack_info (
"\tPeriod size = %d", (
int ) snd_pcm_hw_params_get_period_size ( params, NULL, NULL ) );
587 jack_info (
"\tPeriod time = %d", snd_pcm_hw_params_get_period_time ( params, NULL, NULL ) );
588 jack_info (
"\tBuffer size = %d", (
int ) snd_pcm_hw_params_get_buffer_size ( params, NULL ) );
589 jack_info (
"\tBuffer time = %d", snd_pcm_hw_params_get_buffer_time ( params, NULL, NULL ) );
614 virtual int SetSampleRate ( jack_nframes_t sample_rate );
615 virtual int SetBufferSize ( jack_nframes_t buffer_size );
618 virtual bool Execute();
629 #include "JackCompilerDeps.h"
630 #include "driver_interface.h"
Audio adapter using ALSA API.
The base class for runnable objects, that have an Init and Execute method to be called in a threa...
SERVER_EXPORT void jack_info(const char *fmt,...)
Base class for audio adapters.
Darwin threads. Real-time threads are actually "time constraint" threads.