@@ -361,31 +361,6 @@ impl Device {
361361 sample_format : SampleFormat ,
362362 stream_type : alsa:: Direction ,
363363 ) -> Result < StreamInner , Error > {
364- // Validate buffer size if Fixed is specified. This is necessary because
365- // `set_period_size_near()` with `ValueOr::Nearest` will accept ANY value and return the
366- // "nearest" supported value, which could be wildly different (e.g., requesting 4096 frames
367- // might return 512 frames if that's "nearest").
368- if let BufferSize :: Fixed ( requested_size) = conf. buffer_size {
369- // Note: We use `default_input_config`/`default_output_config` to get the buffer size
370- // range. This queries the CURRENT device (`self.pcm_id`), not the default device. The
371- // buffer size range is the same across all format configurations for a given device
372- // (see `supported_configs()`).
373- let supported_config = match stream_type {
374- alsa:: Direction :: Capture => self . default_input_config ( ) ,
375- alsa:: Direction :: Playback => self . default_output_config ( ) ,
376- } ;
377- if let Ok ( config) = supported_config {
378- if let SupportedBufferSize :: Range { min, max } = config. buffer_size {
379- if !( min..=max) . contains ( & requested_size) {
380- return Err ( Error :: with_message (
381- ErrorKind :: UnsupportedConfig ,
382- format ! ( "Buffer size {requested_size} is not in the supported range {min}..={max}" ) ,
383- ) ) ;
384- }
385- }
386- }
387- }
388-
389364 let handle = {
390365 let _guard = ALSA_OPEN_MUTEX . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
391366 alsa:: pcm:: PCM :: new ( & self . pcm_id , stream_type, true ) ?
@@ -1571,6 +1546,17 @@ fn set_hw_params_from_format(
15711546 // buffer_size = 2x and period_size = x. This provides consistent low-latency
15721547 // behavior across different ALSA implementations and hardware.
15731548 if let BufferSize :: Fixed ( buffer_frames) = config. buffer_size {
1549+ // Validate the requested size against the device's supported range using the same PCM
1550+ // handle we'll use for streaming. This avoids a second PCM open (which can disturb
1551+ // hardware clock state on some drivers) while still catching wildly out-of-range
1552+ // requests before set_period_size_near silently rounds them.
1553+ let ( min_buffer, max_buffer) = hw_params_buffer_size_min_max ( & hw_params) ;
1554+ if !( min_buffer..=max_buffer) . contains ( & buffer_frames) {
1555+ return Err ( Error :: with_message (
1556+ ErrorKind :: UnsupportedConfig ,
1557+ format ! ( "Buffer size {buffer_frames} is not in the supported range {min_buffer}..={max_buffer}" ) ,
1558+ ) ) ;
1559+ }
15741560 hw_params. set_buffer_size_near ( DEFAULT_PERIODS * buffer_frames as alsa:: pcm:: Frames ) ?;
15751561 hw_params
15761562 . set_period_size_near ( buffer_frames as alsa:: pcm:: Frames , alsa:: ValueOr :: Nearest ) ?;
0 commit comments