@@ -162,7 +162,7 @@ impl AACEncoder {
162162 let Some ( & rate) = rates
163163 . iter ( )
164164 . find ( |r| * * r >= input_config. rate ( ) )
165- . or ( rates. first ( ) )
165+ . or ( rates. last ( ) )
166166 else {
167167 return Err ( AACEncoderError :: RateNotSupported ( input_config. rate ( ) ) ) ;
168168 } ;
@@ -279,6 +279,74 @@ mod tests {
279279 use super :: * ;
280280 use ffmpeg:: ChannelLayout ;
281281
282+ #[ test]
283+ fn sample_rate_selection_preserves_supported_rates_and_clamps_outliers ( ) {
284+ let directory = tempfile:: tempdir ( ) . unwrap ( ) ;
285+ for ( input_rate, expected_rate) in [
286+ ( 4_000 , 7_350 ) ,
287+ ( 44_100 , 44_100 ) ,
288+ ( 45_000 , 48_000 ) ,
289+ ( 96_000 , 96_000 ) ,
290+ ( 192_000 , 96_000 ) ,
291+ ] {
292+ let mut output =
293+ format:: output ( & directory. path ( ) . join ( format ! ( "{input_rate}.mp4" ) ) ) . unwrap ( ) ;
294+ let encoder = AACEncoder :: init (
295+ AudioInfo :: new_raw ( Sample :: F32 ( Type :: Packed ) , input_rate, 1 ) ,
296+ & mut output,
297+ )
298+ . unwrap ( ) ;
299+ let stream = output. stream ( encoder. stream_index ( ) ) . unwrap ( ) ;
300+ let decoder = context:: Context :: from_parameters ( stream. parameters ( ) )
301+ . unwrap ( )
302+ . decoder ( )
303+ . audio ( )
304+ . unwrap ( ) ;
305+ assert_eq ! ( decoder. rate( ) , expected_rate, "input rate {input_rate}" ) ;
306+ }
307+ }
308+
309+ #[ test]
310+ fn high_rate_input_keeps_high_frequency_audio_through_encode_decode ( ) {
311+ let directory = tempfile:: tempdir ( ) . unwrap ( ) ;
312+ let path = directory. path ( ) . join ( "high-rate.mp4" ) ;
313+ let mut output = format:: output ( & path) . unwrap ( ) ;
314+ let mut encoder = AACEncoder :: init (
315+ AudioInfo :: new_raw ( Sample :: F32 ( Type :: Packed ) , 192_000 , 1 ) ,
316+ & mut output,
317+ )
318+ . unwrap ( ) ;
319+ output. write_header ( ) . unwrap ( ) ;
320+
321+ let mut audio = frame:: Audio :: new ( Sample :: F32 ( Type :: Packed ) , 192_000 , ChannelLayout :: MONO ) ;
322+ audio. set_rate ( 192_000 ) ;
323+ audio. set_pts ( Some ( 0 ) ) ;
324+ for ( index, sample) in audio. plane_mut :: < f32 > ( 0 ) . iter_mut ( ) . enumerate ( ) {
325+ * sample = 0.5 * ( std:: f32:: consts:: TAU * 12_000.0 * index as f32 / 192_000.0 ) . sin ( ) ;
326+ }
327+ encoder
328+ . send_frame ( audio, Duration :: MAX , & mut output)
329+ . unwrap ( ) ;
330+ encoder. flush ( & mut output) . unwrap ( ) ;
331+ output. write_trailer ( ) . unwrap ( ) ;
332+ drop ( encoder) ;
333+ drop ( output) ;
334+
335+ let ( samples, track_end) = decode_first_channel ( & path) ;
336+ assert_eq ! ( track_end, 48_000 ) ;
337+ assert ! ( samples. len( ) >= 96_000 , "decoded {} samples" , samples. len( ) ) ;
338+ let mut sine = 0.0 ;
339+ let mut cosine = 0.0 ;
340+ let signal = & samples[ 9_600 ..86_400 ] ;
341+ for ( index, sample) in signal. iter ( ) . enumerate ( ) {
342+ let phase = std:: f64:: consts:: TAU * 12_000.0 * index as f64 / 96_000.0 ;
343+ sine += f64:: from ( * sample) * phase. sin ( ) ;
344+ cosine += f64:: from ( * sample) * phase. cos ( ) ;
345+ }
346+ let amplitude = 2.0 * sine. hypot ( cosine) / signal. len ( ) as f64 ;
347+ assert ! ( amplitude > 0.4 , "12 kHz tone amplitude {amplitude}" ) ;
348+ }
349+
282350 fn input_frame ( start : i64 , samples : usize ) -> frame:: Audio {
283351 let mut audio =
284352 frame:: Audio :: new ( Sample :: F32 ( Type :: Packed ) , samples, ChannelLayout :: STEREO ) ;
0 commit comments