Skip to content

Commit 2a78623

Browse files
committed
perf: use Arc for audio buffer
1 parent 364865a commit 2a78623

2 files changed

Lines changed: 14 additions & 15 deletions

File tree

src-tauri/src/audio/player.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub struct PlaybackState {
5353
/// Commands sent to the audio thread
5454
enum AudioCommand {
5555
Play {
56-
audio_data: Vec<u8>,
56+
audio_data: Arc<[u8]>,
5757
metadata: SongMetadata,
5858
duration_secs: f64,
5959
normalization_gain: Option<f32>,
@@ -69,7 +69,7 @@ enum AudioCommand {
6969
/// Append a song to the existing player for gapless playback.
7070
/// Unlike Play, this does NOT create a new player.
7171
AppendGapless {
72-
audio_data: Vec<u8>,
72+
audio_data: Arc<[u8]>,
7373
metadata: SongMetadata,
7474
duration_secs: f64,
7575
normalization_gain: Option<f32>,
@@ -80,7 +80,7 @@ enum AudioCommand {
8080
/// Crossfade to a new song: keep the current sink fading out
8181
/// while a new sink fades in over the specified duration.
8282
CrossfadePlay {
83-
audio_data: Vec<u8>,
83+
audio_data: Arc<[u8]>,
8484
metadata: SongMetadata,
8585
duration_secs: f64,
8686
normalization_gain: Option<f32>,
@@ -94,7 +94,7 @@ enum AudioCommand {
9494

9595
#[derive(Debug)]
9696
pub struct CrossfadePlayRequest {
97-
pub audio_data: Vec<u8>,
97+
pub audio_data: Arc<[u8]>,
9898
pub metadata: SongMetadata,
9999
pub duration_secs: f64,
100100
pub normalization_gain: Option<f32>,
@@ -116,7 +116,6 @@ struct GaplessSegment {
116116
/// Inner playback state consolidated into a single struct for efficient locking
117117
struct PlaybackInner {
118118
current_song: Option<SongMetadata>,
119-
current_audio_data: Option<(Vec<u8>, u64)>, // (data, byte_len)
120119
volume: f32,
121120
playback_start: Option<Instant>,
122121
paused_position: f64,
@@ -130,7 +129,6 @@ impl Default for PlaybackInner {
130129
fn default() -> Self {
131130
Self {
132131
current_song: None,
133-
current_audio_data: None,
134132
volume: 0.8,
135133
playback_start: None,
136134
paused_position: 0.0,
@@ -285,7 +283,7 @@ impl AudioPlayer {
285283
#[allow(clippy::too_many_arguments)]
286284
pub fn play(
287285
&self,
288-
audio_data: Vec<u8>,
286+
audio_data: Arc<[u8]>,
289287
metadata: SongMetadata,
290288
duration_secs: f64,
291289
normalization_gain: Option<f32>,
@@ -311,7 +309,7 @@ impl AudioPlayer {
311309
#[allow(clippy::too_many_arguments)]
312310
pub fn append_gapless(
313311
&self,
314-
audio_data: Vec<u8>,
312+
audio_data: Arc<[u8]>,
315313
metadata: SongMetadata,
316314
duration_secs: f64,
317315
normalization_gain: Option<f32>,
@@ -876,7 +874,7 @@ fn run_audio_thread(
876874

877875
// Decode and play with coarse seek enabled for better seeking
878876
let byte_len = audio_data.len() as u64;
879-
let cursor = Cursor::new(audio_data.clone());
877+
let cursor = Cursor::new(audio_data);
880878
match Decoder::builder()
881879
.with_data(cursor)
882880
.with_byte_len(byte_len)
@@ -905,7 +903,6 @@ fn run_audio_thread(
905903
// Update shared state (single lock acquisition)
906904
{
907905
let mut inner = shared_state.write_inner();
908-
inner.current_audio_data = Some((audio_data, byte_len));
909906
inner.current_song = Some(metadata.clone());
910907
inner.playback_start = Some(Instant::now());
911908
inner.paused_position = 0.0;
@@ -987,7 +984,6 @@ fn run_audio_thread(
987984
{
988985
let mut inner = shared_state.write_inner();
989986
inner.current_song = None;
990-
inner.current_audio_data = None;
991987
inner.playback_start = None;
992988
inner.paused_position = 0.0;
993989
inner.duration = 0.0;
@@ -1122,7 +1118,7 @@ fn run_audio_thread(
11221118
crossfade_sink = current_sink.take();
11231119

11241120
let byte_len = audio_data.len() as u64;
1125-
let cursor = Cursor::new(audio_data.clone());
1121+
let cursor = Cursor::new(audio_data);
11261122
match Decoder::builder()
11271123
.with_data(cursor)
11281124
.with_byte_len(byte_len)
@@ -1148,7 +1144,6 @@ fn run_audio_thread(
11481144
// Update shared state for the new song
11491145
{
11501146
let mut inner = shared_state.write_inner();
1151-
inner.current_audio_data = Some((audio_data, byte_len));
11521147
inner.current_song = Some(metadata.clone());
11531148
inner.playback_start = Some(Instant::now());
11541149
inner.paused_position = 0.0;

src-tauri/src/commands/playback.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use log::{info, warn};
2+
use std::sync::Arc;
23
use tauri::{AppHandle, Manager, State};
34

45
use crate::audio::binaural::BinauralPreset;
@@ -19,7 +20,7 @@ use crate::state::AppState;
1920

2021
/// Common song data needed for playback.
2122
struct SongData {
22-
audio_data: Vec<u8>,
23+
audio_data: Arc<[u8]>,
2324
metadata: SongMetadata,
2425
duration: f64,
2526
album_id: String,
@@ -77,7 +78,10 @@ async fn fetch_song_data(
7778
};
7879

7980
let cache = AudioCache::new(app_handle)?;
80-
let audio_data = cache.get_or_fetch(&state.client, song_id, &suffix).await?;
81+
let audio_data: Arc<[u8]> = cache
82+
.get_or_fetch(&state.client, song_id, &suffix)
83+
.await?
84+
.into();
8185

8286
let norm_settings = read_normalization_settings(app_handle);
8387
let normalization_gain = if norm_settings.enabled {

0 commit comments

Comments
 (0)