agent: lumotia-rebrand — drop MagnotiaError prefix, now lumotia_core::Error
Phase 3 of the rebrand cascade per locked decision D4. MagnotiaError -> Error in crates/core/src/error.rs (the crate name already qualifies it). 92 usages across 14 .rs files renamed via word-boundary sed. One collision required disambiguation: lumotia_storage already had its own local Error type (introduced by the slop-pass Area A residuals work). crates/storage/src/error.rs aliases the imported core error as CoreError on import; the From<Error> for CoreError boundary impl and the CoreError::Storage construction site use the alias. cargo build --workspace passes. cargo test --workspace: 330 pass, 0 fail. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use lumotia_core::error::{MagnotiaError, Result};
|
||||
use lumotia_core::error::{Error, Result};
|
||||
|
||||
const AUDIO_CHANNEL_CAPACITY: usize = 32;
|
||||
|
||||
@@ -106,7 +106,7 @@ impl MicrophoneCapture {
|
||||
|
||||
let devices = host
|
||||
.input_devices()
|
||||
.map_err(|e| MagnotiaError::AudioCaptureFailed(format!("input_devices: {e}")))?;
|
||||
.map_err(|e| Error::AudioCaptureFailed(format!("input_devices: {e}")))?;
|
||||
|
||||
// Load ALSA card descriptions once per enumeration. These are the
|
||||
// "real" product names (e.g. "Blue Microphones") that cpal's
|
||||
@@ -144,7 +144,7 @@ impl MicrophoneCapture {
|
||||
let host = cpal::default_host();
|
||||
let devices = host
|
||||
.input_devices()
|
||||
.map_err(|e| MagnotiaError::AudioCaptureFailed(format!("input_devices: {e}")))?;
|
||||
.map_err(|e| Error::AudioCaptureFailed(format!("input_devices: {e}")))?;
|
||||
|
||||
for device in devices {
|
||||
let name = device_display_name(&device).unwrap_or_default();
|
||||
@@ -154,7 +154,7 @@ impl MicrophoneCapture {
|
||||
}
|
||||
}
|
||||
|
||||
Err(MagnotiaError::AudioCaptureFailed(format!(
|
||||
Err(Error::AudioCaptureFailed(format!(
|
||||
"Selected device '{device_name}' not found in current host enumeration. \
|
||||
It may have been disconnected. Open Settings → Audio to pick another."
|
||||
)))
|
||||
@@ -178,7 +178,7 @@ impl MicrophoneCapture {
|
||||
|
||||
let mut all_devices: Vec<cpal::Device> = host
|
||||
.input_devices()
|
||||
.map_err(|e| MagnotiaError::AudioCaptureFailed(format!("input_devices: {e}")))?
|
||||
.map_err(|e| Error::AudioCaptureFailed(format!("input_devices: {e}")))?
|
||||
.collect();
|
||||
|
||||
// Sort: default first, then non-monitor, then monitor-as-last-resort.
|
||||
@@ -237,7 +237,7 @@ impl MicrophoneCapture {
|
||||
}
|
||||
}
|
||||
|
||||
Err(MagnotiaError::AudioCaptureFailed(
|
||||
Err(Error::AudioCaptureFailed(
|
||||
"No working microphone found. Check that an input device is connected, \
|
||||
that PulseAudio/PipeWire is running, and that the app has microphone permission. \
|
||||
Then open Settings → Audio to pick a device explicitly."
|
||||
@@ -361,7 +361,7 @@ fn open_and_validate(
|
||||
) -> Result<(MicrophoneCapture, mpsc::Receiver<AudioChunk>)> {
|
||||
let config = device
|
||||
.default_input_config()
|
||||
.map_err(|e| MagnotiaError::AudioCaptureFailed(format!("default_input_config: {e}")))?;
|
||||
.map_err(|e| Error::AudioCaptureFailed(format!("default_input_config: {e}")))?;
|
||||
let sample_rate = config.sample_rate();
|
||||
let channels = config.channels();
|
||||
let format = config.sample_format();
|
||||
@@ -422,16 +422,16 @@ fn open_and_validate(
|
||||
name.to_string(),
|
||||
),
|
||||
other => {
|
||||
return Err(MagnotiaError::AudioCaptureFailed(format!(
|
||||
return Err(Error::AudioCaptureFailed(format!(
|
||||
"unsupported sample format {other:?}"
|
||||
)))
|
||||
}
|
||||
}
|
||||
.map_err(|e| MagnotiaError::AudioCaptureFailed(format!("build_input_stream: {e}")))?;
|
||||
.map_err(|e| Error::AudioCaptureFailed(format!("build_input_stream: {e}")))?;
|
||||
|
||||
stream
|
||||
.play()
|
||||
.map_err(|e| MagnotiaError::AudioCaptureFailed(format!("stream.play: {e}")))?;
|
||||
.map_err(|e| Error::AudioCaptureFailed(format!("stream.play: {e}")))?;
|
||||
|
||||
// Validation window: collect chunks for DEVICE_VALIDATION_MS, compute RMS.
|
||||
let deadline =
|
||||
@@ -460,7 +460,7 @@ fn open_and_validate(
|
||||
}
|
||||
|
||||
if total_samples == 0 {
|
||||
return Err(MagnotiaError::AudioCaptureFailed(
|
||||
return Err(Error::AudioCaptureFailed(
|
||||
"device delivered zero samples in validation window".into(),
|
||||
));
|
||||
}
|
||||
@@ -475,7 +475,7 @@ fn open_and_validate(
|
||||
);
|
||||
|
||||
if require_audio && rms < SILENCE_RMS_FLOOR {
|
||||
return Err(MagnotiaError::AudioCaptureFailed(format!(
|
||||
return Err(Error::AudioCaptureFailed(format!(
|
||||
"device produced silence (rms={rms:.6} below floor {SILENCE_RMS_FLOOR:.6})"
|
||||
)));
|
||||
}
|
||||
@@ -485,7 +485,7 @@ fn open_and_validate(
|
||||
// long stream of f32 zeros from a borked device — that is worse than
|
||||
// failing fast.
|
||||
if rms < DEAD_SILENCE_FLOOR {
|
||||
return Err(MagnotiaError::AudioCaptureFailed(format!(
|
||||
return Err(Error::AudioCaptureFailed(format!(
|
||||
"device produced dead silence (rms={rms:.6e} below absolute floor {DEAD_SILENCE_FLOOR:.6e})"
|
||||
)));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ pub async fn decode_and_resample(path: &Path) -> Result<AudioSamples> {
|
||||
})
|
||||
.await
|
||||
.map_err(|e| {
|
||||
lumotia_core::error::MagnotiaError::AudioDecodeFailed(format!("Task join error: {e}"))
|
||||
lumotia_core::error::Error::AudioDecodeFailed(format!("Task join error: {e}"))
|
||||
})?
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ use symphonia::core::io::MediaSourceStream;
|
||||
use symphonia::core::meta::MetadataOptions;
|
||||
use symphonia::core::probe::Hint;
|
||||
|
||||
use lumotia_core::error::{MagnotiaError, Result};
|
||||
use lumotia_core::error::{Error, Result};
|
||||
use lumotia_core::types::AudioSamples;
|
||||
|
||||
/// Decode an audio file to mono f32 PCM samples.
|
||||
/// Supports all formats symphonia handles: mp3, aac, flac, wav, ogg, etc.
|
||||
///
|
||||
/// Any read- or decode-side error is propagated as `MagnotiaError::AudioDecodeFailed`.
|
||||
/// Any read- or decode-side error is propagated as `Error::AudioDecodeFailed`.
|
||||
/// A previous implementation `break`ed out of the packet loop on any read
|
||||
/// error and skipped per-packet decode errors, so a truncated or corrupt
|
||||
/// input silently returned `Ok` with whatever had decoded before the
|
||||
@@ -29,7 +29,7 @@ pub fn decode_audio_file_limited(
|
||||
max_duration_secs: Option<f64>,
|
||||
) -> Result<AudioSamples> {
|
||||
let file = File::open(path)
|
||||
.map_err(|e| MagnotiaError::AudioDecodeFailed(format!("Cannot open file: {e}")))?;
|
||||
.map_err(|e| Error::AudioDecodeFailed(format!("Cannot open file: {e}")))?;
|
||||
let mss = MediaSourceStream::new(Box::new(file), Default::default());
|
||||
|
||||
let mut hint = Hint::new();
|
||||
@@ -42,7 +42,7 @@ pub fn decode_audio_file_limited(
|
||||
|
||||
pub fn probe_audio_duration_secs(path: &Path) -> Result<Option<f64>> {
|
||||
let file = File::open(path)
|
||||
.map_err(|e| MagnotiaError::AudioDecodeFailed(format!("Cannot open file: {e}")))?;
|
||||
.map_err(|e| Error::AudioDecodeFailed(format!("Cannot open file: {e}")))?;
|
||||
let mss = MediaSourceStream::new(Box::new(file), Default::default());
|
||||
let mut hint = Hint::new();
|
||||
if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
|
||||
@@ -56,15 +56,15 @@ pub fn probe_audio_duration_secs(path: &Path) -> Result<Option<f64>> {
|
||||
&FormatOptions::default(),
|
||||
&MetadataOptions::default(),
|
||||
)
|
||||
.map_err(|e| MagnotiaError::AudioDecodeFailed(format!("Unsupported format: {e}")))?;
|
||||
.map_err(|e| Error::AudioDecodeFailed(format!("Unsupported format: {e}")))?;
|
||||
let track = probed
|
||||
.format
|
||||
.default_track()
|
||||
.ok_or_else(|| MagnotiaError::AudioDecodeFailed("No audio track found".into()))?;
|
||||
.ok_or_else(|| Error::AudioDecodeFailed("No audio track found".into()))?;
|
||||
let sample_rate = track
|
||||
.codec_params
|
||||
.sample_rate
|
||||
.ok_or_else(|| MagnotiaError::AudioDecodeFailed("Unknown sample rate".into()))?;
|
||||
.ok_or_else(|| Error::AudioDecodeFailed("Unknown sample rate".into()))?;
|
||||
Ok(track
|
||||
.codec_params
|
||||
.n_frames
|
||||
@@ -86,20 +86,20 @@ fn decode_media_stream(
|
||||
&FormatOptions::default(),
|
||||
&MetadataOptions::default(),
|
||||
)
|
||||
.map_err(|e| MagnotiaError::AudioDecodeFailed(format!("Unsupported format: {e}")))?;
|
||||
.map_err(|e| Error::AudioDecodeFailed(format!("Unsupported format: {e}")))?;
|
||||
|
||||
let mut format = probed.format;
|
||||
|
||||
let track = format
|
||||
.default_track()
|
||||
.ok_or_else(|| MagnotiaError::AudioDecodeFailed("No audio track found".into()))?;
|
||||
.ok_or_else(|| Error::AudioDecodeFailed("No audio track found".into()))?;
|
||||
let sample_rate = track
|
||||
.codec_params
|
||||
.sample_rate
|
||||
.ok_or_else(|| MagnotiaError::AudioDecodeFailed("Unknown sample rate".into()))?;
|
||||
.ok_or_else(|| Error::AudioDecodeFailed("Unknown sample rate".into()))?;
|
||||
|
||||
if sample_rate == 0 {
|
||||
return Err(MagnotiaError::AudioDecodeFailed(
|
||||
return Err(Error::AudioDecodeFailed(
|
||||
"Invalid sample rate: 0".into(),
|
||||
));
|
||||
}
|
||||
@@ -109,7 +109,7 @@ fn decode_media_stream(
|
||||
|
||||
let mut decoder = symphonia::default::get_codecs()
|
||||
.make(&track.codec_params, &DecoderOptions::default())
|
||||
.map_err(|e| MagnotiaError::AudioDecodeFailed(format!("Codec error: {e}")))?;
|
||||
.map_err(|e| Error::AudioDecodeFailed(format!("Codec error: {e}")))?;
|
||||
|
||||
let mut samples: Vec<f32> = Vec::new();
|
||||
|
||||
@@ -123,12 +123,12 @@ fn decode_media_stream(
|
||||
break;
|
||||
}
|
||||
Err(SymphoniaError::ResetRequired) => {
|
||||
return Err(MagnotiaError::AudioDecodeFailed(
|
||||
return Err(Error::AudioDecodeFailed(
|
||||
"decoder reset required mid-stream — input contains a discontinuity".into(),
|
||||
));
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(MagnotiaError::AudioDecodeFailed(format!(
|
||||
return Err(Error::AudioDecodeFailed(format!(
|
||||
"packet read failed: {e}"
|
||||
)));
|
||||
}
|
||||
@@ -140,7 +140,7 @@ fn decode_media_stream(
|
||||
|
||||
let decoded = decoder
|
||||
.decode(&packet)
|
||||
.map_err(|e| MagnotiaError::AudioDecodeFailed(format!("packet decode failed: {e}")))?;
|
||||
.map_err(|e| Error::AudioDecodeFailed(format!("packet decode failed: {e}")))?;
|
||||
|
||||
let spec = *decoded.spec();
|
||||
let channels = spec.channels.count();
|
||||
@@ -160,7 +160,7 @@ fn decode_media_stream(
|
||||
.map(|limit| samples.len() > limit)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return Err(MagnotiaError::AudioDecodeFailed(format!(
|
||||
return Err(Error::AudioDecodeFailed(format!(
|
||||
"Audio is longer than the {:.0} minute import limit",
|
||||
max_duration_secs.unwrap_or(0.0) / 60.0
|
||||
)));
|
||||
@@ -168,7 +168,7 @@ fn decode_media_stream(
|
||||
}
|
||||
|
||||
if samples.is_empty() {
|
||||
return Err(MagnotiaError::AudioDecodeFailed(
|
||||
return Err(Error::AudioDecodeFailed(
|
||||
"No audio data decoded".into(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use rubato::{
|
||||
};
|
||||
|
||||
use lumotia_core::constants::WHISPER_SAMPLE_RATE;
|
||||
use lumotia_core::error::{MagnotiaError, Result};
|
||||
use lumotia_core::error::{Error, Result};
|
||||
use lumotia_core::types::AudioSamples;
|
||||
|
||||
/// Resample audio to 16kHz mono using sinc interpolation (rubato).
|
||||
@@ -17,7 +17,7 @@ pub fn resample_to_16khz(audio: &AudioSamples) -> Result<AudioSamples> {
|
||||
}
|
||||
|
||||
if from_rate == 0 {
|
||||
return Err(MagnotiaError::AudioDecodeFailed(
|
||||
return Err(Error::AudioDecodeFailed(
|
||||
"Cannot resample: source rate is 0".into(),
|
||||
));
|
||||
}
|
||||
@@ -36,7 +36,7 @@ pub fn resample_to_16khz(audio: &AudioSamples) -> Result<AudioSamples> {
|
||||
let mut resampler = SincFixedIn::<f32>::new(
|
||||
ratio, 1.1, params, chunk_size, 1, // mono
|
||||
)
|
||||
.map_err(|e| MagnotiaError::AudioDecodeFailed(format!("Resampler init failed: {e}")))?;
|
||||
.map_err(|e| Error::AudioDecodeFailed(format!("Resampler init failed: {e}")))?;
|
||||
|
||||
let samples = audio.samples();
|
||||
let mut output_samples: Vec<f32> = Vec::new();
|
||||
@@ -53,7 +53,7 @@ pub fn resample_to_16khz(audio: &AudioSamples) -> Result<AudioSamples> {
|
||||
let input = vec![chunk];
|
||||
let result = resampler
|
||||
.process(&input, None)
|
||||
.map_err(|e| MagnotiaError::AudioDecodeFailed(format!("Resample failed: {e}")))?;
|
||||
.map_err(|e| Error::AudioDecodeFailed(format!("Resample failed: {e}")))?;
|
||||
|
||||
if !result.is_empty() && !result[0].is_empty() {
|
||||
output_samples.extend_from_slice(&result[0]);
|
||||
|
||||
@@ -28,7 +28,7 @@ use rubato::{
|
||||
};
|
||||
|
||||
use lumotia_core::constants::WHISPER_SAMPLE_RATE;
|
||||
use lumotia_core::error::{MagnotiaError, Result};
|
||||
use lumotia_core::error::{Error, Result};
|
||||
|
||||
/// Number of input samples the rubato resampler consumes per `process()`
|
||||
/// call. Matches the chunk size used in `resample::resample_to_16khz`.
|
||||
@@ -51,7 +51,7 @@ impl StreamingResampler {
|
||||
/// rubato rejects the requested ratio.
|
||||
pub fn new(from_rate: u32) -> Result<Self> {
|
||||
if from_rate == 0 {
|
||||
return Err(MagnotiaError::AudioDecodeFailed(
|
||||
return Err(Error::AudioDecodeFailed(
|
||||
"StreamingResampler: input sample rate is 0".into(),
|
||||
));
|
||||
}
|
||||
@@ -78,7 +78,7 @@ impl StreamingResampler {
|
||||
1, // mono
|
||||
)
|
||||
.map_err(|e| {
|
||||
MagnotiaError::AudioDecodeFailed(format!("StreamingResampler init failed: {e}"))
|
||||
Error::AudioDecodeFailed(format!("StreamingResampler init failed: {e}"))
|
||||
})?;
|
||||
|
||||
Ok(Self::Sinc {
|
||||
@@ -110,7 +110,7 @@ impl StreamingResampler {
|
||||
let chunk: Vec<f32> = residual.drain(..INPUT_CHUNK).collect();
|
||||
let input = vec![chunk];
|
||||
let result = resampler.process(&input, None).map_err(|e| {
|
||||
MagnotiaError::AudioDecodeFailed(format!(
|
||||
Error::AudioDecodeFailed(format!(
|
||||
"StreamingResampler process failed: {e}"
|
||||
))
|
||||
})?;
|
||||
@@ -144,7 +144,7 @@ impl StreamingResampler {
|
||||
|
||||
let input = vec![chunk];
|
||||
let result = resampler.process(&input, None).map_err(|e| {
|
||||
MagnotiaError::AudioDecodeFailed(format!(
|
||||
Error::AudioDecodeFailed(format!(
|
||||
"StreamingResampler flush failed: {e}"
|
||||
))
|
||||
})?;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::io::BufWriter;
|
||||
use std::path::Path;
|
||||
|
||||
use lumotia_core::error::{MagnotiaError, Result};
|
||||
use lumotia_core::error::{Error, Result};
|
||||
use lumotia_core::types::AudioSamples;
|
||||
|
||||
/// Append-friendly WAV writer for long-running captures.
|
||||
@@ -40,10 +40,10 @@ impl WavWriter {
|
||||
bits_per_sample: 16,
|
||||
sample_format: hound::SampleFormat::Int,
|
||||
};
|
||||
let file = std::fs::File::create(path).map_err(MagnotiaError::from)?;
|
||||
let file = std::fs::File::create(path).map_err(Error::from)?;
|
||||
let buffered = BufWriter::new(file);
|
||||
let inner = hound::WavWriter::new(buffered, spec).map_err(|e| {
|
||||
MagnotiaError::from(std::io::Error::other(format!("WAV create failed: {e}")))
|
||||
Error::from(std::io::Error::other(format!("WAV create failed: {e}")))
|
||||
})?;
|
||||
Ok(Self {
|
||||
inner,
|
||||
@@ -61,7 +61,7 @@ impl WavWriter {
|
||||
let clamped = sample.clamp(-1.0, 1.0);
|
||||
let int_sample = (clamped * i16::MAX as f32) as i16;
|
||||
self.inner.write_sample(int_sample).map_err(|e| {
|
||||
MagnotiaError::from(std::io::Error::other(format!("WAV write failed: {e}")))
|
||||
Error::from(std::io::Error::other(format!("WAV write failed: {e}")))
|
||||
})?;
|
||||
}
|
||||
self.samples_since_flush += samples.len();
|
||||
@@ -78,7 +78,7 @@ impl WavWriter {
|
||||
/// boundaries (end-of-utterance, UI events) for tighter recovery.
|
||||
pub fn flush(&mut self) -> Result<()> {
|
||||
self.inner.flush().map_err(|e| {
|
||||
MagnotiaError::from(std::io::Error::other(format!("WAV flush failed: {e}")))
|
||||
Error::from(std::io::Error::other(format!("WAV flush failed: {e}")))
|
||||
})?;
|
||||
self.samples_since_flush = 0;
|
||||
Ok(())
|
||||
@@ -90,7 +90,7 @@ impl WavWriter {
|
||||
/// that care about the unflushed tail should always finalise.
|
||||
pub fn finalize(self) -> Result<()> {
|
||||
self.inner.finalize().map_err(|e| {
|
||||
MagnotiaError::from(std::io::Error::other(format!("WAV finalize failed: {e}")))
|
||||
Error::from(std::io::Error::other(format!("WAV finalize failed: {e}")))
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -106,19 +106,19 @@ pub fn write_wav(path: &Path, audio: &AudioSamples) -> Result<()> {
|
||||
};
|
||||
|
||||
let mut writer = hound::WavWriter::create(path, spec).map_err(|e| {
|
||||
MagnotiaError::from(std::io::Error::other(format!("WAV create failed: {e}")))
|
||||
Error::from(std::io::Error::other(format!("WAV create failed: {e}")))
|
||||
})?;
|
||||
|
||||
for &sample in audio.samples() {
|
||||
let clamped = sample.clamp(-1.0, 1.0);
|
||||
let int_sample = (clamped * i16::MAX as f32) as i16;
|
||||
writer.write_sample(int_sample).map_err(|e| {
|
||||
MagnotiaError::from(std::io::Error::other(format!("WAV write failed: {e}")))
|
||||
Error::from(std::io::Error::other(format!("WAV write failed: {e}")))
|
||||
})?;
|
||||
}
|
||||
|
||||
writer.finalize().map_err(|e| {
|
||||
MagnotiaError::from(std::io::Error::other(format!("WAV finalize failed: {e}")))
|
||||
Error::from(std::io::Error::other(format!("WAV finalize failed: {e}")))
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
@@ -126,14 +126,14 @@ pub fn write_wav(path: &Path, audio: &AudioSamples) -> Result<()> {
|
||||
|
||||
/// Read a WAV file to f32 PCM `AudioSamples`.
|
||||
///
|
||||
/// Any per-sample decode error is surfaced as `MagnotiaError::AudioDecodeFailed`
|
||||
/// Any per-sample decode error is surfaced as `Error::AudioDecodeFailed`
|
||||
/// rather than silently dropped. A previous implementation used
|
||||
/// `filter_map(|s| s.ok())`, so a truncated or corrupt payload returned
|
||||
/// a short, silently-partial `AudioSamples` — callers got `Ok` while
|
||||
/// losing audio (flagged by the 2026-04-22 review).
|
||||
pub fn read_wav(path: &Path) -> Result<AudioSamples> {
|
||||
let reader = hound::WavReader::open(path)
|
||||
.map_err(|e| MagnotiaError::AudioDecodeFailed(format!("WAV open failed: {e}")))?;
|
||||
.map_err(|e| Error::AudioDecodeFailed(format!("WAV open failed: {e}")))?;
|
||||
|
||||
let spec = reader.spec();
|
||||
let sample_rate = spec.sample_rate;
|
||||
@@ -147,7 +147,7 @@ pub fn read_wav(path: &Path) -> Result<AudioSamples> {
|
||||
sample
|
||||
.map(|s| s as f32 / (1 << (bits_per_sample - 1)) as f32)
|
||||
.map_err(|e| {
|
||||
MagnotiaError::AudioDecodeFailed(format!("WAV sample decode failed: {e}"))
|
||||
Error::AudioDecodeFailed(format!("WAV sample decode failed: {e}"))
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<f32>>>()?,
|
||||
@@ -155,7 +155,7 @@ pub fn read_wav(path: &Path) -> Result<AudioSamples> {
|
||||
.into_samples::<f32>()
|
||||
.map(|sample| {
|
||||
sample.map_err(|e| {
|
||||
MagnotiaError::AudioDecodeFailed(format!("WAV sample decode failed: {e}"))
|
||||
Error::AudioDecodeFailed(format!("WAV sample decode failed: {e}"))
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<f32>>>()?,
|
||||
|
||||
Reference in New Issue
Block a user