Feat: rework audio sample library viewer
This commit is contained in:
@@ -170,12 +170,49 @@ fn render_side_panel(frame: &mut Frame, app: &App, area: Rect) {
|
||||
let focused = app.panel.focus == PanelFocus::Side;
|
||||
match &app.panel.side {
|
||||
Some(SidePanel::SampleBrowser(state)) => {
|
||||
let [tree_area, preview_area] =
|
||||
Layout::vertical([Constraint::Fill(1), Constraint::Length(6)]).areas(area);
|
||||
|
||||
let entries = state.entries();
|
||||
SampleBrowser::new(&entries, state.cursor)
|
||||
.scroll_offset(state.scroll_offset)
|
||||
.search(&state.search_query, state.search_active)
|
||||
.focused(focused)
|
||||
.render(frame, area);
|
||||
.render(frame, tree_area);
|
||||
|
||||
if let Some(sample) = state
|
||||
.sample_key()
|
||||
.and_then(|key| app.audio.sample_registry.as_ref()?.get(&key))
|
||||
.filter(|s| s.frame_count >= s.total_frames)
|
||||
{
|
||||
use crate::widgets::Waveform;
|
||||
use std::cell::RefCell;
|
||||
thread_local! {
|
||||
static MONO_BUF: RefCell<Vec<f32>> = const { RefCell::new(Vec::new()) };
|
||||
}
|
||||
|
||||
let [wave_area, info_area] =
|
||||
Layout::vertical([Constraint::Fill(1), Constraint::Length(1)])
|
||||
.areas(preview_area);
|
||||
|
||||
MONO_BUF.with(|buf| {
|
||||
let mut buf = buf.borrow_mut();
|
||||
let channels = sample.channels as usize;
|
||||
let frame_count = sample.frame_count as usize;
|
||||
buf.clear();
|
||||
buf.reserve(frame_count);
|
||||
for i in 0..frame_count {
|
||||
buf.push(sample.frames[i * channels]);
|
||||
}
|
||||
frame.render_widget(Waveform::new(&buf), wave_area);
|
||||
});
|
||||
|
||||
let duration = sample.total_frames as f32 / app.audio.config.sample_rate;
|
||||
let ch_label = if sample.channels == 1 { "mono" } else { "stereo" };
|
||||
let info = Paragraph::new(format!(" {duration:.1}s · {ch_label}"))
|
||||
.style(Style::new().fg(theme::get().ui.text_dim));
|
||||
frame.render_widget(info, info_area);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user