Skip to content

Commit

Permalink
Merge pull request #61 from MarcelLieb/56-create-settings-for-audio-d…
Browse files Browse the repository at this point in the history
…evices

56 create settings for audio devices
  • Loading branch information
MarcelLieb authored Dec 31, 2023
2 parents 255d87b + 2f2317d commit d4d412f
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 52 deletions.
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ async fn main() {
}

{
let stream = create_default_output_stream().await;
let stream = create_default_output_stream()
.await
.expect("Error occurred while building stream");
stream.play().unwrap();
let (tx, rx) = channel();

Expand Down
123 changes: 73 additions & 50 deletions src/utils/audiodevices.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::utils::audioprocessing::hfc::Hfc;
use std::collections::VecDeque;

use crate::utils::audioprocessing::spectral_flux::SpecFlux;
use crate::utils::audioprocessing::ProcessingSettings;
use crate::utils::audioprocessing::{prepare_buffers, process_raw};
Expand All @@ -11,67 +12,52 @@ use cpal::{
};
use log::debug;

use super::audioprocessing::spectral_flux::SpecFluxSettings;

fn capture_err_fn(err: cpal::StreamError) {
eprintln!("an error occurred on stream: {}", err);
}

pub async fn create_default_output_stream() -> cpal::Stream {
let _hosts = cpal::available_hosts();
let default_host = cpal::default_host();
pub fn create_monitor_stream(
device_name: &str,
processing_settings: ProcessingSettings,
detection_settings: SpecFluxSettings,
lightservices: Vec<Box<dyn LightService + Send>>,
) -> Result<cpal::Stream, BuildStreamError> {
let out = cpal::default_host()
.devices()
.map_err(|_| BuildStreamError::DeviceNotAvailable)?
.filter(|d| d.name().unwrap_or_default() == device_name)
.next()
.ok_or_else(|| BuildStreamError::DeviceNotAvailable)?;

let out = default_host
.default_output_device()
.expect("no output device available");
let audio_cfg = out
.default_output_config()
.expect("No default output config found");

let channels = audio_cfg.channels();

let settings = ProcessingSettings::default();
let config = StreamConfig {
channels,
sample_rate: cpal::SampleRate(settings.sample_rate),
sample_rate: cpal::SampleRate(processing_settings.sample_rate),
buffer_size: cpal::BufferSize::Default,
};

let mut detection_buffer = prepare_buffers(channels, &settings);
let mut lightservices = lightservices;

let mut lightservices: Vec<Box<dyn LightService + Send>> = Vec::new();
if let Ok(bridge) = hue::connect().await {
lightservices.push(Box::new(bridge));
}
let mut detection_buffer = prepare_buffers(channels, &processing_settings);

/*
let strip = wled::LEDStripOnset::connect("192.168.2.53").await;
if let Ok(strip) = strip {
lightservices.push(Box::new(strip));
}
*/

if let Ok(strip) = wled::LEDStripSpectrum::connect("192.168.2.53").await {
lightservices.push(Box::new(strip));
}

let console = Console::default();
lightservices.push(Box::new(console));

let serializer = serialize::OnsetContainer::init(
"onsets.cbor".to_string(),
settings.sample_rate as usize,
settings.hop_size,
let mut spec_flux = SpecFlux::with_settings(
processing_settings.sample_rate,
processing_settings.fft_size as u32,
detection_settings,
);
lightservices.push(Box::new(serializer));

let mut spec_flux = SpecFlux::init(settings.sample_rate, settings.fft_size as u32);

let mut _hfc = Hfc::init(settings.sample_rate as usize, settings.fft_size);

let buffer_size = settings.buffer_size * channels as usize;
let hop_size = settings.hop_size * channels as usize;
let buffer_size = processing_settings.buffer_size * channels as usize;
let hop_size = processing_settings.hop_size * channels as usize;
macro_rules! build_buffered_onset_stream {
($t:ty) => {{
let mut buffer: Vec<$t> = Vec::new();
let mut buffer: VecDeque<$t> = VecDeque::new();

out.build_input_stream(
&config,
Expand All @@ -80,7 +66,11 @@ pub async fn create_default_output_stream() -> cpal::Stream {
let n = (buffer.len() + hop_size).saturating_sub(buffer_size) / hop_size;

(0..n).for_each(|_| {
process_raw(&buffer[0..buffer_size], channels, &mut detection_buffer);
process_raw(
&buffer.make_contiguous()[0..buffer_size],
channels,
&mut detection_buffer,
);

let onsets = spec_flux.detect(
&detection_buffer.freq_bins,
Expand All @@ -91,13 +81,6 @@ pub async fn create_default_output_stream() -> cpal::Stream {
lightservices.process_spectrum(&detection_buffer.freq_bins);
lightservices.process_samples(&detection_buffer.mono_samples);
lightservices.update();
/*
let onsets = _hfc.detect(
&detection_buffer.freq_bins,
detection_buffer.peak,
detection_buffer.rms
);
*/

buffer.drain(0..hop_size);
})
Expand All @@ -112,8 +95,7 @@ pub async fn create_default_output_stream() -> cpal::Stream {
cpal::SampleFormat::I16 => build_buffered_onset_stream!(i16),
cpal::SampleFormat::U16 => build_buffered_onset_stream!(u16),
_ => Err(BuildStreamError::StreamConfigNotSupported),
}
.expect("Couldn't build input stream.\nMake sure you are running at 48kHz sample rate");
};
debug!("Default output device: {:?}", out.name().unwrap());
debug!(
"Default output sample format: {:?}",
Expand All @@ -124,3 +106,44 @@ pub async fn create_default_output_stream() -> cpal::Stream {
debug!("Default output channels: {:?}", audio_cfg.channels());
outstream
}

pub async fn create_default_output_stream() -> Result<cpal::Stream, BuildStreamError> {
let device = cpal::default_host()
.default_output_device()
.ok_or_else(|| BuildStreamError::DeviceNotAvailable)?;

let settings = ProcessingSettings::default();

let mut lightservices: Vec<Box<dyn LightService + Send>> = Vec::new();
if let Ok(bridge) = hue::connect().await {
lightservices.push(Box::new(bridge));
}

/*
let strip = wled::LEDStripOnset::connect("192.168.2.53").await;
if let Ok(strip) = strip {
lightservices.push(Box::new(strip));
}
*/

if let Ok(strip) = wled::LEDStripSpectrum::connect("192.168.2.53").await {
lightservices.push(Box::new(strip));
}

let console = Console::default();
lightservices.push(Box::new(console));

let serializer = serialize::OnsetContainer::init(
"onsets.cbor".to_string(),
settings.sample_rate as usize,
settings.hop_size,
);
lightservices.push(Box::new(serializer));
let detection_settings = SpecFluxSettings::default();
create_monitor_stream(
&device.name().unwrap_or_default(),
settings,
detection_settings,
lightservices,
)
}
2 changes: 1 addition & 1 deletion src/utils/audioprocessing/spectral_flux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ impl SpecFlux {
.old_spectrum
.iter()
.zip(&self.spectrum)
.map(|(&a, &b)| (((b - a) + (b - a).abs()) / 2.0));
.map(|(&a, &b)| ((b - a).max(0.0)));

let weight: f32 = flux.clone().sum();

Expand Down

0 comments on commit d4d412f

Please sign in to comment.