Skip to main content

max / audiofiles

Reuse SampleBuffer across packets in preview decode loops Both decode_to_f32 and start_streaming_decode allocated a fresh SampleBuffer<f32> per packet. Hoist the allocation outside the loop and reallocate only when capacity is insufficient. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-05-14 19:23 UTC
Commit: 4b4b192f259bd12764189169bbffd65a4ae3267f
Parent: f148f11
1 file changed, +24 insertions, -10 deletions
@@ -123,6 +123,9 @@ pub fn decode_to_f32(path: &Path) -> Result<PreviewBuffer, PreviewError> {
123 123 // that bypass the streaming threshold.
124 124 const MAX_SAMPLES: usize = 10 * 60 * 48_000 * 2;
125 125
126 + // Reuse SampleBuffer across packets to avoid per-packet allocation.
127 + let mut sample_buf: Option<SampleBuffer<f32>> = None;
128 +
126 129 loop {
127 130 let packet = match format.next_packet() {
128 131 Ok(p) => p,
@@ -148,12 +151,16 @@ pub fn decode_to_f32(path: &Path) -> Result<PreviewBuffer, PreviewError> {
148 151 let num_frames = decoded.frames();
149 152 let num_channels = spec.channels.count();
150 153
151 - let mut sample_buf = SampleBuffer::<f32>::new(
152 - num_frames as u64,
153 - *decoded.spec(),
154 - );
155 - sample_buf.copy_interleaved_ref(decoded);
156 - let samples = sample_buf.samples();
154 + // Reallocate only when the buffer can't fit this packet.
155 + let buf = match &mut sample_buf {
156 + Some(buf) if buf.capacity() >= num_frames => buf,
157 + _ => {
158 + sample_buf = Some(SampleBuffer::<f32>::new(num_frames as u64, spec));
159 + sample_buf.as_mut().unwrap()
160 + }
161 + };
162 + buf.copy_interleaved_ref(decoded);
163 + let samples = buf.samples();
157 164
158 165 // Convert to interleaved stereo
159 166 interleaved_to_stereo(samples, num_channels, num_frames, &mut all_samples);
@@ -317,6 +324,8 @@ pub fn start_streaming_decode(
317 324 std::thread::spawn(move || {
318 325 let mut total_frames = 0usize;
319 326 let mut started = false;
327 + // Reuse SampleBuffer across packets to avoid per-packet allocation.
328 + let mut sample_buf: Option<SampleBuffer<f32>> = None;
320 329
321 330 loop {
322 331 // Check if a newer decode has started — if so, this thread exits
@@ -350,10 +359,15 @@ pub fn start_streaming_decode(
350 359 let num_frames = decoded.frames();
351 360 let num_channels = spec.channels.count();
352 361
353 - let mut sample_buf =
354 - SampleBuffer::<f32>::new(num_frames as u64, *decoded.spec());
355 - sample_buf.copy_interleaved_ref(decoded);
356 - let samples = sample_buf.samples();
362 + let buf = match &mut sample_buf {
363 + Some(buf) if buf.capacity() >= num_frames => buf,
364 + _ => {
365 + sample_buf = Some(SampleBuffer::<f32>::new(num_frames as u64, spec));
366 + sample_buf.as_mut().unwrap()
367 + }
368 + };
369 + buf.copy_interleaved_ref(decoded);
370 + let samples = buf.samples();
357 371
358 372 // Convert to interleaved stereo in a local batch
359 373 let mut batch = Vec::with_capacity(num_frames * 2);