Skip to content

Commit

Permalink
Add -double support for faust2jackrust and faust2portaudiorust.
Browse files Browse the repository at this point in the history
  • Loading branch information
sletz committed Feb 17, 2024
1 parent 4c44a63 commit 9f2eb57
Show file tree
Hide file tree
Showing 6 changed files with 421 additions and 8 deletions.
192 changes: 192 additions & 0 deletions architecture/jack-double.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/************************************************************************
FAUST Architecture File
Copyright (C) 2003-2024 GRAME, Centre National de Creation Musicale
---------------------------------------------------------------------
This Architecture section is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3 of
the License, or (at your option) any later version.
This program 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; If not, see <http://www.gnu.org/licenses/>.
EXCEPTION : As a special exception, you may create a larger work
that contains this FAUST architecture section and distribute
that work under terms of your choice, so long as this FAUST
architecture section is not modified.
************************************************************************
************************************************************************/

#![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)]

//! Faust JACK architecture file
extern crate jack;
use jack::prelude as j;
use std::io;
extern crate libm;

type F32 = f32;
type F64 = f64;

#[derive(Copy, Clone)]
pub struct ParamIndex(pub i32);

pub struct Soundfile<'a,T> {
fBuffers: &'a&'a T,
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<Self::T>);
fn build_user_interface_static(ui_interface: &mut dyn UI<Self::T>) where Self: Sized;
fn get_param(&self, param: ParamIndex) -> Option<Self::T>;
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<T> {
// -- 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<ParamIndex>, key: &str, value: &str);
}

<<includeIntrinsic>>
<<includeclass>>

fn main() {

// Create JACK client
let (client, _status) = j::Client::new("faust_rust", j::client_options::NO_START_SERVER).unwrap();

// Allocation DSP on the heap
let mut dsp;
#[cfg(feature = "default-boxed")]
{
use default_boxed::DefaultBoxed;
dsp = mydsp::default_boxed();
}

#[cfg(not(feature = "default-boxed"))]
{
dsp = Box::new(mydsp::new());
}

println!("Faust Rust code running with JACK: sample-rate = {} buffer-size = {}", client.sample_rate(), client.buffer_size());

println!("get_num_inputs: {}", dsp.get_num_inputs());
println!("get_num_outputs: {}", dsp.get_num_outputs());

// Init DSP with a given SR
dsp.init(client.sample_rate() as i32);

// Register ports. They will be used in a callback that will be
// called when new data is available.

let in_a = client.register_port("in1", j::AudioInSpec::default()).unwrap();
let in_b = client.register_port("in2", j::AudioInSpec::default()).unwrap();

let mut out_a = client.register_port("out1", j::AudioOutSpec::default()).unwrap();
let mut out_b = client.register_port("out2", j::AudioOutSpec::default()).unwrap();

let process_callback = move |_: &j::Client, ps: &j::ProcessScope| -> j::JackControl {
let mut out_a_p = j::AudioOutPort::new(&mut out_a, ps);
let mut out_b_p = j::AudioOutPort::new(&mut out_b, ps);

let in_a_p = j::AudioInPort::new(&in_a, ps);
let in_b_p = j::AudioInPort::new(&in_b, ps);

// Adapt f32 inputs in f64 inputs
let input0: &[f32] = &in_a_p;
let input1: &[f32] = &in_b_p;

let input0_f64: Vec<f64> = input0.iter().map(|&sample| sample as f64).collect();
let input1_f64: Vec<f64> = input1.iter().map(|&sample| sample as f64).collect();

let inputs_f64: [&[f64]; 2] = [&input0_f64[..], &input1_f64[..]];
let inputs_ref: &[&[f64]] = &inputs_f64;

// Prepare f64 outputs
let mut output0_f64: Vec<f64> = vec![0.0; out_a_p.len()];
let mut output1_f64: Vec<f64> = vec![0.0; out_b_p.len()];

let mut outputs_f64: [&mut [f64]; 2] = [&mut output0_f64[..], &mut output1_f64[..]];
let outputs_ref: &mut [&mut [f64]] = &mut outputs_f64;

// Compute using f64 inputs and outputs
dsp.compute(in_a_p.len() as i32, inputs_ref, outputs_ref);

// Convert f64 outputs to f32 outputs
let output0: &mut[f32] = &mut out_a_p;
let output1: &mut[f32] = &mut out_b_p;

// Copy and convert outputs_ref[0] (f64) to output0 (f32)
for (dest, &src) in output0.iter_mut().zip(outputs_ref[0].iter()) {
*dest = src as f32;
}
for (dest, &src) in output1.iter_mut().zip(outputs_ref[1].iter()) {
*dest = src as f32;
}

j::JackControl::Continue
};
let process = j::ClosureProcessHandler::new(process_callback);

// Activate the client, which starts the processing.
let active_client = j::AsyncClient::new(client, (), process).unwrap();

// Wait for user input to quit
println!("Press enter/return to quit...");
let mut user_input = String::new();
io::stdin().read_line(&mut user_input).ok();

active_client.deactivate().unwrap();
}
2 changes: 1 addition & 1 deletion architecture/jack.rs → architecture/jack-float.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/************************************************************************
FAUST Architecture File
Copyright (C) 2003-2019 GRAME, Centre National de Creation Musicale
Copyright (C) 2003-2024 GRAME, Centre National de Creation Musicale
---------------------------------------------------------------------
This Architecture section is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
Expand Down
Loading

0 comments on commit 9f2eb57

Please sign in to comment.