fix view diff
This commit is contained in:
+78
-20
@@ -1,23 +1,46 @@
|
||||
use clap::Parser;
|
||||
use ncurses::*;
|
||||
use ncurses::{LcCategory, setlocale};
|
||||
use rustfft::{algorithm::Radix4, num_complex::Complex, Fft, FftDirection};
|
||||
use std::collections::VecDeque;
|
||||
use std::collections::{VecDeque, HashMap};
|
||||
use std::io::{stdin, Read};
|
||||
use std::fs::File;
|
||||
use std::time::{Duration, Instant};
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
|
||||
use std::process::{Command, Stdio};
|
||||
use std::thread::sleep;
|
||||
|
||||
// Create screen buffer struct to track cell states
|
||||
// Each cell stores a character and its state (whether it's filled or not)
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
struct Cell {
|
||||
character: String,
|
||||
filled: bool,
|
||||
}
|
||||
|
||||
// ViewDiff struct for efficient terminal updates
|
||||
struct ViewDiff {
|
||||
changes: HashMap<(usize, usize), String>,
|
||||
}
|
||||
|
||||
impl ViewDiff {
|
||||
fn new() -> Self {
|
||||
ViewDiff {
|
||||
changes: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_change(&mut self, y: usize, x: usize, character: String) {
|
||||
self.changes.insert((y, x), character);
|
||||
}
|
||||
|
||||
fn apply(&self) {
|
||||
for ((y, x), character) in &self.changes {
|
||||
let _ = mvprintw(*y as i32, *x as i32, character);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Function to handle terminal resizing
|
||||
fn handle_terminal_resize(
|
||||
rows: &mut i32,
|
||||
@@ -99,7 +122,7 @@ fn main() {
|
||||
let cli = Cli::parse();
|
||||
|
||||
// Initialize ncurses with proper locale for UTF-8 support
|
||||
setlocale(LcCategory::all, ""); // Set locale before ncurses init for UTF-8 support
|
||||
let _ = setlocale(LcCategory::all, ""); // Set locale before ncurses init for UTF-8 support
|
||||
initscr();
|
||||
noecho();
|
||||
curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE);
|
||||
@@ -114,14 +137,15 @@ fn main() {
|
||||
|
||||
let sample_rate: usize = 48000;
|
||||
let bit_depth: usize = 16;
|
||||
let num_channels: usize = 2; // Default to assume stereo for better handling
|
||||
let samples_per_frame: usize = sample_rate / usize::from(cli.fps);
|
||||
let fft_size: usize = 1024;
|
||||
|
||||
// Set up FFT processor
|
||||
let fft = Radix4::new(fft_size, FftDirection::Forward);
|
||||
|
||||
// Set up audio input source
|
||||
let mut input_buffer = vec![0; samples_per_frame * (bit_depth / 8)];
|
||||
// Set up audio input source - account for num_channels in buffer size
|
||||
let mut input_buffer = vec![0; samples_per_frame * num_channels * (bit_depth / 8)];
|
||||
let mut complex_buffer = vec![Complex { re: 0.0, im: 0.0 }; fft_size];
|
||||
|
||||
// Set up input reader based on command line arguments
|
||||
@@ -137,8 +161,9 @@ fn main() {
|
||||
// Set up audio source
|
||||
let mut audio_source = if cli.pipewire {
|
||||
// Launch PipeWire capture process with raw output format
|
||||
// Using stereo (2 channels) for consistent behavior with other input sources
|
||||
let process = Command::new("pw-record")
|
||||
.args(["--format=s16", "--rate=48000", "--channels=1", "--raw", "-"])
|
||||
.args(["--format=s16", "--rate=48000", "--channels=2", "--raw", "-"])
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to start pw-record");
|
||||
@@ -264,14 +289,28 @@ fn main() {
|
||||
// Resize input buffer to match actual bytes read
|
||||
let actual_input = &input_buffer[0..n];
|
||||
|
||||
// Convert raw bytes to audio samples
|
||||
// Convert raw bytes to audio samples, handling multichannel input
|
||||
let mut cursor = std::io::Cursor::new(actual_input);
|
||||
|
||||
// Read as many complete samples as possible
|
||||
while cursor.position() < (n as u64 - 1) {
|
||||
match cursor.read_i16::<LittleEndian>() {
|
||||
Ok(sample) => all_samples.push(sample as f32 / 32768.0),
|
||||
Err(_) => break,
|
||||
// Read as many complete sample frames as possible
|
||||
while cursor.position() < (n as u64 - (num_channels * (bit_depth / 8)) as u64 + 1) {
|
||||
let mut frame_sum = 0.0;
|
||||
let mut valid_channels = 0;
|
||||
|
||||
// Read all channels and average them
|
||||
for _ in 0..num_channels {
|
||||
match cursor.read_i16::<LittleEndian>() {
|
||||
Ok(sample) => {
|
||||
frame_sum += sample as f32;
|
||||
valid_channels += 1;
|
||||
},
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
|
||||
// Average the channels (if any valid channels were read)
|
||||
if valid_channels > 0 {
|
||||
all_samples.push((frame_sum / valid_channels as f32) / 32768.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,15 +341,21 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Render only the changed cells - using safe dimensions
|
||||
// Create a view diff for error display
|
||||
let mut view_diff = ViewDiff::new();
|
||||
|
||||
// Record only the changed cells - using safe dimensions
|
||||
for y in 0..safe_rows as usize {
|
||||
for x in 0..safe_cols as usize {
|
||||
if current_buffer[y][x] != next_buffer[y][x] {
|
||||
let _ = mvprintw(y as i32, x as i32, &next_buffer[y][x].character);
|
||||
view_diff.add_change(y, x, next_buffer[y][x].character.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply all changes in one batch operation
|
||||
view_diff.apply();
|
||||
|
||||
// Swap buffers
|
||||
std::mem::swap(&mut current_buffer, &mut next_buffer);
|
||||
|
||||
@@ -362,6 +407,7 @@ fn main() {
|
||||
complex_buffer[i].re *= window;
|
||||
}
|
||||
|
||||
// Process FFT using standard rustfft implementation (already optimized)
|
||||
fft.process(&mut complex_buffer);
|
||||
|
||||
// Calculate frequency bands using our mapping - with safe dimensions
|
||||
@@ -440,15 +486,21 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Render only the cells that changed (diff and patch) - using safe dimensions
|
||||
// Create a view diff for efficient terminal updates
|
||||
let mut view_diff = ViewDiff::new();
|
||||
|
||||
// Record only the changed cells (diff and patch) - using safe dimensions
|
||||
for y in 0..safe_rows as usize {
|
||||
for x in 0..safe_cols as usize {
|
||||
if current_buffer[y][x] != next_buffer[y][x] {
|
||||
let _ = mvprintw(y as i32, x as i32, &next_buffer[y][x].character);
|
||||
view_diff.add_change(y, x, next_buffer[y][x].character.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply changes efficiently in one batch
|
||||
view_diff.apply();
|
||||
|
||||
// Swap buffers for next frame
|
||||
std::mem::swap(&mut current_buffer, &mut next_buffer);
|
||||
|
||||
@@ -483,15 +535,21 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Render only the cells that changed - using safe dimensions
|
||||
// Create a view diff for efficient terminal updates
|
||||
let mut view_diff = ViewDiff::new();
|
||||
|
||||
// Record only the changed cells - using safe dimensions
|
||||
for y in 0..safe_rows as usize {
|
||||
for x in 0..safe_cols as usize {
|
||||
if current_buffer[y][x] != next_buffer[y][x] {
|
||||
let _ = mvprintw(y as i32, x as i32, &next_buffer[y][x].character);
|
||||
view_diff.add_change(y, x, next_buffer[y][x].character.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply all changes in one batch operation
|
||||
view_diff.apply();
|
||||
|
||||
// Swap buffers
|
||||
std::mem::swap(&mut current_buffer, &mut next_buffer);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user