Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audio file sampler implementation #64

Merged
merged 21 commits into from
Oct 10, 2024
Merged

Audio file sampler implementation #64

merged 21 commits into from
Oct 10, 2024

Conversation

tomoyanonymous
Copy link
Owner

@tomoyanonymous tomoyanonymous commented Sep 27, 2024

This PR adds audio file sample using symphonia crate.

This PR also introduces ExecContext, a pair of the compiler and VM, to manage type information of external functions.
ExecContext is needed for decoupling external functions which depend on a external crates.

The PR contains an implementation of array access parser but I'm going to change the way of loading & reading wav files into that uses higher-order external function.

//loadwav returns higher-order function that takes playback position in samples as an argument
let sampler = gen_sampler_mono("test.wav")
fn counter(){
    self+1
}
fn dsp(){
    counter() |> sampler
}
  • only mono files are supported(other format causes panic on runtime)
  • index for sampler is a raw position of samples(Now, samplerate mismatch between audio driver and audio file are not handled. Resampler is not implemented as a part of symphonia, but there's an example code of resampler in symphonia-play application, it can be derived.
  • index are not needed to be integer, a boundary check and linear interpolation are performed on read.(Aceess out of range returns 0.0 .)
  • gen_sampler_mono function internally creates external Rust closure that holds Vec as internal data(The allocated external closure will never be released in the current implementation. )

Todo:

  • add api for wrapping an external closure with mimium closure
  • String literal type support
  • Relative path resolution from each mmm files
  • add test for file reader

@tomoyanonymous tomoyanonymous marked this pull request as ready for review October 8, 2024 09:11
@tomoyanonymous
Copy link
Owner Author

I think it's finally ready to merge.

A new api in the VM, wrap_extern_closure is introduced to call higher-order native closure.

    let res = move |machine: &mut Machine| -> ReturnCode {
        let pos = vm::Machine::get_as::<f64>(machine.get_stack(0));
        // this sampler read with boundary checks.
        let val = interpolate_vec(&vec, pos);
        machine.set_stack(0, Machine::to_value(val));
        1
    };
    let ty = function!(vec![numeric!()], numeric!());
    let idx = machine.wrap_extern_cls(("loadwavfile_impl", Arc::new(res), ty));
    machine.set_stack(0, Machine::to_value(idx));
    1
}

wrap_extern_closure internally modifies VM program on the fly (generate a glue code which calls Rust closure), so now program is now a member of VM struct. This change made initialization step of VM complicated, I will refactor it later in some way.

Other next todos:

  • Move common test modules into an independent crate so that each external crates can use it and test can be defined within each modules(now the test for mimium-symphonia uses duplicated codes.)
  • Relation between ExecContext and Driver & RuntimeData in mimium-audiodriver are total mess, should be restructured

@tomoyanonymous tomoyanonymous added this to the v2.0.0 milestone Oct 10, 2024
@tomoyanonymous tomoyanonymous linked an issue Oct 10, 2024 that may be closed by this pull request
@tomoyanonymous tomoyanonymous merged commit a561dec into dev Oct 10, 2024
6 checks passed
@tomoyanonymous tomoyanonymous deleted the feat-symphonia branch October 10, 2024 07:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add audio file reader function
1 participant