Skip to content

Commit 4d97810

Browse files
authored
rewrite player pipeline with cpal and state events & bump rubato version to 1.0.1 (#12)
2 parents 9276604 + 0064a05 commit 4d97810

File tree

16 files changed

+1589
-767
lines changed

16 files changed

+1589
-767
lines changed

Cargo.lock

Lines changed: 168 additions & 281 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ version = "0.1.0"
2424
# Shared dependencies that can be inherited by workspace members
2525
[workspace.dependencies]
2626
approx = "0.5.1"
27+
audioadapter-buffers = "2.0.0"
2728
atomic_float = "1.1.0"
2829
itertools = "0.14.0"
2930
ndarray = "0.17.1"
3031
num-traits = "0.2.19"
3132
parking_lot = "0.12.5"
33+
rubato = "1.0.1"
3234
serde = { version = "1", features = ["derive"] }
3335
serde_json = "1"
3436

src-tauri/Cargo.toml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ tauri-build = { version = "2", features = ["codegen"] }
2121
[dependencies]
2222
# console-subscriber = "0.4.0"
2323
anyhow = "1"
24+
audioadapter-buffers = { workspace = true }
2425
atomic_float = { workspace = true }
2526
const_format = "0.2.35"
26-
cpal = "0.16.0"
27+
cpal = "0.17.3"
2728
crossbeam-channel = "0.5.15"
2829
dunce = "1.0.5"
2930
ebur128 = "0.1.10"
@@ -38,6 +39,7 @@ parking_lot = { workspace = true }
3839
rayon = "1.11.0"
3940
readonly = "0.2.13"
4041
realfft = "3.5.0"
42+
rubato = { workspace = true }
4143
serde = { workspace = true }
4244
serde_json = { workspace = true }
4345
tauri = { version = "2", features = ["protocol-asset"] }
@@ -51,10 +53,6 @@ thesia-common = { path = "../src-common" }
5153
tokio = "1"
5254
tokio-rayon = "2.1.0"
5355

54-
[dependencies.kittyaudio]
55-
git = "https://github.com/Sytronik/kittyaudio.git"
56-
rev = "549b6764da73724336b7539cf773b653c01d9420"
57-
5856
[dependencies.symphonia]
5957
default-features = false
6058
features = [

src-tauri/src/core/audio.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use std::fs;
33
use std::io;
44
use std::path::Path;
55

6-
use kittyaudio::Frame;
76
use ndarray::prelude::*;
87
use rayon::prelude::*;
98
use serde::Deserialize;
@@ -178,19 +177,17 @@ impl GuardClipping<Ix2> for Audio {
178177
}
179178
}
180179

181-
impl From<&Audio> for Vec<Frame> {
182-
fn from(value: &Audio) -> Self {
183-
value
184-
.view()
185-
.axis_iter(Axis(1))
186-
.map(|frame| {
187-
match frame.len() {
188-
1 => frame[0].into(),
189-
2 => (frame[0], frame[1]).into(),
190-
_ => unimplemented!(), // TODO
191-
}
192-
})
193-
.collect()
180+
impl Audio {
181+
pub fn interleaved_samples(&self) -> Vec<f32> {
182+
let n_ch = self.wavs.shape()[0];
183+
let n_sample = self.wavs.shape()[1];
184+
let mut samples = Vec::with_capacity(n_ch * n_sample);
185+
for i in 0..n_sample {
186+
for ch in 0..n_ch {
187+
samples.push(self.wavs[(ch, i)]);
188+
}
189+
}
190+
samples
194191
}
195192
}
196193

src-tauri/src/core/track.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::path::PathBuf;
44
use std::sync::Arc;
55

66
use identity_hash::{IntMap, IntSet};
7-
use kittyaudio::Frame;
87
use ndarray::prelude::*;
98
use rayon::prelude::*;
109
use symphonia::core::errors::Error as SymphoniaError;
@@ -94,8 +93,8 @@ impl AudioTrack {
9493
self.audio.channel(ch)
9594
}
9695

97-
pub fn interleaved_frames(&self) -> Vec<Frame> {
98-
self.audio.as_ref().into()
96+
pub fn interleaved_samples(&self) -> Vec<f32> {
97+
self.audio.interleaved_samples()
9998
}
10099

101100
#[inline]

src-tauri/src/interface.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,6 @@ pub struct ConstsAndUserSettings {
100100
pub user_settings: UserSettings,
101101
}
102102

103-
#[derive(Serialize, Deserialize)]
104-
#[serde(rename_all = "camelCase")]
105-
pub struct PlayerState {
106-
pub is_playing: bool,
107-
pub position_sec: f64,
108-
pub err: String,
109-
}
110-
111103
#[derive(Serialize)]
112104
#[serde(rename_all = "camelCase")]
113105
pub struct Spectrogram<'a> {

src-tauri/src/lib.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ mod player;
2121

2222
use core::*;
2323
use interface::*;
24-
use player::{PlayerCommand, PlayerNotification};
24+
use player::PlayerCommand;
2525
use tauri_plugin_window_state::{AppHandleExt, StateFlags, WindowExt};
2626

2727
#[cfg(all(
@@ -83,7 +83,7 @@ fn init(app: AppHandle, colormap_length: u32) -> tauri::Result<ConstsAndUserSett
8383
let settings_json = json!(user_settings);
8484
_set_user_settings(&app, settings_json, false)?;
8585

86-
player::spawn_task();
86+
player::spawn_task(app);
8787
Ok(ConstsAndUserSettings {
8888
constants: Default::default(),
8989
user_settings,
@@ -498,22 +498,6 @@ async fn resume_player() {
498498
player::send(PlayerCommand::Resume).await;
499499
}
500500

501-
#[tauri::command]
502-
fn get_player_state() -> PlayerState {
503-
match player::recv() {
504-
PlayerNotification::Ok(state) => PlayerState {
505-
is_playing: state.is_playing,
506-
position_sec: state.position_sec,
507-
err: "".to_string(),
508-
},
509-
PlayerNotification::Err(e_str) => PlayerState {
510-
is_playing: false,
511-
position_sec: 0.,
512-
err: e_str,
513-
},
514-
}
515-
}
516-
517501
#[inline]
518502
async fn _refresh_track_player() {
519503
player::send(PlayerCommand::SetTrack((None, None))).await;
@@ -763,7 +747,6 @@ pub fn run() {
763747
seek_player,
764748
pause_player,
765749
resume_player,
766-
get_player_state,
767750
menu::enable_edit_menu,
768751
menu::disable_edit_menu,
769752
menu::enable_axis_zoom_menu,

0 commit comments

Comments
 (0)