rlx_orpheus/decoder/
backend.rs1use std::path::Path;
4
5use anyhow::{Result, bail};
6#[cfg(feature = "coreml")]
7use rlx_runtime::{Device, is_available};
8
9use super::eager::SnacDecoder;
10
11#[derive(Debug, Clone, Copy, Default)]
13pub struct SnacLoadOptions {
14 pub coreml: bool,
16}
17
18pub enum SnacBackend {
20 Eager(SnacDecoder),
21 #[cfg(feature = "coreml")]
22 Rlx(super::compiled::RlxSnacDecoder),
23}
24
25impl SnacBackend {
26 pub fn open(path: &Path, opts: SnacLoadOptions) -> Result<Self> {
27 if opts.coreml {
28 #[cfg(feature = "coreml")]
29 {
30 if !is_available(Device::Ane) {
31 bail!(
32 "SNAC CoreML (Device::Ane) is not available — rebuild with \
33 `--features coreml` on macOS"
34 );
35 }
36 return Ok(Self::Rlx(super::compiled::RlxSnacDecoder::load(
37 path,
38 Device::Ane,
39 )?));
40 }
41 #[cfg(not(feature = "coreml"))]
42 {
43 bail!(
44 "SNAC CoreML requested but rlx-orpheus was built without \
45 `--features coreml`"
46 );
47 }
48 }
49 Ok(Self::Eager(SnacDecoder::from_file(path)?))
50 }
51
52 pub fn decode_codes(
53 &self,
54 codes_0: &[i32],
55 codes_1: &[i32],
56 codes_2: &[i32],
57 ) -> Result<Vec<f32>> {
58 match self {
59 Self::Eager(d) => d.decode_codes(codes_0, codes_1, codes_2),
60 #[cfg(feature = "coreml")]
61 Self::Rlx(d) => d.decode_codes(codes_0, codes_1, codes_2),
62 }
63 }
64
65 pub fn decode_orpheus_frames(&self, frame_tokens: &[i32]) -> Result<Vec<f32>> {
66 match self {
67 Self::Eager(d) => d.decode_orpheus_frames(frame_tokens),
68 #[cfg(feature = "coreml")]
69 Self::Rlx(d) => d.decode_orpheus_frames(frame_tokens),
70 }
71 }
72}