@@ -84,6 +84,7 @@ pub(crate) enum AudioOutputBuffer<'buffer> {
8484}
8585
8686impl < ' buffer > AudioOutputBuffer < ' buffer > {
87+ /// Return the number of interleaved samples in the underlying buffer.
8788 #[ allow( dead_code) ]
8889 fn len ( & self ) -> usize {
8990 match self {
@@ -99,6 +100,7 @@ impl<'buffer> AudioOutputBuffer<'buffer> {
99100 }
100101 }
101102
103+ /// Return the sample format of the underlying typed buffer.
102104 fn sample_format ( & self ) -> AudioSampleFormat {
103105 match self {
104106 Self :: F32 ( _) => {
@@ -125,6 +127,11 @@ pub(crate) struct InterleavedAudioOutputWriter<'buffer> {
125127}
126128
127129impl < ' buffer > InterleavedAudioOutputWriter < ' buffer > {
130+ /// Create a writer for an interleaved output buffer.
131+ ///
132+ /// `channels` MUST match the channel count encoded in the output stream
133+ /// configuration. The frame count is derived from the buffer length and
134+ /// channel count.
128135 #[ allow( dead_code) ]
129136 pub fn new ( channels : u16 , buffer : AudioOutputBuffer < ' buffer > ) -> Self {
130137 let channels_usize = channels as usize ;
@@ -141,12 +148,14 @@ impl<'buffer> InterleavedAudioOutputWriter<'buffer> {
141148 } ;
142149 }
143150
151+ /// Return the sample format of the current callback buffer.
144152 #[ allow( dead_code) ]
145153 pub fn sample_format ( & self ) -> AudioSampleFormat {
146154 return self . buffer . sample_format ( ) ;
147155 }
148156}
149157
158+ /// Clamp a normalized audio sample to the nominal output range `[-1.0, 1.0]`.
150159#[ allow( dead_code) ]
151160fn clamp_normalized_sample ( sample : f32 ) -> f32 {
152161 if sample > 1.0 {
@@ -680,6 +689,12 @@ impl Default for AudioDeviceBuilder {
680689 }
681690}
682691
692+ /// Invoke an output callback using a typed platform buffer.
693+ ///
694+ /// This adapter:
695+ /// - Wraps the typed `cpal` output slice in an [`AudioOutputWriter`].
696+ /// - Clears the buffer to silence before invoking the callback.
697+ /// - Guarantees a single callback invocation per platform callback tick.
683698fn invoke_output_callback_on_buffer < Callback > (
684699 channels : u16 ,
685700 buffer : AudioOutputBuffer < ' _ > ,
@@ -694,6 +709,10 @@ fn invoke_output_callback_on_buffer<Callback>(
694709 return ;
695710}
696711
712+ /// Convert a `cpal` sample format into a stable preference ordering.
713+ ///
714+ /// The current backend prefers `f32`, then `i16`, then `u16`. Any other format
715+ /// is treated as unsupported by this abstraction.
697716fn sample_format_priority ( sample_format : cpal_backend:: SampleFormat ) -> u8 {
698717 match sample_format {
699718 cpal_backend:: SampleFormat :: F32 => {
@@ -711,6 +730,17 @@ fn sample_format_priority(sample_format: cpal_backend::SampleFormat) -> u8 {
711730 }
712731}
713732
733+ /// Select a supported output stream configuration for the default device.
734+ ///
735+ /// Selection rules:
736+ /// - If `requested_channels` is set, only exact channel matches are considered.
737+ /// - If `requested_sample_rate` is set, only ranges that contain the rate are
738+ /// considered.
739+ /// - If no rate is requested, the selection targets `48_000` Hz and chooses the
740+ /// closest available rate within each range.
741+ /// - Higher-quality sample formats are preferred (`f32` > `i16` > `u16`).
742+ /// - When priorities tie, the configuration with sample rate closest to
743+ /// `48_000` Hz is preferred.
714744fn select_output_stream_config (
715745 supported_configs : & [ cpal_backend:: SupportedStreamConfigRange ] ,
716746 requested_sample_rate : Option < u32 > ,
@@ -844,24 +874,29 @@ mod tests {
844874
845875 use super :: * ;
846876
877+ /// Builder MUST reject invalid sample rates.
847878 #[ test]
848879 fn build_rejects_zero_sample_rate ( ) {
849880 let result = AudioDeviceBuilder :: new ( ) . with_sample_rate ( 0 ) . build ( ) ;
850881 assert ! ( matches!(
851882 result,
852883 Err ( AudioError :: InvalidSampleRate { requested: 0 } )
853884 ) ) ;
885+ return ;
854886 }
855887
888+ /// Builder MUST reject invalid channel counts.
856889 #[ test]
857890 fn build_rejects_zero_channels ( ) {
858891 let result = AudioDeviceBuilder :: new ( ) . with_channels ( 0 ) . build ( ) ;
859892 assert ! ( matches!(
860893 result,
861894 Err ( AudioError :: InvalidChannels { requested: 0 } )
862895 ) ) ;
896+ return ;
863897 }
864898
899+ /// Builder MUST NOT panic for typical host/device states.
865900 #[ test]
866901 fn build_does_not_panic ( ) {
867902 let result = AudioDeviceBuilder :: new ( ) . build ( ) ;
@@ -873,12 +908,14 @@ mod tests {
873908 return ;
874909 }
875910
911+ /// Device enumeration MUST NOT panic for typical host/device states.
876912 #[ test]
877913 fn enumerate_devices_does_not_panic ( ) {
878914 let _result = enumerate_devices ( ) ;
879915 return ;
880916 }
881917
918+ /// Callback-based builder MUST NOT panic for typical host/device states.
882919 #[ test]
883920 fn build_with_output_callback_does_not_panic ( ) {
884921 let result = AudioDeviceBuilder :: new ( ) . build_with_output_callback (
@@ -894,6 +931,7 @@ mod tests {
894931 return ;
895932 }
896933
934+ /// Callback adapter MUST clear and then invoke the callback for `f32`.
897935 #[ test]
898936 fn invoke_output_callback_on_buffer_clears_and_invokes_callback_f32 ( ) {
899937 let mut buffer_f32 = [ 1.0 , -1.0 , 0.5 , -0.5 ] ;
@@ -923,8 +961,10 @@ mod tests {
923961
924962 assert ! ( callback_called) ;
925963 assert_eq ! ( buffer_f32, [ 0.5 , 0.0 , 0.0 , 0.0 ] ) ;
964+ return ;
926965 }
927966
967+ /// Callback adapter MUST clear and then invoke the callback for `i16`.
928968 #[ test]
929969 fn invoke_output_callback_on_buffer_clears_and_invokes_callback_i16 ( ) {
930970 let mut buffer_i16 = [ 1 , -1 , 200 , -200 ] ;
@@ -952,8 +992,10 @@ mod tests {
952992
953993 assert ! ( callback_called) ;
954994 assert_eq ! ( buffer_i16, [ 32767 , 0 , 0 , 0 ] ) ;
995+ return ;
955996 }
956997
998+ /// Callback adapter MUST clear and then invoke the callback for `u16`.
957999 #[ test]
9581000 fn invoke_output_callback_on_buffer_clears_and_invokes_callback_u16 ( ) {
9591001 let mut buffer_u16 = [ 0 , 1 , 65535 , 12345 ] ;
@@ -981,8 +1023,10 @@ mod tests {
9811023
9821024 assert ! ( callback_called) ;
9831025 assert_eq ! ( buffer_u16, [ 0 , 32768 , 32768 , 32768 ] ) ;
1026+ return ;
9841027 }
9851028
1029+ /// Writer silence MUST match each sample format's conventions.
9861030 #[ test]
9871031 fn writer_clear_sets_silence_for_all_formats ( ) {
9881032 let mut buffer_f32 = [ 1.0 , -1.0 , 0.5 , -0.5 ] ;
@@ -1008,8 +1052,10 @@ mod tests {
10081052 ) ;
10091053 writer. clear ( ) ;
10101054 assert_eq ! ( buffer_u16, [ 32768 , 32768 , 32768 , 32768 ] ) ;
1055+ return ;
10111056 }
10121057
1058+ /// Writer MUST clamp normalized samples and convert to output formats.
10131059 #[ test]
10141060 fn writer_set_sample_clamps_and_converts ( ) {
10151061 let mut buffer_f32 = [ 0.0 , 0.0 , 0.0 , 0.0 ] ;
@@ -1045,8 +1091,10 @@ mod tests {
10451091 assert_eq ! ( buffer_u16[ 0 ] , 0 ) ;
10461092 assert_eq ! ( buffer_u16[ 1 ] , 32768 ) ;
10471093 assert_eq ! ( buffer_u16[ 2 ] , 65535 ) ;
1094+ return ;
10481095 }
10491096
1097+ /// Out-of-range indices MUST be treated as no-ops.
10501098 #[ test]
10511099 fn writer_set_sample_is_noop_for_out_of_range_indices ( ) {
10521100 let mut buffer_f32 = [ 0.25 , 0.25 , 0.25 , 0.25 ] ;
@@ -1059,8 +1107,10 @@ mod tests {
10591107 writer. set_sample ( 0 , 10 , 1.0 ) ;
10601108
10611109 assert_eq ! ( buffer_f32, [ 0.25 , 0.25 , 0.25 , 0.25 ] ) ;
1110+ return ;
10621111 }
10631112
1113+ /// Config selection MUST prefer `f32` when available.
10641114 #[ test]
10651115 fn select_output_stream_config_prefers_f32_when_available ( ) {
10661116 let supported_configs = [
@@ -1084,8 +1134,10 @@ mod tests {
10841134 select_output_stream_config ( & supported_configs, None , None ) . unwrap ( ) ;
10851135 assert_eq ! ( selected. sample_format( ) , cpal_backend:: SampleFormat :: F32 ) ;
10861136 assert_eq ! ( selected. sample_rate( ) , 48_000 ) ;
1137+ return ;
10871138 }
10881139
1140+ /// Config selection MUST honor exact requested channel counts.
10891141 #[ test]
10901142 fn select_output_stream_config_respects_requested_channels ( ) {
10911143 let supported_configs = [ cpal_backend:: SupportedStreamConfigRange :: new (
@@ -1108,8 +1160,10 @@ mod tests {
11081160 requested_channels: Some ( 1 ) ,
11091161 } )
11101162 ) ) ;
1163+ return ;
11111164 }
11121165
1166+ /// Config selection MUST honor requested sample rates when available.
11131167 #[ test]
11141168 fn select_output_stream_config_respects_requested_sample_rate ( ) {
11151169 let supported_configs = [ cpal_backend:: SupportedStreamConfigRange :: new (
@@ -1134,5 +1188,6 @@ mod tests {
11341188 requested_channels: None ,
11351189 } )
11361190 ) ) ;
1191+ return ;
11371192 }
11381193}
0 commit comments