@@ -163,6 +163,7 @@ _PA_DEFINE_FUNC(snd_pcm_hw_params_get_periods_max);
163163_PA_DEFINE_FUNC (snd_pcm_hw_params_set_period_size );
164164_PA_DEFINE_FUNC (snd_pcm_hw_params_get_period_size_min );
165165_PA_DEFINE_FUNC (snd_pcm_hw_params_get_period_size_max );
166+ _PA_DEFINE_FUNC (snd_pcm_hw_params_get_buffer_size_min );
166167_PA_DEFINE_FUNC (snd_pcm_hw_params_get_buffer_size_max );
167168_PA_DEFINE_FUNC (snd_pcm_hw_params_get_rate_min );
168169_PA_DEFINE_FUNC (snd_pcm_hw_params_get_rate_max );
@@ -448,6 +449,7 @@ static int PaAlsa_LoadLibrary()
448449 _PA_LOAD_FUNC (snd_pcm_hw_params_set_period_size );
449450 _PA_LOAD_FUNC (snd_pcm_hw_params_get_period_size_min );
450451 _PA_LOAD_FUNC (snd_pcm_hw_params_get_period_size_max );
452+ _PA_LOAD_FUNC (snd_pcm_hw_params_get_buffer_size_min );
451453 _PA_LOAD_FUNC (snd_pcm_hw_params_get_buffer_size_max );
452454 _PA_LOAD_FUNC (snd_pcm_hw_params_get_rate_min );
453455 _PA_LOAD_FUNC (snd_pcm_hw_params_get_rate_max );
@@ -534,6 +536,7 @@ static int PaAlsa_LoadLibrary()
534536 _PA_VALIDATE_LOAD_REPLACEMENT (snd_pcm_hw_params_get_periods_max );
535537 _PA_VALIDATE_LOAD_REPLACEMENT (snd_pcm_hw_params_get_period_size_min );
536538 _PA_VALIDATE_LOAD_REPLACEMENT (snd_pcm_hw_params_get_period_size_max );
539+ _PA_VALIDATE_LOAD_REPLACEMENT (snd_pcm_hw_params_get_buffer_size_min );
537540 _PA_VALIDATE_LOAD_REPLACEMENT (snd_pcm_hw_params_get_buffer_size_max );
538541 _PA_VALIDATE_LOAD_REPLACEMENT (snd_pcm_hw_params_get_rate_min );
539542 _PA_VALIDATE_LOAD_REPLACEMENT (snd_pcm_hw_params_get_rate_max );
@@ -844,18 +847,22 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
844847 * traits like max channels, suitable default latencies and default sample rate. Upon error, max channels is set to zero,
845848 * and a suitable result returned. The device is closed before returning.
846849 */
847- static PaError GropeDevice ( snd_pcm_t * pcm , int isPlug , StreamDirection mode , int openBlocking ,
850+ static PaError ProbeDeviceDefaults ( snd_pcm_t * pcm , int isPlug , StreamDirection mode , int openBlocking ,
848851 PaAlsaDeviceInfo * devInfo )
849852{
850853 PaError result = paNoError ;
851854 snd_pcm_hw_params_t * hwParams ;
852- snd_pcm_uframes_t alsaBufferFrames , alsaPeriodFrames ;
853855 unsigned int minChans = 0 ;
854856 unsigned int maxChans = 0 ;
855857 int * minChannels , * maxChannels ;
858+ snd_pcm_uframes_t lowBufferFrames = 0 ;
859+ snd_pcm_uframes_t highBufferFrames = 0 ;
860+ int ret = 0 ;
856861 double * defaultLowLatency , * defaultHighLatency ;
857862 double defaultSr = devInfo -> baseDeviceInfo .defaultSampleRate ;
858863 unsigned int approximateSampleRate = 0 ;
864+ const int kLowBufferFrames = 512 ;
865+ const int kHighBufferFrames = 2048 ;
859866
860867 assert ( pcm );
861868
@@ -947,32 +954,35 @@ static PaError GropeDevice( snd_pcm_t* pcm, int isPlug, StreamDirection mode, in
947954 PA_DEBUG (( "%s: Limiting number of plugin channels to %u\n" , __FUNCTION__ , maxChans ));
948955 }
949956
950- /* TWEAKME:
951- * Giving values for default min and max latency is not straightforward.
952- * * for low latency, we want to give the lowest value that will work reliably.
953- * This varies based on the sound card, kernel, CPU, etc. Better to give
954- * sub-optimal latency than to give a number too low and cause dropouts.
955- * * for high latency we want to give a large enough value that dropouts are basically impossible.
956- * This doesn't really require as much tweaking, since providing too large a number will
957- * just cause us to select the nearest setting that will work at stream config time.
957+ /*
958+ * Choose a reasonable low and high latency based on the min and max buffer size.
958959 */
959- /* Try low latency values, (sometimes the buffer & period that result are larger) */
960- alsaBufferFrames = 512 ;
961- alsaPeriodFrames = 128 ;
962- ENSURE_ ( alsa_snd_pcm_hw_params_set_buffer_size_near ( pcm , hwParams , & alsaBufferFrames ), paUnanticipatedHostError );
963- ENSURE_ ( alsa_snd_pcm_hw_params_set_period_size_near ( pcm , hwParams , & alsaPeriodFrames , NULL ), paUnanticipatedHostError );
964- * defaultLowLatency = (double ) (alsaBufferFrames - alsaPeriodFrames ) / defaultSr ;
965-
966- /* Base the high latency case on values four times larger */
967- alsaBufferFrames = 2048 ;
968- alsaPeriodFrames = 512 ;
969- /* Have to reset hwParams, to set new buffer size; need to also set sample rate again */
970- ENSURE_ ( alsa_snd_pcm_hw_params_any ( pcm , hwParams ), paUnanticipatedHostError );
971- ENSURE_ ( SetApproximateSampleRate ( pcm , hwParams , & approximateSampleRate ), paUnanticipatedHostError );
972- defaultSr = (double ) approximateSampleRate ;
973- ENSURE_ ( alsa_snd_pcm_hw_params_set_buffer_size_near ( pcm , hwParams , & alsaBufferFrames ), paUnanticipatedHostError );
974- ENSURE_ ( alsa_snd_pcm_hw_params_set_period_size_near ( pcm , hwParams , & alsaPeriodFrames , NULL ), paUnanticipatedHostError );
975- * defaultHighLatency = (double ) (alsaBufferFrames - alsaPeriodFrames ) / defaultSr ;
960+ ret = alsa_snd_pcm_hw_params_get_buffer_size_min ( hwParams , & lowBufferFrames );
961+ if (ret ) {
962+ printf ( "%s: alsa_snd_pcm_hw_params_get_buffer_size_min() returned %d !\n" , __FUNCTION__ , ret );
963+ lowBufferFrames = kLowBufferFrames ;
964+ }
965+ ret = alsa_snd_pcm_hw_params_get_buffer_size_max ( hwParams , & highBufferFrames );
966+ if (ret ) {
967+ printf ( "%s: alsa_snd_pcm_hw_params_get_buffer_size_max() returned %d !\n" , __FUNCTION__ , ret );
968+ highBufferFrames = kHighBufferFrames ;
969+ }
970+ printf ( "%s: lowBufferFrames = %u, highBufferFrames = %u\n" ,
971+ __FUNCTION__ , lowBufferFrames , highBufferFrames );
972+
973+ /* Clip to ensure optimal low value. */
974+ if (lowBufferFrames < kLowBufferFrames ) lowBufferFrames = kLowBufferFrames ;
975+ /* Base the high latency case on values four times larger. */
976+ const snd_pcm_uframes_t lowTimesN = lowBufferFrames * 4 ;
977+ /* Clip to ensure optimal high value. */
978+ if (highBufferFrames > lowTimesN ) highBufferFrames = lowTimesN ;
979+ if (highBufferFrames > kHighBufferFrames ) highBufferFrames = kHighBufferFrames ;
980+
981+ /* Assume period is 1/4 the buffer so it will normally be 3/4 full. */
982+ * defaultLowLatency = (double ) ((lowBufferFrames * 3 ) / 4 ) / defaultSr ;
983+ * defaultHighLatency = (double ) ((highBufferFrames * 3 ) / 4 ) / defaultSr ;
984+ printf ( "%s: defaultLowLatency = %f, defaultHighLatency = %f\n" ,
985+ __FUNCTION__ , * defaultLowLatency , * defaultHighLatency );
976986
977987 * minChannels = (int )minChans ;
978988 * maxChannels = (int )maxChans ;
@@ -1209,7 +1219,7 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d
12091219 if ( deviceHwInfo -> hasCapture &&
12101220 OpenPcm ( & pcm , deviceHwInfo -> alsaName , SND_PCM_STREAM_CAPTURE , blocking , 0 ) >= 0 )
12111221 {
1212- if ( GropeDevice ( pcm , deviceHwInfo -> isPlug , StreamDirection_In , blocking , devInfo ) != paNoError )
1222+ if ( ProbeDeviceDefaults ( pcm , deviceHwInfo -> isPlug , StreamDirection_In , blocking , devInfo ) != paNoError )
12131223 {
12141224 /* Error */
12151225 PA_DEBUG (( "%s: Failed groping %s for capture\n" , __FUNCTION__ , deviceHwInfo -> alsaName ));
@@ -1221,7 +1231,7 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d
12211231 if ( deviceHwInfo -> hasPlayback &&
12221232 OpenPcm ( & pcm , deviceHwInfo -> alsaName , SND_PCM_STREAM_PLAYBACK , blocking , 0 ) >= 0 )
12231233 {
1224- if ( GropeDevice ( pcm , deviceHwInfo -> isPlug , StreamDirection_Out , blocking , devInfo ) != paNoError )
1234+ if ( ProbeDeviceDefaults ( pcm , deviceHwInfo -> isPlug , StreamDirection_Out , blocking , devInfo ) != paNoError )
12251235 {
12261236 /* Error */
12271237 PA_DEBUG (( "%s: Failed groping %s for playback\n" , __FUNCTION__ , deviceHwInfo -> alsaName ));
@@ -1869,6 +1879,7 @@ static PaError TestParameters( const PaUtilHostApiRepresentation *hostApi, const
18691879 result = paUnanticipatedHostError ;
18701880 }
18711881
1882+ printf ( "%s: ret = %d\n" , __FUNCTION__ , ret );
18721883 ENSURE_ ( ret , result );
18731884 }
18741885 }
0 commit comments