Compare commits
2 Commits
c10f42da8f
...
9935c2f3bd
| Author | SHA1 | Date |
|---|---|---|
|
|
9935c2f3bd | |
|
|
5a97ea76d5 |
|
|
@ -155,7 +155,7 @@ impl AudioSystem {
|
|||
}
|
||||
};
|
||||
|
||||
// Get input config - use the input device's own default config
|
||||
// Get input config using the device's default (most compatible)
|
||||
let input_config = match input_device.default_input_config() {
|
||||
Ok(config) => {
|
||||
let cfg: cpal::StreamConfig = config.into();
|
||||
|
|
@ -165,7 +165,6 @@ impl AudioSystem {
|
|||
eprintln!("Warning: Could not get input config: {}, recording will be disabled", e);
|
||||
output_stream.play().map_err(|e| e.to_string())?;
|
||||
|
||||
// Spawn emitter thread if provided
|
||||
if let Some(emitter) = event_emitter {
|
||||
Self::spawn_emitter_thread(event_rx, emitter);
|
||||
}
|
||||
|
|
@ -180,14 +179,58 @@ impl AudioSystem {
|
|||
}
|
||||
};
|
||||
|
||||
// Build input stream that feeds into the ringbuffer
|
||||
let input_sample_rate = input_config.sample_rate;
|
||||
let input_channels = input_config.channels as u32;
|
||||
let output_sample_rate = sample_rate;
|
||||
let output_channels = channels;
|
||||
let needs_resample = input_sample_rate != output_sample_rate || input_channels != output_channels;
|
||||
|
||||
if needs_resample {
|
||||
eprintln!("[AUDIO] Input device: {}Hz {}ch -> resampling to {}Hz {}ch",
|
||||
input_sample_rate, input_channels, output_sample_rate, output_channels);
|
||||
}
|
||||
|
||||
// Build input stream with resampling if needed
|
||||
let input_stream = match input_device
|
||||
.build_input_stream(
|
||||
&input_config,
|
||||
move |data: &[f32], _: &cpal::InputCallbackInfo| {
|
||||
if !needs_resample {
|
||||
for &sample in data {
|
||||
let _ = input_tx.push(sample);
|
||||
}
|
||||
} else {
|
||||
// Resample: linear interpolation from input rate to output rate
|
||||
let in_ch = input_channels as usize;
|
||||
let out_ch = output_channels as usize;
|
||||
let ratio = output_sample_rate as f64 / input_sample_rate as f64;
|
||||
let in_frames = data.len() / in_ch;
|
||||
let out_frames = (in_frames as f64 * ratio) as usize;
|
||||
|
||||
for i in 0..out_frames {
|
||||
let src_pos = i as f64 / ratio;
|
||||
let src_idx = src_pos as usize;
|
||||
let frac = (src_pos - src_idx as f64) as f32;
|
||||
|
||||
for ch in 0..out_ch {
|
||||
// Map output channel to input channel
|
||||
let in_ch_idx = ch.min(in_ch - 1);
|
||||
|
||||
let s0 = if src_idx < in_frames {
|
||||
data[src_idx * in_ch + in_ch_idx]
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let s1 = if src_idx + 1 < in_frames {
|
||||
data[(src_idx + 1) * in_ch + in_ch_idx]
|
||||
} else {
|
||||
s0
|
||||
};
|
||||
|
||||
let _ = input_tx.push(s0 + frac * (s1 - s0));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|err| eprintln!("Input stream error: {}", err),
|
||||
None,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
@echo off
|
||||
REM Build script for Windows
|
||||
REM Requires: FFmpeg 8.0.0 dev files in C:\ffmpeg, LLVM installed
|
||||
|
||||
REM FFmpeg location (headers + libs + DLLs)
|
||||
if not defined FFMPEG_DIR set FFMPEG_DIR=C:\ffmpeg
|
||||
|
||||
REM LLVM/libclang for bindgen (ffmpeg-sys-next)
|
||||
if not defined LIBCLANG_PATH set LIBCLANG_PATH=C:\Program Files\LLVM\bin
|
||||
|
||||
REM Validate prerequisites
|
||||
if not exist "%FFMPEG_DIR%\include\libavcodec\avcodec.h" (
|
||||
echo ERROR: FFmpeg dev files not found at %FFMPEG_DIR%
|
||||
echo Download FFmpeg 8.0.0 shared+dev from https://github.com/GyanD/codexffmpeg/releases
|
||||
echo and extract to %FFMPEG_DIR%
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist "%LIBCLANG_PATH%\libclang.dll" (
|
||||
echo ERROR: LLVM/libclang not found at %LIBCLANG_PATH%
|
||||
echo Install with: winget install LLVM.LLVM
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Building Lightningbeam Editor...
|
||||
echo FFMPEG_DIR=%FFMPEG_DIR%
|
||||
echo LIBCLANG_PATH=%LIBCLANG_PATH%
|
||||
|
||||
cargo build --package lightningbeam-editor %*
|
||||
Loading…
Reference in New Issue