Skip to content
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: ci
on: [push, pull_request]
jobs:
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hecrj/setup-rust-action@v2
with:
components: clippy
- run: sudo apt-get -y update && sudo apt-get -y install libgtk-3-dev libjack-jackd2-dev
- run: cargo clippy -- -D warnings
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hecrj/setup-rust-action@v2
with:
components: rustfmt
- run: cargo fmt --all -- --check
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hecrj/setup-rust-action@v2
- run: sudo apt-get -y update && sudo apt-get -y install libgtk-3-dev libjack-jackd2-dev
- run: cargo test --verbose --workspace
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

# Raumklang

[![GitHub License](https://img.shields.io/github/license/kunerd/raumklang)](https://github.com/kunerd/raumklang/LICENSE)
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/kunerd/raumklang/ci.yml)
[![Made with iced](https://iced.rs/badge.svg)](https://github.com/iced-rs/iced)

An open source room impulse response measurement software using the sine sweep
method.

Expand Down
18 changes: 9 additions & 9 deletions raumklang-gui/src/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,7 @@ fn run_audio_backend(sender: mpsc::Sender<Event>) {
};
}
Err(err) => {
state = State::Retrying {
err: err.into(),
retry_count,
};
state = State::Retrying { err, retry_count };
}
}
}
Expand All @@ -198,7 +195,7 @@ fn run_audio_backend(sender: mpsc::Sender<Event>) {
mut process_tx,
is_server_shutdown,
} => {
while is_server_shutdown.load(std::sync::atomic::Ordering::Relaxed) != true {
while !is_server_shutdown.load(std::sync::atomic::Ordering::Relaxed) {
// FIXME: wrong channel type
match command_rx.try_recv() {
Ok(Command::ConnectOutPort(dest)) => {
Expand Down Expand Up @@ -245,7 +242,8 @@ fn run_audio_backend(sender: mpsc::Sender<Event>) {
let (producer, consumer) = measurement::create(buf_size);

let process_msg = ProcessHandlerMessage::Measurement(producer);
process_tx.try_push(process_msg);
// TODO refactor
let _ = process_tx.try_push(process_msg);

let test_process = Test::new(sender);
std::thread::spawn(move || {
Expand Down Expand Up @@ -293,17 +291,19 @@ fn run_audio_backend(sender: mpsc::Sender<Event>) {
.enumerate()
.map(move |(i, s)| s * window[i]);

// TODO: make configurable
let sweep = (0..22_000)
.into_iter()
.map(|_| 0.0)
.chain(sweep)
.chain((0..20_000).into_iter().map(|_| 0.0));
.chain((0..20_000).map(|_| 0.0));

let buf_size = client.as_client().buffer_size() as usize;
let (producer, consumer) = measurement::create(buf_size);

let process_msg = ProcessHandlerMessage::Measurement(producer);
process_tx.try_push(process_msg);

// TODO: refactor
let _ = process_tx.try_push(process_msg);

let loudness = loudness::Test::new(loudness_sender);
let measurement = Measurement::new(loudness, data_sender);
Expand Down
6 changes: 2 additions & 4 deletions raumklang-gui/src/audio/measurement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ pub struct State {

impl Producer {
#[must_use]
pub fn play_signal_chunk<'a>(
&'a mut self,
pub fn play_signal_chunk(
&mut self,
out_port: &mut [f32],
amplitude: f32,
) -> Option<SignalState> {
Expand Down Expand Up @@ -98,7 +98,6 @@ impl Producer {
}
}

#[must_use]
pub fn record_chunk(&mut self, chunk: &[f32]) -> Result<(), Error> {
if self.state.consumer_dropped.load(atomic::Ordering::Acquire) {
return Err(Error::ConsumerDropped);
Expand Down Expand Up @@ -149,7 +148,6 @@ impl Consumer {
.state
.producer_dropped
.load(std::sync::atomic::Ordering::Acquire)
== true
&& data.is_empty()
{
log::debug!("All real-time audio data consumed.");
Expand Down
12 changes: 6 additions & 6 deletions raumklang-gui/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn smooth_fractional_octave(signal: &[f32], num_fractions: u8) -> Vec<f32> {

// linearly and logarithmically spaced frequency bins ----------------------
let len = signal.len() as f32;
let n_lin = Array::range(0., len as f32, 1.0);
let n_lin = Array::range(0., len, 1.0);
let n_log = n_lin.mapv(|n| n / (len - 1.0)).mapv(|n| len.powf(n));

// frequency bin spacing in octaves: log2(n_log[n]/n_log[n-1])
Expand Down Expand Up @@ -105,21 +105,21 @@ pub fn smooth_fractional_octave(signal: &[f32], num_fractions: u8) -> Vec<f32> {
#[derive(Debug, Clone, thiserror::Error)]
pub enum Error {
#[error("io operation failed: {0}")]
IOFailed(Arc<io::Error>),
IO(Arc<io::Error>),
#[error("deserialization failed: {0}")]
SerdeFailed(Arc<serde_json::Error>),
Serde(Arc<serde_json::Error>),
#[error("impulse response computation failed")]
ImpulseResponseComputationFailed,
ImpulseResponseComputation,
}

impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Self::IOFailed(Arc::new(error))
Self::IO(Arc::new(error))
}
}

impl From<serde_json::Error> for Error {
fn from(error: serde_json::Error) -> Self {
Self::SerdeFailed(Arc::new(error))
Self::Serde(Arc::new(error))
}
}
2 changes: 1 addition & 1 deletion raumklang-gui/src/data/samples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl From<Samples> for f32 {

impl From<Samples> for usize {
fn from(samples: Samples) -> Self {
samples.0 as usize
samples.0
}
}

Expand Down
1 change: 0 additions & 1 deletion raumklang-gui/src/data/spectral_decay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ pub(crate) async fn compute(
let window = window.build();

let ir: Vec<_> = (0..usize::from(left_width))
.into_iter()
.map(|_| Complex32::from(0.0))
.chain(
ir.data
Expand Down
2 changes: 0 additions & 2 deletions raumklang-gui/src/data/spectrogram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ pub(crate) async fn compute(
let half_window_size = window_size / 2;
let sig = 0.3;
let window: Vec<_> = (0..window_size)
.into_iter()
.map(|n| (n as f32 - half_window_size as f32) / ((sig * window_size as f32) / 2.0))
.map(|w| f32::powi(w, 2))
.map(|s| f32::exp(-0.5 * s))
Expand All @@ -59,7 +58,6 @@ pub(crate) async fn compute(
dbg!(span_before_peak);
dbg!(span_after_peak);
let ir: Vec<_> = (0..half_window_size + usize::from(span_before_peak))
.into_iter()
.map(|_| Complex32::from(0.0))
.chain(
ir.data
Expand Down
6 changes: 3 additions & 3 deletions raumklang-gui/src/data/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ impl Window<Duration> {

pub fn update(&mut self, handles: Handles) {
let left_width = handles.center.x() - handles.left.x();
self.left_width = Duration::from_millis(left_width as u64).into();
self.left_width = Duration::from_millis(left_width as u64);

self.position = Duration::from_millis(handles.center.x() as u64).into();
self.position = Duration::from_millis(handles.center.x() as u64);

let right_width = handles.right.x() - handles.center.x();
self.right_width = Duration::from_millis(right_width as u64).into();
self.right_width = Duration::from_millis(right_width as u64);
}
}

Expand Down
7 changes: 1 addition & 6 deletions raumklang-gui/src/data/window/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,14 @@ impl Handle {

impl From<Alignment> for f32 {
fn from(alignment: Alignment) -> Self {
Into::into(&alignment)
}
}

impl From<&Alignment> for f32 {
fn from(alignment: &Alignment) -> Self {
match alignment {
Alignment::Bottom => 0.0,
Alignment::Center => 0.5,
Alignment::Top => 1.0,
}
}
}

impl SubAssign<f32> for Handle {
fn sub_assign(&mut self, offset: f32) {
self.x -= offset;
Expand Down
1 change: 1 addition & 0 deletions raumklang-gui/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod audio;
mod data;
#[rustfmt::skip]
mod icon;
mod log;
mod screen;
Expand Down
1 change: 1 addition & 0 deletions raumklang-gui/src/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use iced::{
Element, Length,
};

#[allow(clippy::large_enum_variant)]
pub enum Screen {
Loading,
Landing,
Expand Down
32 changes: 15 additions & 17 deletions raumklang-gui/src/screen/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ mod recording;
use generic_overlay::generic_overlay::{dropdown_menu, dropdown_root};
use impulse_response::{ChartOperation, WindowSettings};
use recording::Recording;
use rfd::FileHandle;

use crate::{
data::{
Expand All @@ -19,6 +18,8 @@ use crate::{
ui, PickAndLoadError,
};

use raumklang_core::dbfs;

use iced::{
alignment::{Horizontal, Vertical},
futures::{FutureExt, TryFutureExt},
Expand All @@ -32,8 +33,6 @@ use iced::{

use prism::{axis, line_series, Axis, Chart, Labels};

use raumklang_core::dbfs;

use std::{
fmt::Display,
path::{Path, PathBuf},
Expand All @@ -53,6 +52,7 @@ pub struct Main {
project_path: Option<PathBuf>,
}

#[allow(clippy::large_enum_variant)]
enum State {
CollectingMeasuremnts {
recording: Option<Recording>,
Expand All @@ -71,6 +71,7 @@ impl Default for State {
}
}

#[allow(clippy::large_enum_variant)]
pub enum Tab {
Measurements { recording: Option<Recording> },
ImpulseResponses { window_settings: WindowSettings },
Expand Down Expand Up @@ -391,16 +392,16 @@ impl Main {
charts
.impulse_responses
.x_range
.get_or_insert_with(|| 0.0..=impulse_response.data.len() as f32);
.get_or_insert(0.0..=impulse_response.data.len() as f32);

charts.impulse_responses.data_cache.clear();
}

if let Tab::FrequencyResponses { .. } = active_tab {
if let Tab::FrequencyResponses = active_tab {
compute_frequency_response(self.loopback.as_ref().unwrap(), measurement, window)
} else if let Tab::SpectralDecay { .. } = active_tab {
} else if let Tab::SpectralDecay = active_tab {
compute_spectral_decay(self.loopback.as_ref().unwrap(), measurement)
} else if let Tab::Spectrogram { .. } = active_tab {
} else if let Tab::Spectrogram = active_tab {
compute_spectrogram(self.loopback.as_ref().unwrap(), measurement)
} else {
Task::none()
Expand Down Expand Up @@ -984,7 +985,7 @@ impl Main {
.style(container::bordered_box)
};

modal(content, pending_window).into()
modal(content, pending_window)
} else {
content.into()
}
Expand Down Expand Up @@ -1055,9 +1056,8 @@ impl Main {
.into()
};

let content = if let Some(measurement) = self
.selected
.map(|selected| match selected {
let content = if let Some(measurement) =
self.selected.and_then(|selected| match selected {
measurement::Selected::Loopback => self
.loopback
.as_ref()
Expand All @@ -1068,10 +1068,8 @@ impl Main {
.get(i)
.and_then(ui::measurement::State::loaded)
.map(|m| &m.data),
})
.flatten()
{
chart::waveform(&measurement, &self.signal_cache, self.zoom, self.offset)
}) {
chart::waveform(measurement, &self.signal_cache, self.zoom, self.offset)
.map(Message::MeasurementChart)
} else {
welcome_text(text("Select a signal to view its data."))
Expand Down Expand Up @@ -1395,7 +1393,7 @@ impl Main {
// .x_range(20.0..=2000.0)
.y_labels(Labels::default().format(&|v| format!("{v:.0}")))
.extend_series(series_list)
.cache(&cache);
.cache(cache);

container(chart)
} else {
Expand Down Expand Up @@ -1853,7 +1851,7 @@ where
.align_y(Alignment::Center);

column!(header, rule::horizontal(1))
.extend(self.entries.into_iter())
.extend(self.entries)
.width(Length::Fill)
.spacing(5)
.into()
Expand Down
Loading