74 lines
2.5 KiB
Rust
74 lines
2.5 KiB
Rust
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
use molotov_core::audio::buffer::AudioRingBuffer;
|
|
use molotov_core::audio::c_api::*;
|
|
use molotov_core::audio::types::AAudioResult;
|
|
|
|
#[test]
|
|
fn test_ring_buffer_overrun_no_panic_and_preserves_frames() {
|
|
let mut buffer = AudioRingBuffer::new_framed(4, 2); // 4 frames capacity, 2 channels per frame
|
|
// Write 6 stereo frames (12 samples): [L0, R0, L1, R1, ...]
|
|
let samples = [
|
|
1.0, 1.5,
|
|
2.0, 2.5,
|
|
3.0, 3.5,
|
|
4.0, 4.5,
|
|
5.0, 5.5,
|
|
6.0, 6.5,
|
|
];
|
|
|
|
// Must not panic on overrun
|
|
buffer.write_frames(&samples);
|
|
|
|
let mut out = [0.0f32; 8]; // Read 4 frames (8 samples)
|
|
let read_frames = buffer.read_frames(&mut out);
|
|
assert_eq!(read_frames, 4);
|
|
|
|
// Channels must remain aligned: left has .fract() == 0.0, right has .fract() == 0.5
|
|
for i in 0..4 {
|
|
let left = out[i * 2];
|
|
let right = out[i * 2 + 1];
|
|
assert_eq!(left.fract(), 0.0, "Left channel phase shifted: {}", left);
|
|
assert_eq!(right.fract(), 0.5, "Right channel phase shifted: {}", right);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_ring_buffer_underrun_fills_silence() {
|
|
let mut buffer = AudioRingBuffer::new_framed(8, 1);
|
|
buffer.write_frames(&[0.5, 0.6]); // 2 frames
|
|
|
|
let mut out = [9.9f32; 6]; // Request 6 frames
|
|
let read_frames = buffer.read_frames(&mut out);
|
|
assert_eq!(read_frames, 2);
|
|
assert_eq!(out[0], 0.5);
|
|
assert_eq!(out[1], 0.6);
|
|
// Unread frames must be filled with silence (0.0)
|
|
for &sample in &out[2..6] {
|
|
assert_eq!(sample, 0.0, "Underrun must fill silence");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_c_api_double_close_safety_handle_registry() {
|
|
unsafe {
|
|
let mut builder = std::ptr::null_mut();
|
|
AAudio_createStreamBuilder(&mut builder);
|
|
|
|
let mut stream = std::ptr::null_mut();
|
|
AAudioStreamBuilder_openStream(builder, &mut stream);
|
|
assert!(!stream.is_null());
|
|
|
|
// First close succeeds
|
|
let res1 = AAudioStream_close(stream);
|
|
assert_eq!(res1, AAudioResult::Ok as i32);
|
|
|
|
// Second close must NOT double-free; it safely returns ErrorInvalidHandle
|
|
let res2 = AAudioStream_close(stream);
|
|
assert_eq!(res2, AAudioResult::ErrorInvalidHandle as i32);
|
|
|
|
// Delete builder
|
|
assert_eq!(AAudioStreamBuilder_delete(builder), AAudioResult::Ok as i32);
|
|
// Double delete builder also safe
|
|
assert_eq!(AAudioStreamBuilder_delete(builder), AAudioResult::ErrorInvalidHandle as i32);
|
|
}
|
|
}
|