Skip to content

Commit

Permalink
add spectrum
Browse files Browse the repository at this point in the history
  • Loading branch information
aizcutei committed Jun 3, 2024
1 parent f77674b commit de23257
Show file tree
Hide file tree
Showing 11 changed files with 6,275 additions and 129 deletions.
14 changes: 8 additions & 6 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub struct NanometersApp {
pub(crate) vectorscope: Vectorscope,
pub(crate) spectrogram: Spectrogram,
pub(crate) oscilloscope: Oscilloscope,
pub(crate) spectrum: Spectrum,
}

impl Default for NanometersApp {
Expand Down Expand Up @@ -84,12 +85,13 @@ impl Default for NanometersApp {
setting_switch: false,
allways_on_top: false,
meter_size: Rect::from_two_pos([0.0, 0.0].into(), [600.0, 200.0].into()),
meters_rects: Vec::new(),
waveform: Default::default(),
peak: Default::default(),
vectorscope: Default::default(),
spectrogram: Default::default(),
oscilloscope: Default::default(),
meters_rects: vec![],
waveform: Waveform::default(),
peak: Peak::default(),
vectorscope: Vectorscope::default(),
spectrogram: Spectrogram::default(),
oscilloscope: Oscilloscope::default(),
spectrum: Spectrum::default(),
}
}
}
Expand Down
245 changes: 174 additions & 71 deletions src/audio/callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ pub fn get_callback(

let mut buf = buffer.lock().unwrap();
rx_setting.try_iter().for_each(|s| buf.setting = s);
let mut send_data = SendData::new();
let len = data[0].len();

let waveform_on = buf.setting.sequence[1].contains(&ModuleList::Waveform);
let peak_on = buf.setting.sequence[1].contains(&ModuleList::Peak);
let stereo_on = buf.setting.sequence[1].contains(&ModuleList::Vectorscope);
let vector_on = buf.setting.sequence[1].contains(&ModuleList::Vectorscope);
let spectrum_on = buf.setting.sequence[1].contains(&ModuleList::Spectrum);
let spectrogram_on = buf.setting.sequence[1].contains(&ModuleList::Spectrogram);
let oscilloscope_on = buf.setting.sequence[1].contains(&ModuleList::Oscilloscope);

let waveform_block_length = 280;
let stereo_block_length = 1;
let mut send_data = SendData::new();
let len = data[0].len();
let vector_block_length = 1;
let spectrogram_fft_size = 2048;
let mut amp_l = 0.0;
let mut amp_r = 0.0;

Expand All @@ -38,62 +40,64 @@ pub fn get_callback(
let r = data[1][i];
let m = (l + r) / 2.0;
let s = (l - r) / 2.0;
let low_l = multiband_low_filter(l, &mut buf.multiband.low_buf);
let low_r = multiband_low_filter(r, &mut buf.multiband.low_buf);
let low_m = multiband_low_filter(m, &mut buf.multiband.low_buf);
let low_s = multiband_low_filter(s, &mut buf.multiband.low_buf);
let mid_l = multiband_mid_filter(l, &mut buf.multiband.mid_buf);
let mid_r = multiband_mid_filter(r, &mut buf.multiband.mid_buf);
let mid_m = multiband_mid_filter(m, &mut buf.multiband.mid_buf);
let mid_s = multiband_mid_filter(s, &mut buf.multiband.mid_buf);
let high_l = multiband_high_filter(l, &mut buf.multiband.high_buf);
let high_r = multiband_high_filter(r, &mut buf.multiband.high_buf);
let high_m = multiband_high_filter(m, &mut buf.multiband.high_buf);
let high_s = multiband_high_filter(s, &mut buf.multiband.high_buf);
buf.raw.l.push(l);
buf.raw.r.push(r);
buf.raw.m.push(m);
buf.raw.s.push(s);
buf.low_raw.l.push(low_l);
buf.low_raw.r.push(low_r);
buf.low_raw.m.push(low_m);
buf.low_raw.s.push(low_s);
buf.mid_raw.l.push(mid_l);
buf.mid_raw.r.push(mid_r);
buf.mid_raw.m.push(mid_m);
buf.mid_raw.s.push(mid_s);
buf.high_raw.l.push(high_l);
buf.high_raw.r.push(high_r);
buf.high_raw.m.push(high_m);
buf.high_raw.s.push(high_s);

let raw_len = buf.raw.l.len();

if spectrogram_on || spectrum_on {
if spectrum_on {
if buf.spectrum.ab {
// Update Buffer
let spectrum_index = buf.spectrum.a.l.len();
if spectrum_index >= 1024 {
buf.spectrum.b.l.push(l * HANN_2048[spectrum_index - 1024]);
buf.spectrum.b.r.push(r * HANN_2048[spectrum_index - 1024]);
buf.spectrum.b.m.push(m * HANN_2048[spectrum_index - 1024]);
buf.spectrum.b.s.push(s * HANN_2048[spectrum_index - 1024]);
}
buf.spectrum.a.l.push(l * HANN_2048[spectrum_index]);
buf.spectrum.a.r.push(r * HANN_2048[spectrum_index]);
buf.spectrum.a.m.push(m * HANN_2048[spectrum_index]);
buf.spectrum.a.s.push(s * HANN_2048[spectrum_index]);
// Calculate FFT
if buf.spectrum.a.l.len() >= 2048 {
let mut a_data = buf.spectrum.a.clone();
process_spectrum(&mut buf, &mut send_data, &mut a_data);
buf.spectrum.a.clear();
}
} else {
let spectrum_index = buf.spectrum.b.l.len();
if spectrum_index >= 1024 {
buf.spectrum.a.l.push(l * HANN_2048[spectrum_index - 1024]);
buf.spectrum.a.r.push(r * HANN_2048[spectrum_index - 1024]);
buf.spectrum.a.m.push(m * HANN_2048[spectrum_index - 1024]);
buf.spectrum.a.s.push(s * HANN_2048[spectrum_index - 1024]);
}
buf.spectrum.b.l.push(l * HANN_2048[spectrum_index]);
buf.spectrum.b.r.push(r * HANN_2048[spectrum_index]);
buf.spectrum.b.m.push(m * HANN_2048[spectrum_index]);
buf.spectrum.b.s.push(s * HANN_2048[spectrum_index]);
if buf.spectrum.b.l.len() >= 2048 {
let mut b_data = buf.spectrum.b.clone();
process_spectrum(&mut buf, &mut send_data, &mut b_data);
buf.spectrum.b.clear();
}
}
} else {
buf.spectrum.a.clear();
buf.spectrum.b.clear();
}

if spectrogram_on {
if buf.spectrogram.ab {
let spectrogram_index = buf.spectrogram.a.index.clone();
if spectrogram_index >= 1024 {
if spectrogram_index >= spectrogram_fft_size / 2 {
updata_spectrogram_window(
&mut buf.spectrogram.b,
spectrogram_index - 1024,
spectrogram_index - spectrogram_fft_size / 2,
m,
);
}
updata_spectrogram_window(&mut buf.spectrogram.a, spectrogram_index, m);
} else {
let spectrogram_index = buf.spectrogram.b.index.clone();
if spectrogram_index >= 1024 {
updata_spectrogram_window(
&mut buf.spectrogram.a,
spectrogram_index - 1024,
m,
);
}
updata_spectrogram_window(&mut buf.spectrogram.b, spectrogram_index, m);
}

if buf.spectrogram.ab {
if buf.spectrogram.a.index >= 2048 {
if buf.spectrogram.a.index >= spectrogram_fft_size {
let mut spectrum_buffer = buf.spectrogram.clone();
process_spectrogram(
&mut buf,
Expand All @@ -105,7 +109,16 @@ pub fn get_callback(
buf.spectrogram.a.reset();
}
} else {
if buf.spectrogram.b.index >= 2048 {
let spectrogram_index = buf.spectrogram.b.index.clone();
if spectrogram_index >= spectrogram_fft_size / 2 {
updata_spectrogram_window(
&mut buf.spectrogram.a,
spectrogram_index - spectrogram_fft_size / 2,
m,
);
}
updata_spectrogram_window(&mut buf.spectrogram.b, spectrogram_index, m);
if buf.spectrogram.b.index >= spectrogram_fft_size {
let mut spectrum_buffer = buf.spectrogram.clone();
process_spectrogram(
&mut buf,
Expand Down Expand Up @@ -188,10 +201,38 @@ pub fn get_callback(
}
}

if stereo_on {
if vector_on {
// Stereo
let low_l = multiband_low_filter(l, &mut buf.multiband.low_buf);
let low_r = multiband_low_filter(r, &mut buf.multiband.low_buf);
let low_m = multiband_low_filter(m, &mut buf.multiband.low_buf);
let low_s = multiband_low_filter(s, &mut buf.multiband.low_buf);
let mid_l = multiband_mid_filter(l, &mut buf.multiband.mid_buf);
let mid_r = multiband_mid_filter(r, &mut buf.multiband.mid_buf);
let mid_m = multiband_mid_filter(m, &mut buf.multiband.mid_buf);
let mid_s = multiband_mid_filter(s, &mut buf.multiband.mid_buf);
let high_l = multiband_high_filter(l, &mut buf.multiband.high_buf);
let high_r = multiband_high_filter(r, &mut buf.multiband.high_buf);
let high_m = multiband_high_filter(m, &mut buf.multiband.high_buf);
let high_s = multiband_high_filter(s, &mut buf.multiband.high_buf);
buf.raw.l.push(l);
buf.raw.r.push(r);
buf.raw.m.push(m);
buf.raw.s.push(s);
buf.low_raw.l.push(low_l);
buf.low_raw.r.push(low_r);
buf.low_raw.m.push(low_m);
buf.low_raw.s.push(low_s);
buf.mid_raw.l.push(mid_l);
buf.mid_raw.r.push(mid_r);
buf.mid_raw.m.push(mid_m);
buf.mid_raw.s.push(mid_s);
buf.high_raw.l.push(high_l);
buf.high_raw.r.push(high_r);
buf.high_raw.m.push(high_m);
buf.high_raw.s.push(high_s);
buf.stereo.update(l, r);
if buf.stereo.index >= stereo_block_length {
if buf.stereo.index >= vector_block_length {
buf.stereo.index = 0;
send_data.vectorscope.lissa.push(Pos2::new(l, r));
send_data
Expand Down Expand Up @@ -244,7 +285,7 @@ pub fn get_callback(

// Send data

if stereo_on {
if vector_on {
// Stereo
send_data.vectorscope.max = buf.stereo.max;
buf.stereo.max = f32::NEG_INFINITY;
Expand All @@ -269,8 +310,8 @@ fn process_spectrogram(
raw_hann_dt: &mut [f32],
raw_hann_t: &mut [f32],
) {
let resolution = buf.setting.spectrogram.resolution;
let speed = 1;
let resolution = 2048;
let speed = 4;
buf.spectrogram.image.drain(0..resolution * speed);
buf.spectrogram
.image
Expand All @@ -290,24 +331,86 @@ fn process_spectrogram(
let tc_temp = (fft_xt[i] * fft_x[i].conj()).re() / magsqrd[i];

if fc_temp > 0.0 && fc_temp < 22000.0 {
let image_x = fc_temp / 22000.0 * resolution as f32;
let image_y = 1920.0 + tc_temp * 20.0;
let origin_color = buf.spectrogram.image
[image_x.round() as usize + (image_y.round() as usize) * resolution]
.a();
buf.spectrogram.image
[image_x.round() as usize + (image_y.round() as usize) * resolution] =
Color32::from_rgba_unmultiplied(
buf.setting.theme.main.r(),
buf.setting.theme.main.g(),
buf.setting.theme.main.b(),
origin_color.wrapping_add(
(255.0 * fft_x[i].norm() * buf.setting.spectrogram.brightness_boost as f32)
as u8,
),
);
let image_x = if buf.setting.spectrogram.curve == SpectrogramCurve::Linear {
fc_temp.floor() / 22000.0 * resolution as f32
} else {
0.2991878257 * (fc_temp.log10() - 1.0) * resolution as f32
};
let image_y = 1920.0 + tc_temp * 46.875 * speed as f32;

let o_x_weight = image_x - image_x.floor();
let o_y_weight = image_y - image_y.floor();
let o_x = image_x.floor() as usize;
let o_y = image_y.floor() as usize;
let o_00_weight = o_x_weight * o_y_weight;
let o_01_weight = o_x_weight * (1.0 - o_y_weight);
let o_10_weight = (1.0 - o_x_weight) * o_y_weight;
let o_11_weight = (1.0 - o_x_weight) * (1.0 - o_y_weight);
let o_00_index = o_x + o_y * resolution;
let o_01_index = o_x + (o_y + 1) * resolution;
let o_10_index = o_x + 1 + o_y * resolution;
let o_11_index = o_x + 1 + (o_y + 1) * resolution;

let o_00_c = buf.spectrogram.image[o_00_index].a();
let o_01_c = buf.spectrogram.image[o_01_index].a();
let o_10_c = buf.spectrogram.image[o_10_index].a();
let o_11_c = buf.spectrogram.image[o_11_index].a();

let r = buf.setting.theme.main.r();
let g = buf.setting.theme.main.g();
let b = buf.setting.theme.main.b();
let boost = buf.setting.spectrogram.brightness_boost as f32;

buf.spectrogram.image[o_00_index] = Color32::from_rgba_unmultiplied(
r,
g,
b,
o_00_c.wrapping_add((boost * 255.0 * fft_x[i].norm() * o_00_weight) as u8),
);
buf.spectrogram.image[o_01_index] = Color32::from_rgba_unmultiplied(
r,
g,
b,
o_01_c.wrapping_add((boost * 255.0 * fft_x[i].norm() * o_01_weight) as u8),
);
buf.spectrogram.image[o_10_index] = Color32::from_rgba_unmultiplied(
r,
g,
b,
o_10_c.wrapping_add((boost * 255.0 * fft_x[i].norm() * o_10_weight) as u8),
);
buf.spectrogram.image[o_11_index] = Color32::from_rgba_unmultiplied(
r,
g,
b,
o_11_c.wrapping_add((boost * 255.0 * fft_x[i].norm() * o_11_weight) as u8),
);
}
}
send_data.spectrogram_image = buf.spectrogram.image[0..1920 * resolution].to_owned();
buf.spectrogram.ab = !buf.spectrogram.ab;
}

fn process_spectrum(buf: &mut AudioSourceBuffer, send_data: &mut SendData, data: &mut RawData) {
let mut real_planner = RealFftPlanner::<f32>::new();
let r2c = real_planner.plan_fft_forward(4096);
let mut spectrum = r2c.make_output_vec();
match buf.setting.spectrum.channel {
SpectrumChannel::LR => {
data.l.extend_from_slice(&[0.0; 2048]);
data.r.extend_from_slice(&[0.0; 2048]);
r2c.process(&mut data.l, &mut spectrum).unwrap();
send_data.spectrum.l = spectrum.clone().iter().map(|i| i.norm()).collect();
r2c.process(&mut data.r, &mut spectrum).unwrap();
send_data.spectrum.r = spectrum.clone().iter().map(|i| i.norm()).collect();
}
SpectrumChannel::MS => {
data.m.extend_from_slice(&[0.0; 2048]);
data.s.extend_from_slice(&[0.0; 2048]);
r2c.process(&mut data.m, &mut spectrum).unwrap();
send_data.spectrum.l = spectrum.clone().iter().map(|i| i.norm()).collect();
r2c.process(&mut data.s, &mut spectrum).unwrap();
send_data.spectrum.r = spectrum.clone().iter().map(|i| i.norm()).collect();
}
}
}
4 changes: 3 additions & 1 deletion src/frame/main_canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ impl NanometersApp {
let mut update_db_data = DBData::new();
let mut update_osc_data = OscilloscopeSendData::new();
let mut update_spectrogram_image = Vec::new();
let mut update_spectrum_data = RawData::new();

self.rx_data.as_mut().unwrap().try_iter().for_each(|data| {
update_iir_data.extend_from_slice(&data.iir);
Expand All @@ -88,6 +89,7 @@ impl NanometersApp {
update_waveform_data.concat(&data.waveform);
update_osc_data = data.oscilloscope;
update_spectrogram_image = data.spectrogram_image;
update_spectrum_data = data.spectrum;
});

ui.ctx().request_repaint();
Expand All @@ -108,7 +110,7 @@ impl NanometersApp {
self.oscilloscope_meter(&update_osc_data, meter_rect, ui);
}
ModuleList::Spectrum => {
self.spectrum_meter(meter_rect, ui);
self.spectrum_meter(&update_spectrum_data, meter_rect, ui);
}
ModuleList::Vectorscope => {
self.vectorscope_meter(&update_stereogram_data, meter_rect, ui);
Expand Down
1 change: 1 addition & 0 deletions src/frame/setting_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ impl NanometersApp {
&mut self.setting.spectrum.ref_line,
0.0..=22000.0,
)
.step_by(1.0)
.text("Hz"),
);
});
Expand Down
Loading

0 comments on commit de23257

Please sign in to comment.