diff --git a/compiler/generator/instructions_compiler.cpp b/compiler/generator/instructions_compiler.cpp index 65a0002070..c956bed30d 100644 --- a/compiler/generator/instructions_compiler.cpp +++ b/compiler/generator/instructions_compiler.cpp @@ -578,7 +578,15 @@ void InstructionsCompiler::compileMultiSignal(Tree L) string name; if (gGlobal->gOutputLang == "rust") { name = subst("*output$0", T(index)); - pushComputeDSPMethod(IB::genStoreStackVar(name, res)); + if (gGlobal->gComputeMix) { + // take the cpp code and remove the the loop + ValueInst* res1 = IB::genAdd(res, IB::genLoadStackVar(name)); + pushComputeDSPMethod(IB::genStoreStackVar(name, res1)); + } else { + pushComputeDSPMethod(IB::genStoreStackVar(name, res)); + } + + } else if (gGlobal->gOutputLang == "jax") { res = CS(sig); string result_var = "_result" + to_string(index); @@ -1130,9 +1138,14 @@ ValueInst* InstructionsCompiler::generateVariableStore(Tree sig, ValueInst* exp) return IB::genLoadStructVar(vname); } } else { - // "Slow" variables are declared as locals in 'frame' or 'compute' functions - pushComputeBlockMethod(IB::genDecStackVar(vname, ctype, exp)); - return IB::genLoadStackVar(vname); + if (gGlobal->gOneSample) { + pushControlDeclare(IB::genDecStackVar(vname, ctype, exp)); + return IB::genLoadStackVar(vname); + } else { + // "Slow" variables are declared as locals in 'frame' or 'compute' functions + pushComputeBlockMethod(IB::genDecStackVar(vname, ctype, exp)); + return IB::genLoadStackVar(vname); + } } } @@ -1170,9 +1183,13 @@ ValueInst* InstructionsCompiler::generateVariableStore(Tree sig, ValueInst* exp) getConditionCode(sig), IB::genStoreStructVar(vname_perm, exp))); return IB::genLoadStructVar(vname_perm); } else { - // copy the object variable to the local one - pushComputeBlockMethod( - IB::genDecStackVar(vname, ctype, IB::genLoadStructVar(vname_perm))); + if (gGlobal->gOneSample) { + pushControlDeclare(IB::genDecStackVar(vname, ctype, IB::genLoadStructVar(vname_perm))); + } else { + // copy the object variable to the local one + pushComputeBlockMethod( + IB::genDecStackVar(vname, ctype, IB::genLoadStructVar(vname_perm))); + } // execute the code pushComputeDSPMethod(IB::genControlInst(getConditionCode(sig), IB::genStoreStackVar(vname, exp))); diff --git a/compiler/generator/rust/rust_code_container.cpp b/compiler/generator/rust/rust_code_container.cpp index 75c06e9b68..9dbf5ace44 100644 --- a/compiler/generator/rust/rust_code_container.cpp +++ b/compiler/generator/rust/rust_code_container.cpp @@ -238,6 +238,8 @@ void RustCodeContainer::produceClass() tab(n, *fOut); *fOut << "use std::convert::TryInto;"; + tab(n, *fOut); + *fOut << "use std::borrow;"; // Generate gub containers generateSubContainers(); @@ -511,14 +513,30 @@ void RustCodeContainer::produceClass() // Parameter getter/setter produceParameterGetterSetter(n + 1, parameterLookup); + // Control + if (gGlobal->gExtControl) { + tab(n + 1, *fOut); + tab(n + 1, *fOut); + *fOut << "pub fn control(&mut self) {"; + tab(n + 2, *fOut); + generateControlDeclarations(&fCodeProducer); + back(1, *fOut); + *fOut << "}"; + } + // Compute - generateCompute(n + 1); - generateComputeInterface(n + 1); + if (gGlobal->gOneSample) { + generateComputeFrame(n + 1); + } else { + generateCompute(n + 1); + } tab(n, *fOut); *fOut << "}" << endl; tab(n, *fOut); - produceFaustDspBlob(); + if (!gGlobal->gRustNoTraitSwitch) { + produceFaustDspBlob(); + } } void RustCodeContainer::produceMetadata(int n) @@ -611,39 +629,68 @@ void RustCodeContainer::generateComputeHeader(int n, std::ostream* fOut, int fNu // Compute "compute" declaration tab(n, *fOut); tab(n, *fOut); - *fOut << "pub fn compute_arrays(" - << "&mut self, " << fFullCount << ": usize, inputs: &[&[FaustFloat] ; " << fNumInputs - << "]" - << ", outputs: &mut [&mut [FaustFloat] ; " << fNumOutputs << "]) {"; + *fOut << "pub fn compute("; tab(n + 1, *fOut); -} - -void RustCodeContainer::generateComputeInterfaceHeader(int n, std::ostream* fOut, int fNumInputs, - int fNumOutputs) -{ - // Compute "compute" declaration - *fOut << "pub fn compute(" - << "&mut self, " << fFullCount << ": usize, inputs: & [& [FaustFloat] ]" - << ", outputs: & mut[& mut[FaustFloat] ]) {"; + *fOut << "&mut self,"; + tab(n + 1, *fOut); + *fOut << "count: usize,"; + tab(n + 1, *fOut); + *fOut << "inputs: impl borrow::Borrow<[InType]>,"; + tab(n + 1, *fOut); + *fOut << "mut outputs: impl borrow::BorrowMut<[OutType]>,"; + tab(n, *fOut); + *fOut << ") where"; + tab(n + 1, *fOut); + *fOut << "InType: borrow::Borrow<[FaustFloat]>,"; + tab(n + 1, *fOut); + *fOut << "OutType: borrow::BorrowMut<[FaustFloat]>,"; + tab(n, *fOut); + *fOut << "{"; tab(n + 1, *fOut); } -void RustCodeContainer::generateComputeInterface(int n) +void RustCodeContainer::generateComputeFrame(int n) { - // Generates declaration tab(n, *fOut); tab(n, *fOut); - generateComputeInterfaceHeader(n, fOut, fNumInputs, fNumOutputs); + *fOut << "pub fn compute_frame(&mut self, inputs: &[&FaustFloat], "; + *fOut << "outputs: &mut [&mut FaustFloat]) {"; - *fOut << "let input_array = inputs.split_at(" << fNumInputs - << ").0.try_into().expect(\"too few input buffers\");"; - tab(n + 1, *fOut); - *fOut << "let output_array = outputs.split_at_mut(" << fNumOutputs - << ").0.try_into().expect(\"too few output buffers\");"; - tab(n + 1, *fOut); - *fOut << "self.compute_arrays(count, input_array, output_array);"; + for(int i = 0; i < fNumInputs; i++){ + tab(n+1, *fOut); + *fOut << "let input"<< i <<" = inputs["<< i <<"];"; + }; + + for(int i = 0; i < fNumOutputs; i++){ + tab(n+1, *fOut); + *fOut << "let (nextoutput, outputs): (&mut [&mut f64], &mut [&mut f64]) = outputs.split_at_mut(1);"; + tab(n+1, *fOut); + *fOut << "let output"<< i <<": &mut FaustFloat = nextoutput[0];"; + }; + + fCodeProducer.Tab(n + 1); + + if (!gGlobal->gExtControl) { + generateControlDeclarations(&fCodeProducer); + } else { + } + + tab(n+1, *fOut); + *fOut << "//generateOneSample"; + tab(n+1, *fOut); + // Generates one sample computation + BlockInst* block = fCurLoop->generateOneSample(); + block->accept(&fCodeProducer); + + /* + // TODO : atomic switch + // Currently for soundfile management + // also for temp vars + */ + generatePostComputeBlock(&fCodeProducer); + tab(n, *fOut); + *fOut << "}"; tab(n, *fOut); - *fOut << "}" << endl; } // Scalar @@ -663,7 +710,7 @@ void RustScalarCodeContainer::generateCompute(int n) tab(n + 1, *fOut); fCodeProducer.Tab(n + 1); - // Generates local variables declaration and setup + generateComputeBlock(&fCodeProducer); // Generates one single scalar loop @@ -678,9 +725,10 @@ void RustScalarCodeContainer::generateCompute(int n) loop->accept(&fCodeProducer); // Currently for soundfile management + // and for temp vars generatePostComputeBlock(&fCodeProducer); - back(1, *fOut); + tab(n, *fOut); *fOut << "}" << endl; } diff --git a/compiler/generator/rust/rust_code_container.hh b/compiler/generator/rust/rust_code_container.hh index 4f90a80a16..a48c1d72c5 100644 --- a/compiler/generator/rust/rust_code_container.hh +++ b/compiler/generator/rust/rust_code_container.hh @@ -55,8 +55,7 @@ class RustCodeContainer : public virtual CodeContainer { virtual void produceClass(); void generateComputeHeader(int n, std::ostream* fOut, int fNumInputs, int fNumOutputs); - void generateComputeInterfaceHeader(int n, std::ostream* fOut, int fNumInputs, int fNumOutputs); - void generateComputeInterface(int tab); + void generateComputeFrame(int tab); virtual void generateCompute(int tab) = 0; void produceInternal(); void produceFaustDspBlob(); diff --git a/compiler/generator/rust/rust_instructions.hh b/compiler/generator/rust/rust_instructions.hh index 89f77c13ca..4b4fdbbbb9 100644 --- a/compiler/generator/rust/rust_instructions.hh +++ b/compiler/generator/rust/rust_instructions.hh @@ -225,13 +225,9 @@ class RustInstVisitor : public TextInstVisitor { virtual void visit(DeclareBufferIterators* inst) { /* Generates an expression like: - let (outputs0, outputs1) = if let [outputs0, outputs1, ..] = outputs { - let outputs0 = outputs0[..count as usize].iter_mut(); - let outputs1 = outputs1[..count as usize].iter_mut(); - (outputs0, outputs1) - } else { - panic!("wrong number of outputs"); - }; + let [outputs0, outputs1] = outputs.borrow_mut(); + let outputs0 = outputs0.borrow_mut[..count].iter_mut(); + let outputs1 = outputs1.borrow_mut[..count].iter_mut(); */ // Don't generate if no channels @@ -245,24 +241,30 @@ class RustInstVisitor : public TextInstVisitor { for (int i = 0; i < inst->fChannels; ++i) { *fOut << name << i << ", "; } - *fOut << "] = " << name << ";"; + *fOut << "] = " << name; + if (inst->fMutable) { + *fOut << ".borrow_mut() else { panic!(\"wrong number of outputs\"); };"; + } else { + *fOut << ".borrow() else { panic!(\"wrong number of inputs\"); };"; + } // Build fixed size iterator variables for (int i = 0; i < inst->fChannels; ++i) { tab(fTab, *fOut); - *fOut << "let " << name << i << " = " << name << i << "[..count as usize]"; + *fOut << "let " << name << i << " = " << name << i; + ; if (inst->fMutable) { if (inst->fChunk) { - *fOut << ".chunks_mut(vsize as usize);"; + *fOut << ".borrow_mut()[..count].chunks_mut(vsize as usize);"; } else { - *fOut << ".iter_mut();"; + *fOut << ".borrow_mut()[..count].iter_mut();"; } } else { if (inst->fChunk) { - *fOut << ".chunks(vsize as usize);"; + *fOut << ".borrow()[..count].chunks(vsize as usize);"; } else { - *fOut << ".iter();"; + *fOut << ".borrow()[..count].iter();"; } } } diff --git a/compiler/global.cpp b/compiler/global.cpp index 93f1d552a2..97c26d8757 100644 --- a/compiler/global.cpp +++ b/compiler/global.cpp @@ -451,7 +451,9 @@ void global::reset() gGroupTaskSwitch = false; gFunTaskSwitch = false; - gUIMacroSwitch = false; + gUIMacroSwitch = false; + gRustNoTraitSwitch = false; + gDumpNorm = -1; gFTZMode = 0; gRangeUI = false; @@ -1371,6 +1373,10 @@ bool global::processCmdline(int argc, const char* argv[]) gUIMacroSwitch = true; i += 1; + } else if (isCmd(argv[i], "-rnt", "--rust-no-faustdsp-trait")) { + gRustNoTraitSwitch = true; + i += 1; + } else if (isCmd(argv[i], "-t", "--timeout") && (i + 1 < argc)) { gTimeout = std::atoi(argv[i + 1]); i += 2; @@ -1672,15 +1678,15 @@ bool global::processCmdline(int argc, const char* argv[]) } #endif if (gOneSample && gOutputLang != "cpp" && gOutputLang != "c" && gOutputLang != "dlang" && - !startWith(gOutputLang, "cmajor") && gOutputLang != "fir") { + !startWith(gOutputLang, "cmajor") && gOutputLang != "fir" && gOutputLang != "rust") { throw faustexception( - "ERROR : '-os' option can only be used with 'cpp', 'c', 'fir' or 'cmajor' " + "ERROR : '-os' option can only be used with 'cpp', 'c', 'dlang', 'cmajor', 'fir' or 'rust'" "backends\n"); } - if (gExtControl && gOutputLang != "cpp" && gOutputLang != "c" && gOutputLang != "cmajor") { + if (gExtControl && gOutputLang != "cpp" && gOutputLang != "c" && gOutputLang != "cmajor" && gOutputLang != "rust") { throw faustexception( - "ERROR : '-ec' option can only be used with 'cpp', 'c' or 'cmajor' " + "ERROR : '-ec' option can only be used with 'cpp', 'c', 'cmajor' or 'rust' " "backends\n"); } @@ -2114,6 +2120,10 @@ string global::printHelp() << "-uim --user-interface-macros add user interface macro definitions to the " "output code." << endl; + sstr << tab + << "-rnt --rust-no-faustdsp-trait (Rust only) Don't generate FaustDsp trait" + "implmentation." + << endl; sstr << tab << "-xml generate an XML description file." << endl; sstr << tab << "-json generate a JSON description file." diff --git a/compiler/global.hh b/compiler/global.hh index da4fa2cb4b..bc6e973b3a 100644 --- a/compiler/global.hh +++ b/compiler/global.hh @@ -138,6 +138,7 @@ struct global { bool gPrintFileListSwitch; // -flist option bool gInlineArchSwitch; // -i option bool gUIMacroSwitch; // -uim option + bool gRustNoTraitSwitch; // -rnt option int gDumpNorm; // -norm option bool gMathExceptions; // -me option, whether to check math functions domains bool gLocalCausalityCheck; // -lcc option, when true trigs local causality errors (negative diff --git a/tests/impulse-tests/Make.rust b/tests/impulse-tests/Make.rust index b88af02d2c..e7c18fdf57 100644 --- a/tests/impulse-tests/Make.rust +++ b/tests/impulse-tests/Make.rust @@ -15,114 +15,63 @@ MAKE ?= make outdir ?= rust FAUSTOPTIONS ?= -double +CARGOOPTIONS ?= --release precision ?= # filesCompare precision (empty by default) .PHONY: test .DELETE_ON_ERROR: -alldspfiles := $(wildcard dsp/*.dsp) -allirfiles = $(alldspfiles:dsp/%.dsp=ir/rust/%.ir) - -all: filesCompare - -# Currently this lists all dependencies manually to allow for easily enabling/disabling -# individual test cases. Later this can be replaced by the wildcard dependency: -# all: $(allirfiles) - -all: ir/rust/APF.ir -all: ir/rust/BPF.ir -all: ir/rust/HPF.ir -all: ir/rust/LPF.ir -all: ir/rust/UITester.ir -all: ir/rust/bandfilter.ir -all: ir/rust/bargraph.ir -all: ir/rust/bs.ir -all: ir/rust/capture.ir -all: ir/rust/carre_volterra.ir -all: ir/rust/comb_bug_exp.ir -all: ir/rust/comb_delay1.ir -all: ir/rust/comb_delay2.ir -all: ir/rust/constant.ir -all: ir/rust/cubic_distortion.ir -all: ir/rust/dbmeter.ir -all: ir/rust/delays.ir -all: ir/rust/echo_bug.ir -all: ir/rust/echo.ir -all: ir/rust/freeverb.ir -all: ir/rust/gate_compressor.ir -all: ir/rust/harpe.ir -all: ir/rust/highShelf.ir -all: ir/rust/karplus.ir -all: ir/rust/karplus32.ir -all: ir/rust/lfboost.ir -all: ir/rust/logical.ir -all: ir/rust/lowboost.ir -all: ir/rust/lowcut.ir -all: ir/rust/lowShelf.ir -all: ir/rust/math.ir -all: ir/rust/math_simp.ir -all: ir/rust/matrix.ir -all: ir/rust/midi_tester.ir -all: ir/rust/mixer.ir -all: ir/rust/modulations.ir -all: ir/rust/multibandfilter.ir -all: ir/rust/noise.ir -all: ir/rust/noiseabs.ir -all: ir/rust/noisemetadata.ir -all: ir/rust/notch.ir -all: ir/rust/osc_enable.ir -all: ir/rust/osc.ir -all: ir/rust/osci.ir -all: ir/rust/panpot.ir -all: ir/rust/parametric_eq.ir -all: ir/rust/peakingEQ.ir -all: ir/rust/peakNotch.ir -all: ir/rust/phaser_flanger.ir -all: ir/rust/pitch_shifter.ir -all: ir/rust/pow.ir -all: ir/rust/precision.ir -#all: ir/rust/prefix.ir -all: ir/rust/priority.ir -all: ir/rust/priority1.ir -all: ir/rust/quadecho.ir -all: ir/rust/reverb_designer.ir -all: ir/rust/reverb_tester.ir -all: ir/rust/smoothdelay.ir -#all: ir/rust/sound.ir -all: ir/rust/spat.ir -all: ir/rust/spectral_level.ir -all: ir/rust/spectral_tilt.ir -all: ir/rust/stereoecho.ir -all: ir/rust/switcher.ir -all: ir/rust/table.ir -all: ir/rust/table1.ir -all: ir/rust/table2.ir -all: ir/rust/tapiir.ir -all: ir/rust/tester.ir -all: ir/rust/tester2.ir -all: ir/rust/tf_exp.ir -all: ir/rust/thru_zero_flanger.ir -all: ir/rust/UITester.ir -all: ir/rust/vcf_wah_pedals.ir -all: ir/rust/virtual_analog_oscillators.ir -all: ir/rust/volume.ir -all: ir/rust/vumeter.ir -all: ir/rust/waveform1.ir -all: ir/rust/waveform2.ir -all: ir/rust/waveform3.ir -all: ir/rust/waveform4.ir -all: ir/rust/waveform5.ir -all: ir/rust/waveform6.ir -all: ir/rust/zita_rev1.ir - -filesCompare: +dspfiles := $(wildcard dsp/*.dsp) +listfiles = $(dspfiles:dsp/%.dsp=ir/$1/%.ir) + +######################################################################### +all: filesCompare ir/$(outdir) $(call listfiles,$(outdir)) + +######################################################################### +# output directories +ir/$(outdir): + mkdir -p ir/$(outdir) + + +######################################################################### +# tools +filesCompare: $(MAKE) filesCompare ######################################################################### # rules -ir/$(outdir)/%.ir: reference/%.ir - mkdir -p ir/$(outdir) - $(FAUST) -lang rust $(FAUSTOPTIONS) -i -A ../../architecture -a archs/rust/architecture.rs dsp/$*.dsp -o archs/rust/src/bin/$*.rs - #cd archs/rust/ && cargo run --bin $* ../../$@ - cd archs/rust/ && cargo run --release --bin $* ../../$@ - $(COMPARE) $@ reference/$(notdir $@) $(precision) + +ir/$(outdir)/sound.ir: dsp/sound.dsp + $(FAUST) -lang rust $(FAUSTOPTIONS) dsp/sound.dsp -o archs/rust/src/bin/sound.rs > $@ 2>&1 || (echo "expected failure") + grep "ERROR : 'soundfile' primitive not yet supported for Rust" $@ + +ir/rust/ec/bs.ir: dsp/bs.dsp + $(FAUST) -lang rust $(FAUSTOPTIONS) dsp/bs.dsp -o archs/rust/src/bin/bs.rs > $@ 2>&1 || (echo "expected failure") + grep "ERROR : accessing foreign variable 'count' is not allowed in this compilation mode" $@ + +ir/rust/osec/bs.ir: dsp/bs.dsp + $(FAUST) -lang rust $(FAUSTOPTIONS) dsp/bs.dsp -o archs/rust/src/bin/bs.rs > $@ 2>&1 || (echo "expected failure") + grep "ERROR : accessing foreign variable 'count' is not allowed in this compilation mode" $@ + +ir/rust/os/bs.ir: dsp/bs.dsp + $(FAUST) -lang rust $(FAUSTOPTIONS) dsp/bs.dsp -o archs/rust/src/bin/bs.rs > $@ 2>&1 || (echo "expected failure") + grep "ERROR : accessing foreign variable 'count' is not allowed in this compilation mode" $@ + +ir/rust/vec4/osc_enable.ir: dsp/osc_enable.dsp + $(FAUST) -lang rust $(FAUSTOPTIONS) dsp/osc_enable.dsp -o archs/rust/src/bin/osc_enable.rs > $@ 2>&1 || (echo "expected failure") + grep "ERROR : 'control/enable' can only be used in scalar mode" $@ + +ir/rust/vec32/osc_enable.ir: dsp/osc_enable.dsp + $(FAUST) -lang rust $(FAUSTOPTIONS) dsp/osc_enable.dsp -o archs/rust/src/bin/osc_enable.rs > $@ 2>&1 || (echo "expected failure") + grep "ERROR : 'control/enable' can only be used in scalar mode" $@ + +ir/rust/vec4/prefix.ir: + echo "todo fix bug #1071 to test dsp/prefix.dsp" + +ir/rust/vec32/prefix.ir: + echo "todo fix bug #1071 to test dsp/prefix.dsp" + +ir/$(outdir)/%.ir: dsp/%.dsp reference/%.ir + $(FAUST) -lang rust $(FAUSTOPTIONS) dsp/$*.dsp -o archs/rust/src/bin/$*.rs + cd archs/rust/ && cargo run $(CARGOOPTIONS) --bin $* ../../$@ + $(COMPARE) $@ reference/$(notdir $@) $(precision) || (rm -f $@; false) diff --git a/tests/impulse-tests/Makefile b/tests/impulse-tests/Makefile index afa0508fd3..f4139f0ffb 100644 --- a/tests/impulse-tests/Makefile +++ b/tests/impulse-tests/Makefile @@ -362,13 +362,13 @@ interp1: ######################################################################### # Rust backend rust: - $(MAKE) -f Make.rust FAUSTOPTIONS="-I dsp -double" - rm -rf ir/rust - $(MAKE) -f Make.rust FAUSTOPTIONS="-I dsp -double -fp" - rm -rf ir/rust - $(MAKE) -f Make.rust FAUSTOPTIONS="-I dsp -double -vec -vs 4" - rm -rf ir/rust - $(MAKE) -f Make.rust FAUSTOPTIONS="-I dsp -double -vec -vs 32" + $(MAKE) -f Make.rust outdir=rust/osec CARGOOPTIONS="" FAUSTOPTIONS="-I ../../libraries/ -double -os -ec -rnt -a archs/rust/architecture_os.rs" + $(MAKE) -f Make.rust outdir=rust/ec CARGOOPTIONS="" FAUSTOPTIONS="-I ../../libraries/ -double -cm -a archs/rust/architecture_cm.rs" + $(MAKE) -f Make.rust outdir=rust/ec CARGOOPTIONS="" FAUSTOPTIONS="-I ../../libraries/ -double -rnt -ec -a archs/rust/architecture.rs" + $(MAKE) -f Make.rust outdir=rust/no CARGOOPTIONS="" FAUSTOPTIONS="-I ../../libraries/ -double -a archs/rust/architecture_normal.rs" + $(MAKE) -f Make.rust outdir=rust/fp FAUSTOPTIONS="-I ../../libraries/ -double -fp -a archs/rust/architecture_normal.rs" + $(MAKE) -f Make.rust outdir=rust/vec4 CARGOOPTIONS="" FAUSTOPTIONS="-I ../../libraries/ -double -vec -vs 4 -a archs/rust/architecture_normal.rs" + $(MAKE) -f Make.rust outdir=rust/vec32 FAUSTOPTIONS="-I ../../libraries/ -double -vec -vs 32 -a archs/rust/architecture_normal.rs" ######################################################################### # Cmajor backend diff --git a/tests/impulse-tests/archs/rust/Cargo.toml b/tests/impulse-tests/archs/rust/Cargo.toml index ba2ebd9770..5747804e89 100644 --- a/tests/impulse-tests/archs/rust/Cargo.toml +++ b/tests/impulse-tests/archs/rust/Cargo.toml @@ -12,3 +12,5 @@ default-boxed = "0.2" [features] default = ["default-boxed"] default-boxed = [] + +[workspace] diff --git a/tests/impulse-tests/archs/rust/architecture.rs b/tests/impulse-tests/archs/rust/architecture.rs index 63d9a49db1..7bf451e323 100644 --- a/tests/impulse-tests/archs/rust/architecture.rs +++ b/tests/impulse-tests/archs/rust/architecture.rs @@ -23,17 +23,17 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. #![allow(unused_variables)] #![allow(unused_mut)] #![allow(non_upper_case_globals)] - -#![recursion_limit="256"] +#![recursion_limit = "256"] extern crate libm; extern crate num_traits; /* extern crate fastfloat; */ +use std::env; use std::fs::File; use std::io::Write; -use std::env; +use default_boxed::DefaultBoxed; use num_traits::{cast::FromPrimitive, float::Float}; type F32 = f32; @@ -48,32 +48,11 @@ type F64 = Fast; pub struct ParamIndex(i32); pub struct Soundfile<'a> { - fBuffers: &'a&'a F32, + fBuffers: &'a &'a F32, fLength: &'a i32, fSR: &'a i32, fOffset: &'a i32, - fChannels: i32 -} - -pub trait FaustDsp { - type T; - - fn new() -> Self where Self: Sized; - fn metadata(&self, m: &mut dyn Meta); - fn get_sample_rate(&self) -> i32; - fn get_num_inputs(&self) -> i32; - fn get_num_outputs(&self) -> i32; - fn class_init(sample_rate: i32) where Self: Sized; - fn instance_reset_params(&mut self); - fn instance_clear(&mut self); - fn instance_constants(&mut self, sample_rate: i32); - fn instance_init(&mut self, sample_rate: i32); - fn init(&mut self, sample_rate: i32); - fn build_user_interface(&self, ui_interface: &mut dyn UI); - fn build_user_interface_static(ui_interface: &mut dyn UI) where Self: Sized; - fn get_param(&self, param: ParamIndex) -> Option; - fn set_param(&mut self, param: ParamIndex, value: Self::T); - fn compute(&mut self, count: i32, inputs: &[&[Self::T]], outputs: &mut[&mut[Self::T]]); + fChannels: i32, } pub trait Meta { @@ -91,8 +70,24 @@ pub trait UI { // -- active widgets fn add_button(&mut self, label: &str, param: ParamIndex); fn add_check_button(&mut self, label: &str, param: ParamIndex); - fn add_vertical_slider(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T); - fn add_horizontal_slider(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T); + fn add_vertical_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ); + fn add_horizontal_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ); fn add_num_entry(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T); // -- passive widgets @@ -103,22 +98,19 @@ pub trait UI { fn declare(&mut self, param: Option, key: &str, value: &str); } -pub struct ButtonUI -{ - all_button_params: Vec +pub struct ButtonUI { + all_button_params: Vec, } -impl ButtonUI -{ - fn set_button_parameters_to(&self, dsp: &mut dyn FaustDsp, value: f64) { +impl ButtonUI { + fn set_button_parameters_to(&self, dsp: &mut Box, value: f64) { for button_param in &self.all_button_params { dsp.set_param(*button_param, value); } } } -impl UI for ButtonUI -{ +impl UI for ButtonUI { // -- widget's layouts fn open_tab_box(&mut self, label: &str) {} fn open_horizontal_box(&mut self, label: &str) {} @@ -126,13 +118,30 @@ impl UI for ButtonUI fn close_box(&mut self) {} // -- active widgets - fn add_button(&mut self, label: &str, param: ParamIndex) - { + fn add_button(&mut self, label: &str, param: ParamIndex) { self.all_button_params.push(param); } fn add_check_button(&mut self, label: &str, param: ParamIndex) {} - fn add_vertical_slider(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T) {} - fn add_horizontal_slider(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T) {} + fn add_vertical_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ) { + } + fn add_horizontal_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ) { + } fn add_num_entry(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T) {} // -- passive widgets @@ -151,44 +160,43 @@ impl UI for ButtonUI const SAMPLE_RATE: i32 = 44100; -type Dsp64 = dyn FaustDsp; - -fn print_header(mut dsp: Box, num_total_samples: usize, output_file: &mut File) { +fn print_header(mut dsp: Box, num_total_samples: usize, output_file: &mut File) { dsp.init(SAMPLE_RATE); - writeln!(output_file, "number_of_inputs : {}", dsp.get_num_inputs()).unwrap(); - writeln!(output_file, "number_of_outputs : {}", dsp.get_num_outputs()).unwrap(); + writeln!(output_file, "number_of_inputs : {}", FAUST_INPUTS).unwrap(); + writeln!(output_file, "number_of_outputs : {}", FAUST_OUTPUTS).unwrap(); writeln!(output_file, "number_of_frames : {}", num_total_samples).unwrap(); } -fn run_dsp(mut dsp: Box, num_samples: usize, line_num_offset: usize, output_file: &mut File) { - type T = ::T; - +fn run_dsp( + mut dsp: Box, + num_samples: usize, + line_num_offset: usize, + output_file: &mut File, +) { // Generation constants let buffer_size = 64usize; // Init dsp dsp.init(SAMPLE_RATE); - let num_inputs = dsp.get_num_inputs() as usize; - let num_outputs = dsp.get_num_outputs() as usize; - // Prepare buffers - let mut in_buffer = vec![vec![0 as T; buffer_size]; num_inputs]; - let mut out_buffer = vec![vec![0 as T; buffer_size]; num_outputs]; + let mut in_buffer = vec![vec![0 as FaustFloat; buffer_size]; FAUST_INPUTS]; + let mut out_buffer = vec![vec![0 as FaustFloat; buffer_size]; FAUST_OUTPUTS]; // Prepare UI - let mut ui = ButtonUI{ all_button_params: Vec::new() }; + let mut ui = ButtonUI { + all_button_params: Vec::new(), + }; dsp.build_user_interface(&mut ui); // Compute let mut cycle = 0; let mut num_samples_written = 0; while num_samples_written < num_samples { - let buffer_size = buffer_size.min(num_samples - num_samples_written); // handle inputs - for c in 0..num_inputs { + for c in 0..FAUST_INPUTS { for j in 0..buffer_size { let first_frame = num_samples_written == 0 && j == 0; in_buffer[c][j] = if first_frame { 1.0 } else { 0.0 }; @@ -197,21 +205,30 @@ fn run_dsp(mut dsp: Box, num_samples: usize, line_num_offset: usize, outp // Set button state if cycle == 0 { - ui.set_button_parameters_to(&mut *dsp, 1.0); + ui.set_button_parameters_to(&mut dsp, 1.0); } else { - ui.set_button_parameters_to(&mut *dsp, 0.0); + ui.set_button_parameters_to(&mut dsp, 0.0); } + dsp.control(); dsp.compute( - buffer_size as i32, - in_buffer.iter().map(|buffer| buffer.as_slice()).collect::>().as_slice(), - out_buffer.iter_mut().map(|buffer| buffer.as_mut_slice()).collect::>().as_mut_slice(), + buffer_size, + in_buffer + .iter() + .map(|buffer| buffer.as_slice()) + .collect::>() + .as_slice(), + out_buffer + .iter_mut() + .map(|buffer| buffer.as_mut_slice()) + .collect::>() + .as_mut_slice(), ); // handle outputs for j in 0..buffer_size { write!(output_file, "{:6} :", num_samples_written + line_num_offset).unwrap(); - for c in 0..num_outputs { + for c in 0..FAUST_OUTPUTS { write!(output_file, " {:8.6}", out_buffer[c][j]).unwrap(); } writeln!(output_file).unwrap(); @@ -222,26 +239,18 @@ fn run_dsp(mut dsp: Box, num_samples: usize, line_num_offset: usize, outp } } -fn new_dsp() -> Box { - use default_boxed::DefaultBoxed; - mydsp::default_boxed() -} - fn main() { let num_total_samples = 60000; let block_size = num_total_samples / 4; // Open output file - let output_file_name = env::args().nth(1).expect("ERROR: Output file name expected."); + let output_file_name = env::args() + .nth(1) + .expect("ERROR: Output file name expected."); let mut output_file = File::create(output_file_name).expect("Cannot create output file"); - print_header(new_dsp(), num_total_samples, &mut output_file); - - // Only test mono DSP for now - run_dsp(new_dsp(), block_size, 0, &mut output_file); + print_header(mydsp::default_boxed(), num_total_samples, &mut output_file); - //run_dsp(new_dsp(), block_size, 1 * block_size, &mut output_file); - //run_dsp(new_dsp(), block_size, 2 * block_size, &mut output_file); - //run_dsp(new_dsp(), block_size, 3 * block_size, &mut output_file); + run_dsp(mydsp::default_boxed(), block_size, 0, &mut output_file); } diff --git a/tests/impulse-tests/archs/rust/architecture_cm.rs b/tests/impulse-tests/archs/rust/architecture_cm.rs new file mode 100644 index 0000000000..72dc5f6f3d --- /dev/null +++ b/tests/impulse-tests/archs/rust/architecture_cm.rs @@ -0,0 +1,277 @@ +/************************************************************************ +************************************************************************ +FAUST Architecture File +Copyright (C) 2020 GRAME, Centre National de Creation Musicale +--------------------------------------------------------------------- + +This is sample code. This file is provided as an example of minimal +FAUST architecture file. Redistribution and use in source and binary +forms, with or without modification, in part or in full are permitted. +In particular you can create a derived work of this FAUST architecture +and distribute that work under terms of your choice. + +This sample code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +************************************************************************ +************************************************************************/ + +#![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)] +#![recursion_limit = "256"] + +extern crate libm; +extern crate num_traits; +/* extern crate fastfloat; */ + +use std::env; +use std::fs::File; +use std::io::Write; + +use default_boxed::DefaultBoxed; +use num_traits::{cast::FromPrimitive, float::Float}; + +type F32 = f32; +type F64 = f64; + +/* +type F32 = Fast; +type F64 = Fast; +*/ + +#[derive(Copy, Clone)] +pub struct ParamIndex(i32); + +pub struct Soundfile<'a> { + fBuffers: &'a &'a F32, + fLength: &'a i32, + fSR: &'a i32, + fOffset: &'a i32, + fChannels: i32, +} + +pub trait FaustDsp { + type T; + + fn new() -> Self + where + Self: Sized; + fn metadata(&self, m: &mut dyn Meta); + fn get_sample_rate(&self) -> i32; + fn get_num_inputs(&self) -> i32; + fn get_num_outputs(&self) -> i32; + fn class_init(sample_rate: i32) + where + Self: Sized; + fn instance_reset_params(&mut self); + fn instance_clear(&mut self); + fn instance_constants(&mut self, sample_rate: i32); + fn instance_init(&mut self, sample_rate: i32); + fn init(&mut self, sample_rate: i32); + fn build_user_interface(&self, ui_interface: &mut dyn UI); + fn build_user_interface_static(ui_interface: &mut dyn UI) + where + Self: Sized; + fn get_param(&self, param: ParamIndex) -> Option; + fn set_param(&mut self, param: ParamIndex, value: Self::T); + fn compute(&mut self, count: i32, inputs: &[&[Self::T]], outputs: &mut [&mut [Self::T]]); +} + +pub trait Meta { + // -- metadata declarations + fn declare(&mut self, key: &str, value: &str); +} + +pub trait UI { + // -- widget's layouts + fn open_tab_box(&mut self, label: &str); + fn open_horizontal_box(&mut self, label: &str); + fn open_vertical_box(&mut self, label: &str); + fn close_box(&mut self); + + // -- active widgets + fn add_button(&mut self, label: &str, param: ParamIndex); + fn add_check_button(&mut self, label: &str, param: ParamIndex); + fn add_vertical_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ); + fn add_horizontal_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ); + fn add_num_entry(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T); + + // -- passive widgets + fn add_horizontal_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T); + fn add_vertical_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T); + + // -- metadata declarations + fn declare(&mut self, param: Option, key: &str, value: &str); +} + +pub struct ButtonUI { + all_button_params: Vec, +} + +impl ButtonUI { + fn set_button_parameters_to(&self, dsp: &mut Box, value: f64) { + for button_param in &self.all_button_params { + dsp.set_param(*button_param, value); + } + } +} + +impl UI for ButtonUI { + // -- widget's layouts + fn open_tab_box(&mut self, label: &str) {} + fn open_horizontal_box(&mut self, label: &str) {} + fn open_vertical_box(&mut self, label: &str) {} + fn close_box(&mut self) {} + + // -- active widgets + fn add_button(&mut self, label: &str, param: ParamIndex) { + self.all_button_params.push(param); + } + fn add_check_button(&mut self, label: &str, param: ParamIndex) {} + fn add_vertical_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ) { + } + fn add_horizontal_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ) { + } + fn add_num_entry(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T) {} + + // -- passive widgets + fn add_horizontal_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T) {} + fn add_vertical_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T) {} + + // -- metadata declarations + fn declare(&mut self, param: Option, key: &str, value: &str) {} +} + +const SAMPLE_RATE: i32 = 44100; + +fn print_header(mut dsp: Box, num_total_samples: usize, output_file: &mut File) { + dsp.init(SAMPLE_RATE); + writeln!(output_file, "number_of_inputs : {}", FAUST_INPUTS).unwrap(); + writeln!(output_file, "number_of_outputs : {}", FAUST_OUTPUTS).unwrap(); + writeln!(output_file, "number_of_frames : {}", num_total_samples).unwrap(); +} + +fn run_dsp( + mut dsp: Box, + num_samples: usize, + line_num_offset: usize, + output_file: &mut File, +) { + // Generation constants + let buffer_size = 64usize; + + // Init dsp + dsp.init(SAMPLE_RATE); + + // Prepare buffers + let mut in_buffer = vec![vec![0 as FaustFloat; buffer_size]; FAUST_INPUTS]; + let mut out_buffer = vec![vec![0 as FaustFloat; buffer_size]; FAUST_OUTPUTS]; + + // Prepare UI + let mut ui = ButtonUI { + all_button_params: Vec::new(), + }; + dsp.build_user_interface(&mut ui); + + // Compute + let mut cycle = 0; + let mut num_samples_written = 0; + while num_samples_written < num_samples { + let buffer_size = buffer_size.min(num_samples - num_samples_written); + + // handle inputs + for c in 0..FAUST_INPUTS { + for j in 0..buffer_size { + let first_frame = num_samples_written == 0 && j == 0; + in_buffer[c][j] = if first_frame { 1.0 } else { 0.0 }; + } + } + + // Set button state + if cycle == 0 { + ui.set_button_parameters_to(&mut dsp, 1.0); + } else { + ui.set_button_parameters_to(&mut dsp, 0.0); + } + + // right now the cm flag is only tested for the case that is the buffer is zeroed every time + let i = in_buffer + .iter() + .map(|buffer| buffer.as_slice()) + .collect::>(); + let mut o = out_buffer + .iter_mut() + .map(|buffer| { + buffer.iter_mut().for_each(|i| *i = 0.0); + buffer.as_mut_slice() + }) + .collect::>(); + + dsp.compute(buffer_size, i.as_slice(), o.as_mut_slice()); + + // handle outputs + for j in 0..buffer_size { + write!(output_file, "{:6} :", num_samples_written + line_num_offset).unwrap(); + for c in 0..FAUST_OUTPUTS { + write!(output_file, " {:8.6}", out_buffer[c][j]).unwrap(); + } + writeln!(output_file).unwrap(); + num_samples_written += 1; + } + + cycle = cycle + 1; + } +} + +fn main() { + let num_total_samples = 60000; + + let block_size = num_total_samples / 4; + + // Open output file + let output_file_name = env::args() + .nth(1) + .expect("ERROR: Output file name expected."); + let mut output_file = File::create(output_file_name).expect("Cannot create output file"); + + print_header(mydsp::default_boxed(), num_total_samples, &mut output_file); + + run_dsp(mydsp::default_boxed(), block_size, 0, &mut output_file); +} diff --git a/tests/impulse-tests/archs/rust/architecture_normal.rs b/tests/impulse-tests/archs/rust/architecture_normal.rs new file mode 100644 index 0000000000..c454dd6e1b --- /dev/null +++ b/tests/impulse-tests/archs/rust/architecture_normal.rs @@ -0,0 +1,298 @@ +/************************************************************************ +************************************************************************ +FAUST Architecture File +Copyright (C) 2020 GRAME, Centre National de Creation Musicale +--------------------------------------------------------------------- + +This is sample code. This file is provided as an example of minimal +FAUST architecture file. Redistribution and use in source and binary +forms, with or without modification, in part or in full are permitted. +In particular you can create a derived work of this FAUST architecture +and distribute that work under terms of your choice. + +This sample code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +************************************************************************ +************************************************************************/ + +#![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)] +#![recursion_limit = "256"] + +extern crate libm; +extern crate num_traits; +/* extern crate fastfloat; */ + +use std::env; +use std::fs::File; +use std::io::Write; + +use num_traits::{cast::FromPrimitive, float::Float}; + +type F32 = f32; +type F64 = f64; + +/* +type F32 = Fast; +type F64 = Fast; +*/ + +#[derive(Copy, Clone)] +pub struct ParamIndex(i32); + +pub struct Soundfile<'a> { + fBuffers: &'a &'a F32, + fLength: &'a i32, + fSR: &'a i32, + fOffset: &'a i32, + fChannels: i32, +} + +pub trait FaustDsp { + type T; + + fn new() -> Self + where + Self: Sized; + fn metadata(&self, m: &mut dyn Meta); + fn get_sample_rate(&self) -> i32; + fn get_num_inputs(&self) -> i32; + fn get_num_outputs(&self) -> i32; + fn class_init(sample_rate: i32) + where + Self: Sized; + fn instance_reset_params(&mut self); + fn instance_clear(&mut self); + fn instance_constants(&mut self, sample_rate: i32); + fn instance_init(&mut self, sample_rate: i32); + fn init(&mut self, sample_rate: i32); + fn build_user_interface(&self, ui_interface: &mut dyn UI); + fn build_user_interface_static(ui_interface: &mut dyn UI) + where + Self: Sized; + fn get_param(&self, param: ParamIndex) -> Option; + fn set_param(&mut self, param: ParamIndex, value: Self::T); + fn compute(&mut self, count: i32, inputs: &[&[Self::T]], outputs: &mut [&mut [Self::T]]); +} + +pub trait Meta { + // -- metadata declarations + fn declare(&mut self, key: &str, value: &str); +} + +pub trait UI { + // -- widget's layouts + fn open_tab_box(&mut self, label: &str); + fn open_horizontal_box(&mut self, label: &str); + fn open_vertical_box(&mut self, label: &str); + fn close_box(&mut self); + + // -- active widgets + fn add_button(&mut self, label: &str, param: ParamIndex); + fn add_check_button(&mut self, label: &str, param: ParamIndex); + fn add_vertical_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ); + fn add_horizontal_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ); + fn add_num_entry(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T); + + // -- passive widgets + fn add_horizontal_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T); + fn add_vertical_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T); + + // -- metadata declarations + fn declare(&mut self, param: Option, key: &str, value: &str); +} + +pub struct ButtonUI { + all_button_params: Vec, +} + +impl ButtonUI { + fn set_button_parameters_to(&self, dsp: &mut dyn FaustDsp, value: f64) { + for button_param in &self.all_button_params { + dsp.set_param(*button_param, value); + } + } +} + +impl UI for ButtonUI { + // -- widget's layouts + fn open_tab_box(&mut self, label: &str) {} + fn open_horizontal_box(&mut self, label: &str) {} + fn open_vertical_box(&mut self, label: &str) {} + fn close_box(&mut self) {} + + // -- active widgets + fn add_button(&mut self, label: &str, param: ParamIndex) { + self.all_button_params.push(param); + } + fn add_check_button(&mut self, label: &str, param: ParamIndex) {} + fn add_vertical_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ) { + } + fn add_horizontal_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ) { + } + fn add_num_entry(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T) {} + + // -- passive widgets + fn add_horizontal_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T) {} + fn add_vertical_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T) {} + + // -- metadata declarations + fn declare(&mut self, param: Option, key: &str, value: &str) {} +} + +// Generated intrinsics: +<> + +// Generated class: +<> + +const SAMPLE_RATE: i32 = 44100; + +type Dsp64 = dyn FaustDsp; + +fn print_header(mut dsp: Box, num_total_samples: usize, output_file: &mut File) { + dsp.init(SAMPLE_RATE); + writeln!(output_file, "number_of_inputs : {}", dsp.get_num_inputs()).unwrap(); + writeln!(output_file, "number_of_outputs : {}", dsp.get_num_outputs()).unwrap(); + writeln!(output_file, "number_of_frames : {}", num_total_samples).unwrap(); +} + +fn run_dsp( + mut dsp: Box, + num_samples: usize, + line_num_offset: usize, + output_file: &mut File, +) { + type T = ::T; + + // Generation constants + let buffer_size = 64usize; + + // Init dsp + dsp.init(SAMPLE_RATE); + + let num_inputs = dsp.get_num_inputs() as usize; + let num_outputs = dsp.get_num_outputs() as usize; + + // Prepare buffers + let mut in_buffer = vec![vec![0 as T; buffer_size]; num_inputs]; + let mut out_buffer = vec![vec![0 as T; buffer_size]; num_outputs]; + + // Prepare UI + let mut ui = ButtonUI { + all_button_params: Vec::new(), + }; + dsp.build_user_interface(&mut ui); + + // Compute + let mut cycle = 0; + let mut num_samples_written = 0; + while num_samples_written < num_samples { + let buffer_size = buffer_size.min(num_samples - num_samples_written); + + // handle inputs + for c in 0..num_inputs { + for j in 0..buffer_size { + let first_frame = num_samples_written == 0 && j == 0; + in_buffer[c][j] = if first_frame { 1.0 } else { 0.0 }; + } + } + + // Set button state + if cycle == 0 { + ui.set_button_parameters_to(&mut *dsp, 1.0); + } else { + ui.set_button_parameters_to(&mut *dsp, 0.0); + } + + dsp.compute( + buffer_size as i32, + in_buffer + .iter() + .map(|buffer| buffer.as_slice()) + .collect::>() + .as_slice(), + out_buffer + .iter_mut() + .map(|buffer| buffer.as_mut_slice()) + .collect::>() + .as_mut_slice(), + ); + + // handle outputs + for j in 0..buffer_size { + write!(output_file, "{:6} :", num_samples_written + line_num_offset).unwrap(); + for c in 0..num_outputs { + write!(output_file, " {:8.6}", out_buffer[c][j]).unwrap(); + } + writeln!(output_file).unwrap(); + num_samples_written += 1; + } + + cycle = cycle + 1; + } +} + +fn new_dsp() -> Box { + use default_boxed::DefaultBoxed; + mydsp::default_boxed() +} + +fn main() { + let num_total_samples = 60000; + + let block_size = num_total_samples / 4; + + // Open output file + let output_file_name = env::args() + .nth(1) + .expect("ERROR: Output file name expected."); + let mut output_file = File::create(output_file_name).expect("Cannot create output file"); + + print_header(new_dsp(), num_total_samples, &mut output_file); + + // Only test mono DSP for now + run_dsp(new_dsp(), block_size, 0, &mut output_file); + + //run_dsp(new_dsp(), block_size, 1 * block_size, &mut output_file); + //run_dsp(new_dsp(), block_size, 2 * block_size, &mut output_file); + //run_dsp(new_dsp(), block_size, 3 * block_size, &mut output_file); +} diff --git a/tests/impulse-tests/archs/rust/architecture_os.rs b/tests/impulse-tests/archs/rust/architecture_os.rs new file mode 100644 index 0000000000..4f3531e266 --- /dev/null +++ b/tests/impulse-tests/archs/rust/architecture_os.rs @@ -0,0 +1,262 @@ +/************************************************************************ +************************************************************************ +FAUST Architecture File +Copyright (C) 2020 GRAME, Centre National de Creation Musicale +--------------------------------------------------------------------- + +This is sample code. This file is provided as an example of minimal +FAUST architecture file. Redistribution and use in source and binary +forms, with or without modification, in part or in full are permitted. +In particular you can create a derived work of this FAUST architecture +and distribute that work under terms of your choice. + +This sample code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +************************************************************************ +************************************************************************/ + +#![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)] +#![recursion_limit = "256"] + +extern crate libm; +extern crate num_traits; +/* extern crate fastfloat; */ + +use std::env; +use std::fs::File; +use std::io::Write; + +use default_boxed::DefaultBoxed; +use num_traits::{cast::FromPrimitive, float::Float}; + +type F32 = f32; +type F64 = f64; + +/* +type F32 = Fast; +type F64 = Fast; +*/ + +#[derive(Copy, Clone)] +pub struct ParamIndex(i32); + +pub struct Soundfile<'a> { + fBuffers: &'a &'a F32, + fLength: &'a i32, + fSR: &'a i32, + fOffset: &'a i32, + fChannels: i32, +} + +pub trait Meta { + // -- metadata declarations + fn declare(&mut self, key: &str, value: &str); +} + +pub trait UI { + // -- widget's layouts + fn open_tab_box(&mut self, label: &str); + fn open_horizontal_box(&mut self, label: &str); + fn open_vertical_box(&mut self, label: &str); + fn close_box(&mut self); + + // -- active widgets + fn add_button(&mut self, label: &str, param: ParamIndex); + fn add_check_button(&mut self, label: &str, param: ParamIndex); + fn add_vertical_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ); + fn add_horizontal_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ); + fn add_num_entry(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T); + + // -- passive widgets + fn add_horizontal_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T); + fn add_vertical_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T); + + // -- metadata declarations + fn declare(&mut self, param: Option, key: &str, value: &str); +} + +pub struct ButtonUI { + all_button_params: Vec, +} + +impl ButtonUI { + fn set_button_parameters_to(&self, dsp: &mut Box, value: f64) { + for button_param in &self.all_button_params { + dsp.set_param(*button_param, value); + } + } +} + +impl UI for ButtonUI { + // -- widget's layouts + fn open_tab_box(&mut self, label: &str) {} + fn open_horizontal_box(&mut self, label: &str) {} + fn open_vertical_box(&mut self, label: &str) {} + fn close_box(&mut self) {} + + // -- active widgets + fn add_button(&mut self, label: &str, param: ParamIndex) { + self.all_button_params.push(param); + } + fn add_check_button(&mut self, label: &str, param: ParamIndex) {} + fn add_vertical_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ) { + } + fn add_horizontal_slider( + &mut self, + label: &str, + param: ParamIndex, + init: T, + min: T, + max: T, + step: T, + ) { + } + fn add_num_entry(&mut self, label: &str, param: ParamIndex, init: T, min: T, max: T, step: T) {} + + // -- passive widgets + fn add_horizontal_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T) {} + fn add_vertical_bargraph(&mut self, label: &str, param: ParamIndex, min: T, max: T) {} + + // -- metadata declarations + fn declare(&mut self, param: Option, key: &str, value: &str) {} +} + +// Generated intrinsics: +//<> + +// Generated class: +//<> + +const SAMPLE_RATE: i32 = 44100; + +fn print_header(mut dsp: Box, num_total_samples: usize, output_file: &mut File) { + dsp.init(SAMPLE_RATE); + writeln!(output_file, "number_of_inputs : {}", FAUST_INPUTS).unwrap(); + writeln!(output_file, "number_of_outputs : {}", FAUST_OUTPUTS).unwrap(); + writeln!(output_file, "number_of_frames : {}", num_total_samples).unwrap(); +} + +fn run_dsp( + mut dsp: Box, + num_samples: usize, + line_num_offset: usize, + output_file: &mut File, +) { + // Generation constants + let buffer_size = 64usize; + + // Init dsp + dsp.init(SAMPLE_RATE); + + // Prepare buffers + let mut in_buffer = vec![vec![0 as FaustFloat; buffer_size]; FAUST_INPUTS]; + let mut out_buffer = vec![vec![0 as FaustFloat; buffer_size]; FAUST_OUTPUTS]; + + // Prepare UI + let mut ui = ButtonUI { + all_button_params: Vec::new(), + }; + dsp.build_user_interface(&mut ui); + + // Compute + let mut cycle = 0; + let mut num_samples_written = 0; + while num_samples_written < num_samples { + let buffer_size = buffer_size.min(num_samples - num_samples_written); + + // handle inputs + for c in 0..FAUST_INPUTS { + for j in 0..buffer_size { + let first_frame = num_samples_written == 0 && j == 0; + in_buffer[c][j] = if first_frame { 1.0 } else { 0.0 }; + } + } + + // Set button state + if cycle == 0 { + ui.set_button_parameters_to(&mut dsp, 1.0); + } else { + ui.set_button_parameters_to(&mut dsp, 0.0); + } + + dsp.control(); + for i in 0..buffer_size { + dsp.compute_frame( + in_buffer + .iter() + .map(|buffer| &buffer[i]) + .collect::>() + .split_at(FAUST_INPUTS) + .0 + .try_into() + .expect("too few input buffers"), + out_buffer + .iter_mut() + .map(|buffer| &mut buffer[i]) + .collect::>() + .split_at_mut(FAUST_OUTPUTS) + .0 + .try_into() + .expect("too few output buffers"), + ); + } + // handle outputs + for j in 0..buffer_size { + write!(output_file, "{:6} :", num_samples_written + line_num_offset).unwrap(); + for c in 0..FAUST_OUTPUTS { + write!(output_file, " {:8.6}", out_buffer[c][j]).unwrap(); + } + writeln!(output_file).unwrap(); + num_samples_written += 1; + } + + cycle = cycle + 1; + } +} + +fn main() { + let num_total_samples = 60000; + + let block_size = num_total_samples / 4; + + // Open output file + let output_file_name = env::args() + .nth(1) + .expect("ERROR: Output file name expected."); + let mut output_file = File::create(output_file_name).expect("Cannot create output file"); + + print_header(mydsp::default_boxed(), num_total_samples, &mut output_file); + + run_dsp(mydsp::default_boxed(), block_size, 0, &mut output_file); +}