grame-cncm / faust

Functional programming language for signal processing and sound synthesis
http://faust.grame.fr
Other
2.58k stars 322 forks source link

Rust backend produces unexpected output for physical model generators #445

Closed bluenote10 closed 4 years ago

bluenote10 commented 4 years ago

When experimenting with this simple Faust dsp

import("stdfaust.lib");

gate = 1.0;
freq = 440.0;

process = pm.elecGuitar(
  pm.f2l(freq),
  hslider("pluck position", 0.9, 0, 1, 0.01),
  hslider("mute", 1.0, 0, 1, 0.01),
  hslider("pluck gain", 0.8, 0, 1, 0.01),
  gate
);

I'm not quite getting the expected output from the Rust backend.

Testing this Faust code in the online IDE suggest that it is correct in general, producing a single note output. With the Rust backend I'm only getting 108 non-zero output samples, then the signal dies to zero, which is essentially just a short clicking noise.

I have prepared a minimal architecture file I'm using to debug the Rust output:

Debug architecture file ```rust #![allow(unused_parens)] #![allow(non_snake_case)] #![allow(non_camel_case_types)] #![allow(dead_code)] #![allow(unused_variables)] #![allow(unused_mut)] #![allow(non_upper_case_globals)] extern crate libm; use std::fs::File; use std::io::Write; pub trait Meta { // -- metadata declarations fn declare(&mut self, key: &str, value: &str) -> (); } pub trait UI { // -- widget's layouts fn openTabBox(&mut self, label: &str) -> (); fn openHorizontalBox(&mut self, label: &str) -> (); fn openVerticalBox(&mut self, label: &str) -> (); fn closeBox(&mut self) -> (); // -- active widgets fn addButton(&mut self, label: &str, zone: &mut T) -> (); fn addCheckButton(&mut self, label: &str, zone: &mut T) -> (); fn addVerticalSlider(&mut self, label: &str, zone: &mut T, init: T, min: T, max: T, step: T) -> (); fn addHorizontalSlider(&mut self, label: &str, zone: &mut T , init: T, min: T, max: T, step: T) -> (); fn addNumEntry(&mut self, label: &str, zone: &mut T, init: T, min: T, max: T, step: T) -> (); // -- passive widgets fn addHorizontalBargraph(&mut self, label: &str, zone: &mut T, min: T, max: T) -> (); fn addVerticalBargraph(&mut self, label: &str, zone: &mut T, min: T, max: T) -> (); // -- metadata declarations fn declare(&mut self, zone: &mut T, key: &str, value: &str) -> (); } // Generated intrinsics: <> // Generated class: <> fn main() { // Generation constants let sample_rate = 44100; let buffer_size = 64usize; let num_buffers_to_generate = 100; // Init dsp let mut dsp = Box::new(mydsp::new()); dsp.init(sample_rate); assert_eq!(dsp.getNumOutputs(), 1); // Prepare buffers let mut out_buffer = vec![0 as f32; buffer_size]; // Prepare debug output file let mut debug_output_file = File::create("debug.txt").expect("Cannot create output file"); // Compute for _ in 0..num_buffers_to_generate { dsp.compute( buffer_size as i32, &[], &mut[&mut out_buffer], ); for i in 0..buffer_size { writeln!(debug_output_file, "{}", out_buffer[i]).expect("Failed to write to file"); } } } ```

The generated code is:

Generated code ```rust #![allow(unused_parens)] #![allow(non_snake_case)] #![allow(non_camel_case_types)] #![allow(dead_code)] #![allow(unused_variables)] #![allow(unused_mut)] #![allow(non_upper_case_globals)] extern crate libm; use std::fs::File; use std::io::Write; pub trait Meta { // -- metadata declarations fn declare(&mut self, key: &str, value: &str) -> (); } pub trait UI { // -- widget's layouts fn openTabBox(&mut self, label: &str) -> (); fn openHorizontalBox(&mut self, label: &str) -> (); fn openVerticalBox(&mut self, label: &str) -> (); fn closeBox(&mut self) -> (); // -- active widgets fn addButton(&mut self, label: &str, zone: &mut T) -> (); fn addCheckButton(&mut self, label: &str, zone: &mut T) -> (); fn addVerticalSlider(&mut self, label: &str, zone: &mut T, init: T, min: T, max: T, step: T) -> (); fn addHorizontalSlider(&mut self, label: &str, zone: &mut T , init: T, min: T, max: T, step: T) -> (); fn addNumEntry(&mut self, label: &str, zone: &mut T, init: T, min: T, max: T, step: T) -> (); // -- passive widgets fn addHorizontalBargraph(&mut self, label: &str, zone: &mut T, min: T, max: T) -> (); fn addVerticalBargraph(&mut self, label: &str, zone: &mut T, min: T, max: T) -> (); // -- metadata declarations fn declare(&mut self, zone: &mut T, key: &str, value: &str) -> (); } // Generated intrinsics: // Generated class: pub fn Dsp_faustpower2_f(value: f32) -> f32 { return (value * value); } pub struct Dsp { fDummy: f32, fHslider0: f32, fVec0: [f32;2], fSampleRate: i32, fConst0: f32, fConst1: f32, fHslider1: f32, fConst2: f32, fRec25: [f32;2], fRec29: [f32;2], fRec31: [f32;4], IOTA: i32, fRec32: [f32;256], fVec1: [f32;2], fConst3: f32, fConst4: f32, fConst5: f32, fHslider2: f32, iRec34: [i32;2], fConst6: f32, fConst7: f32, fRec33: [f32;3], fConst8: f32, iRec35: [i32;2], fVec2: [f32;3], fRec30: [f32;256], fRec21: [f32;2], fRec17: [f32;2], fRec13: [f32;256], fRec15: [f32;2], fRec11: [f32;4], fRec6: [f32;2], fRec2: [f32;256], fRec0: [f32;2], } impl Dsp { pub fn new() -> Dsp { Dsp { fDummy: 0 as f32, fHslider0: 0.0, fVec0: [0.0;2], fSampleRate: 0, fConst0: 0.0, fConst1: 0.0, fHslider1: 0.0, fConst2: 0.0, fRec25: [0.0;2], fRec29: [0.0;2], fRec31: [0.0;4], IOTA: 0, fRec32: [0.0;256], fVec1: [0.0;2], fConst3: 0.0, fConst4: 0.0, fConst5: 0.0, fHslider2: 0.0, iRec34: [0;2], fConst6: 0.0, fConst7: 0.0, fRec33: [0.0;3], fConst8: 0.0, iRec35: [0;2], fVec2: [0.0;3], fRec30: [0.0;256], fRec21: [0.0;2], fRec17: [0.0;2], fRec13: [0.0;256], fRec15: [0.0;2], fRec11: [0.0;4], fRec6: [0.0;2], fRec2: [0.0;256], fRec0: [0.0;2], } } pub fn metadata(&mut self, m: &mut Meta) { m.declare("delays.lib/name", "Faust Delay Library"); m.declare("delays.lib/version", "0.1"); m.declare("envelopes.lib/ar:author", "Yann Orlarey, Stéphane Letz"); m.declare("envelopes.lib/author", "GRAME"); m.declare("envelopes.lib/copyright", "GRAME"); m.declare("envelopes.lib/license", "LGPL with exception"); m.declare("envelopes.lib/name", "Faust Envelope Library"); m.declare("envelopes.lib/version", "0.0"); m.declare("filename", "gen_guitar_pm1.dsp"); m.declare("filters.lib/fir:author", "Julius O. Smith III"); m.declare("filters.lib/fir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m.declare("filters.lib/fir:license", "MIT-style STK-4.3 license"); m.declare("filters.lib/iir:author", "Julius O. Smith III"); m.declare("filters.lib/iir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m.declare("filters.lib/iir:license", "MIT-style STK-4.3 license"); m.declare("filters.lib/lowpass0_highpass1", "Copyright (C) 2003-2019 by Julius O. Smith III "); m.declare("filters.lib/lowpass0_highpass1:author", "Julius O. Smith III"); m.declare("filters.lib/lowpass:author", "Julius O. Smith III"); m.declare("filters.lib/lowpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m.declare("filters.lib/lowpass:license", "MIT-style STK-4.3 license"); m.declare("filters.lib/name", "Faust Filters Library"); m.declare("filters.lib/tf2:author", "Julius O. Smith III"); m.declare("filters.lib/tf2:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m.declare("filters.lib/tf2:license", "MIT-style STK-4.3 license"); m.declare("filters.lib/tf2s:author", "Julius O. Smith III"); m.declare("filters.lib/tf2s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m.declare("filters.lib/tf2s:license", "MIT-style STK-4.3 license"); m.declare("maths.lib/author", "GRAME"); m.declare("maths.lib/copyright", "GRAME"); m.declare("maths.lib/license", "LGPL with exception"); m.declare("maths.lib/name", "Faust Math Library"); m.declare("maths.lib/version", "2.1"); m.declare("name", "gen_guitar_pm1"); m.declare("noises.lib/name", "Faust Noise Generator Library"); m.declare("noises.lib/version", "0.0"); m.declare("routes.lib/name", "Faust Signal Routing Library"); m.declare("routes.lib/version", "0.1"); m.declare("signals.lib/name", "Faust Signal Routing Library"); m.declare("signals.lib/version", "0.0"); } pub fn getSampleRateDsp(&mut self) -> i32 { return self.fSampleRate; } pub fn getNumInputs(&mut self) -> i32 { return 0; } pub fn getNumOutputs(&mut self) -> i32 { return 1; } pub fn getInputRate(&mut self, channel: i32) -> i32 { let mut rate: i32; match (channel) { _ => { rate = -1; }, } return rate; } pub fn getOutputRate(&mut self, channel: i32) -> i32 { let mut rate: i32; match (channel) { 0 => { rate = 1; }, _ => { rate = -1; }, } return rate; } pub fn classInit(sample_rate: i32) { } pub fn instanceResetUserInterface(&mut self) { self.fHslider0 = 1.0; self.fHslider1 = 0.899999976; self.fHslider2 = 0.800000012; } pub fn instanceClear(&mut self) { for l0 in 0..2 { self.fVec0[l0 as usize] = 0.0; } for l1 in 0..2 { self.fRec25[l1 as usize] = 0.0; } for l2 in 0..2 { self.fRec29[l2 as usize] = 0.0; } for l3 in 0..4 { self.fRec31[l3 as usize] = 0.0; } self.IOTA = 0; for l4 in 0..256 { self.fRec32[l4 as usize] = 0.0; } for l5 in 0..2 { self.fVec1[l5 as usize] = 0.0; } for l6 in 0..2 { self.iRec34[l6 as usize] = 0; } for l7 in 0..3 { self.fRec33[l7 as usize] = 0.0; } for l8 in 0..2 { self.iRec35[l8 as usize] = 0; } for l9 in 0..3 { self.fVec2[l9 as usize] = 0.0; } for l10 in 0..256 { self.fRec30[l10 as usize] = 0.0; } for l11 in 0..2 { self.fRec21[l11 as usize] = 0.0; } for l12 in 0..2 { self.fRec17[l12 as usize] = 0.0; } for l13 in 0..256 { self.fRec13[l13 as usize] = 0.0; } for l14 in 0..2 { self.fRec15[l14 as usize] = 0.0; } for l15 in 0..4 { self.fRec11[l15 as usize] = 0.0; } for l16 in 0..2 { self.fRec6[l16 as usize] = 0.0; } for l17 in 0..256 { self.fRec2[l17 as usize] = 0.0; } for l18 in 0..2 { self.fRec0[l18 as usize] = 0.0; } } pub fn instanceConstants(&mut self, sample_rate: i32) { self.fSampleRate = sample_rate; self.fConst0 = f32::min(192000.0, f32::max(1.0, (self.fSampleRate as f32))); self.fConst1 = (0.000974598923 * self.fConst0); self.fConst2 = (0.00882352982 * self.fConst0); self.fConst3 = f32::tan((6911.50391 / self.fConst0)); self.fConst4 = (1.0 / self.fConst3); self.fConst5 = (1.0 / (((self.fConst4 + 1.41421354) / self.fConst3) + 1.0)); self.fConst6 = (((self.fConst4 + -1.41421354) / self.fConst3) + 1.0); self.fConst7 = (2.0 * (1.0 - (1.0 / Dsp_faustpower2_f(self.fConst3)))); self.fConst8 = (1.0 / f32::max(1.0, (0.00121679995 * self.fConst0))); } pub fn instanceInit(&mut self, sample_rate: i32) { self.instanceConstants(sample_rate); self.instanceResetUserInterface(); self.instanceClear(); } pub fn init(&mut self, sample_rate: i32) { Dsp::classInit(sample_rate); self.instanceInit(sample_rate); } pub fn buildUserInterface(&mut self, ui_interface: &mut UI) { ui_interface.openVerticalBox("gen_guitar_pm1"); ui_interface.addHorizontalSlider("mute", &mut self.fHslider0, 1.0, 0.0, 1.0, 0.01); ui_interface.addHorizontalSlider("pluck gain", &mut self.fHslider2, 0.80000000000000004, 0.0, 1.0, 0.01); ui_interface.addHorizontalSlider("pluck position", &mut self.fHslider1, 0.90000000000000002, 0.0, 1.0, 0.01); ui_interface.closeBox(); } pub fn compute(&mut self, count: i32, inputs: &[&[f32]], outputs: &mut[&mut[f32]]) { let mut fSlow0: f32 = (self.fHslider0 as f32); let mut fSlow1: f32 = (self.fHslider1 as f32); let mut fSlow2: f32 = (self.fConst1 * (1.0 - fSlow1)); let mut fSlow3: f32 = (fSlow2 + -1.49999499); let mut fSlow4: f32 = f32::floor(fSlow3); let mut fSlow5: f32 = (fSlow2 + (-1.0 - fSlow4)); let mut fSlow6: f32 = (fSlow2 + (-2.0 - fSlow4)); let mut fSlow7: f32 = (fSlow2 + (-3.0 - fSlow4)); let mut fSlow8: f32 = (fSlow2 + (-4.0 - fSlow4)); let mut fSlow9: f32 = ((((0.0 - fSlow5) * (0.0 - (0.5 * fSlow6))) * (0.0 - (0.333333343 * fSlow7))) * (0.0 - (0.25 * fSlow8))); let mut iSlow10: i32 = (fSlow3 as i32); let mut iSlow11: i32 = (f32::min(self.fConst2, (std::cmp::max(0, iSlow10) as f32)) as i32); let mut iSlow12: i32 = (iSlow11 + 1); let mut fSlow13: f32 = (fSlow2 - fSlow4); let mut fSlow14: f32 = (((0.0 - fSlow6) * (0.0 - (0.5 * fSlow7))) * (0.0 - (0.333333343 * fSlow8))); let mut iSlow15: i32 = (f32::min(self.fConst2, (std::cmp::max(0, (iSlow10 + 1)) as f32)) as i32); let mut iSlow16: i32 = (iSlow15 + 1); let mut fSlow17: f32 = (0.5 * ((fSlow5 * (0.0 - fSlow7)) * (0.0 - (0.5 * fSlow8)))); let mut iSlow18: i32 = (f32::min(self.fConst2, (std::cmp::max(0, (iSlow10 + 2)) as f32)) as i32); let mut iSlow19: i32 = (iSlow18 + 1); let mut fSlow20: f32 = (fSlow5 * fSlow6); let mut fSlow21: f32 = (0.166666672 * (fSlow20 * (0.0 - fSlow8))); let mut iSlow22: i32 = (f32::min(self.fConst2, (std::cmp::max(0, (iSlow10 + 3)) as f32)) as i32); let mut iSlow23: i32 = (iSlow22 + 1); let mut fSlow24: f32 = (0.0416666679 * (fSlow20 * fSlow7)); let mut iSlow25: i32 = (f32::min(self.fConst2, (std::cmp::max(0, (iSlow10 + 4)) as f32)) as i32); let mut iSlow26: i32 = (iSlow25 + 1); let mut fSlow27: f32 = (self.fConst1 * fSlow1); let mut fSlow28: f32 = (fSlow27 + -1.49999499); let mut fSlow29: f32 = f32::floor(fSlow28); let mut fSlow30: f32 = (fSlow27 + (-1.0 - fSlow29)); let mut fSlow31: f32 = (fSlow27 + (-2.0 - fSlow29)); let mut fSlow32: f32 = (fSlow27 + (-3.0 - fSlow29)); let mut fSlow33: f32 = (fSlow27 + (-4.0 - fSlow29)); let mut fSlow34: f32 = ((((0.0 - fSlow30) * (0.0 - (0.5 * fSlow31))) * (0.0 - (0.333333343 * fSlow32))) * (0.0 - (0.25 * fSlow33))); let mut iSlow35: i32 = (fSlow28 as i32); let mut iSlow36: i32 = (f32::min(self.fConst2, (std::cmp::max(0, iSlow35) as f32)) as i32); let mut iSlow37: i32 = (iSlow36 + 2); let mut fSlow38: f32 = (fSlow27 - fSlow29); let mut fSlow39: f32 = (((0.0 - fSlow31) * (0.0 - (0.5 * fSlow32))) * (0.0 - (0.333333343 * fSlow33))); let mut iSlow40: i32 = (f32::min(self.fConst2, (std::cmp::max(0, (iSlow35 + 1)) as f32)) as i32); let mut iSlow41: i32 = (iSlow40 + 2); let mut fSlow42: f32 = (0.5 * ((fSlow30 * (0.0 - fSlow32)) * (0.0 - (0.5 * fSlow33)))); let mut iSlow43: i32 = (f32::min(self.fConst2, (std::cmp::max(0, (iSlow35 + 2)) as f32)) as i32); let mut iSlow44: i32 = (iSlow43 + 2); let mut fSlow45: f32 = (fSlow30 * fSlow31); let mut fSlow46: f32 = (0.166666672 * (fSlow45 * (0.0 - fSlow33))); let mut iSlow47: i32 = (f32::min(self.fConst2, (std::cmp::max(0, (iSlow35 + 3)) as f32)) as i32); let mut iSlow48: i32 = (iSlow47 + 2); let mut fSlow49: f32 = (0.0416666679 * (fSlow45 * fSlow32)); let mut iSlow50: i32 = (f32::min(self.fConst2, (std::cmp::max(0, (iSlow35 + 4)) as f32)) as i32); let mut iSlow51: i32 = (iSlow50 + 2); let mut fSlow52: f32 = (self.fConst5 * (self.fHslider2 as f32)); let mut iSlow53: i32 = (iSlow36 + 1); let mut iSlow54: i32 = (iSlow40 + 1); let mut iSlow55: i32 = (iSlow43 + 1); let mut iSlow56: i32 = (iSlow47 + 1); let mut iSlow57: i32 = (iSlow50 + 1); for i in 0..count { let mut fRec10: f32 = (-1.0 * (0.997305274 * ((0.899999976 * self.fRec11[2]) + (0.0500000007 * (self.fRec11[1] + self.fRec11[3]))))); self.fVec0[0] = 1.0; self.fRec25[0] = ((fSlow9 * self.fRec2[((self.IOTA - iSlow12) & 255) as usize]) + (fSlow13 * ((((fSlow14 * self.fRec2[((self.IOTA - iSlow16) & 255) as usize]) + (fSlow17 * self.fRec2[((self.IOTA - iSlow19) & 255) as usize])) + (fSlow21 * self.fRec2[((self.IOTA - iSlow23) & 255) as usize])) + (fSlow24 * self.fRec2[((self.IOTA - iSlow26) & 255) as usize])))); self.fRec29[0] = ((0.0500000007 * self.fRec29[1]) + (0.949999988 * self.fRec25[1])); let mut fRec26: f32 = self.fRec29[0]; self.fRec31[0] = self.fRec0[1]; self.fRec32[(self.IOTA & 255) as usize] = (-1.0 * (0.997305274 * ((0.899999976 * self.fRec31[2]) + (0.0500000007 * (self.fRec31[1] + self.fRec31[3]))))); self.fVec1[0] = ((fSlow34 * self.fRec32[((self.IOTA - iSlow37) & 255) as usize]) + (fSlow38 * ((((fSlow39 * self.fRec32[((self.IOTA - iSlow41) & 255) as usize]) + (fSlow42 * self.fRec32[((self.IOTA - iSlow44) & 255) as usize])) + (fSlow46 * self.fRec32[((self.IOTA - iSlow48) & 255) as usize])) + (fSlow49 * self.fRec32[((self.IOTA - iSlow51) & 255) as usize])))); self.iRec34[0] = ((1103515245 * self.iRec34[1]) + 12345); self.fRec33[0] = ((4.65661287e-10 * (self.iRec34[0] as f32)) - (self.fConst5 * ((self.fConst6 * self.fRec33[2]) + (self.fConst7 * self.fRec33[1])))); self.iRec35[0] = (((1.0 > self.fVec0[1]) as i32) + (((1.0 <= self.fVec0[1]) as i32) * (self.iRec35[1] + ((self.iRec35[1] > 0) as i32)))); let mut fTemp0: f32 = (self.fConst8 * (self.iRec35[0] as f32)); let mut fTemp1: f32 = (fSlow52 * ((self.fRec33[2] + (self.fRec33[0] + (2.0 * self.fRec33[1]))) * f32::max(0.0, f32::min(fTemp0, (2.0 - fTemp0))))); let mut fTemp2: f32 = (self.fVec1[1] + fTemp1); self.fVec2[0] = fTemp2; self.fRec30[(self.IOTA & 255) as usize] = ((0.0500000007 * self.fRec30[((self.IOTA - 1) & 255) as usize]) + (0.949999988 * self.fVec2[2])); let mut fRec27: f32 = ((fSlow9 * self.fRec30[((self.IOTA - iSlow11) & 255) as usize]) + (fSlow13 * ((((fSlow14 * self.fRec30[((self.IOTA - iSlow15) & 255) as usize]) + (fSlow17 * self.fRec30[((self.IOTA - iSlow18) & 255) as usize])) + (fSlow21 * self.fRec30[((self.IOTA - iSlow22) & 255) as usize])) + (fSlow24 * self.fRec30[((self.IOTA - iSlow25) & 255) as usize])))); let mut fRec28: f32 = (self.fVec2[1] + self.fRec21[1]); self.fRec21[0] = fRec26; let mut fRec22: f32 = self.fRec21[1]; let mut fRec23: f32 = fRec27; let mut fRec24: f32 = fRec28; self.fRec17[0] = fRec22; let mut fRec18: f32 = (fTemp1 + self.fRec17[1]); let mut fRec19: f32 = fRec23; let mut fRec20: f32 = fRec24; self.fRec13[(self.IOTA & 255) as usize] = fRec18; let mut fRec14: f32 = ((fSlow34 * self.fRec13[((self.IOTA - iSlow53) & 255) as usize]) + (fSlow38 * ((((fSlow39 * self.fRec13[((self.IOTA - iSlow54) & 255) as usize]) + (fSlow42 * self.fRec13[((self.IOTA - iSlow55) & 255) as usize])) + (fSlow46 * self.fRec13[((self.IOTA - iSlow56) & 255) as usize])) + (fSlow49 * self.fRec13[((self.IOTA - iSlow57) & 255) as usize])))); self.fRec15[0] = fRec19; let mut fRec16: f32 = fRec20; self.fRec11[0] = (fSlow0 * self.fRec15[1]); let mut fRec12: f32 = fRec16; self.fRec6[0] = fRec10; let mut fRec7: f32 = (fSlow0 * self.fRec6[1]); let mut fRec8: f32 = self.fRec11[0]; let mut fRec9: f32 = fRec12; self.fRec2[(self.IOTA & 255) as usize] = fRec7; let mut fRec3: f32 = fRec14; let mut fRec4: f32 = fRec8; let mut fRec5: f32 = fRec9; self.fRec0[0] = fRec3; let mut fRec1: f32 = fRec5; outputs[0][i as usize] = (fRec1 as f32); self.fVec0[1] = self.fVec0[0]; self.fRec25[1] = self.fRec25[0]; self.fRec29[1] = self.fRec29[0]; for j0 in 4..0 { self.fRec31[j0 as usize] = self.fRec31[(j0 - 1) as usize]; } self.IOTA = (self.IOTA + 1); self.fVec1[1] = self.fVec1[0]; self.iRec34[1] = self.iRec34[0]; self.fRec33[2] = self.fRec33[1]; self.fRec33[1] = self.fRec33[0]; self.iRec35[1] = self.iRec35[0]; self.fVec2[2] = self.fVec2[1]; self.fVec2[1] = self.fVec2[0]; self.fRec21[1] = self.fRec21[0]; self.fRec17[1] = self.fRec17[0]; self.fRec15[1] = self.fRec15[0]; for j1 in 4..0 { self.fRec11[j1 as usize] = self.fRec11[(j1 - 1) as usize]; } self.fRec6[1] = self.fRec6[0]; self.fRec0[1] = self.fRec0[0]; } } } fn main() { // Generation constants let sample_rate = 44100; let buffer_size = 64usize; let num_buffers_to_generate = 100; // Init dsp let mut dsp = Box::new(Dsp::new()); dsp.init(sample_rate); assert_eq!(dsp.getNumOutputs(), 1); // Prepare buffers let mut out_buffer = vec![0 as f32; buffer_size]; // Prepare debug output file let mut debug_output_file = File::create("debug.txt").expect("Cannot create output file"); // Compute for _ in 0..num_buffers_to_generate { dsp.compute( buffer_size as i32, &[], &mut[&mut out_buffer], ); for i in 0..buffer_size { writeln!(debug_output_file, "{}", out_buffer[i]).expect("Failed to write to file"); } } } ```

Visualizing the content of the generated debug.txt gives:

image

All subsequent output samples are exactly zero.

Note that it is necessary to run the example in release mode because of #432 (attempt to multiply with overflow). I'm not sure if that is directly related, because I thought that release mode would implicitly have wrapping semantics.

sletz commented 4 years ago

TBH the Rust backend has not been formally tested yet, so it may still contain bugs.

You can have a look at the validation tests here https://github.com/grame-cncm/faust/tree/master-dev/tests/impulse-tests and https://github.com/grame-cncm/faust/blob/master-dev/tests/impulse-tests/README.md and possibly contribute a "rust" target?

bluenote10 commented 4 years ago

Good idea, that should help to narrow down the cause. I'll give it a shot this evening.

sletz commented 4 years ago

That would be great, thanks!

bluenote10 commented 4 years ago

I can confirm that 4b6bed3 has resolved this issue, thanks again! The example produces a nice ringing tone now:

image