extendr: Compilation error when running from R
Hi! I am trying to reproduce audio using the cpal
crate from R. I added the play
function and suddenly I am getting compiler errors when running from R. When I run cargo test play_test
it works well. Do you know what’s going on here?
Error:
─ DONE (audior)
Error in dyn.load(library_path) :
unable to load shared object '/mnt/wd/projects/audior/src/audior.so':
/mnt/wd/projects/audior/src/audior.so: undefined symbol: snd_pcm_hw_params_get_period_size_min
Error in `value[[3L]]()`:
! Failed to generate wrapper functions.
✖ error in callr subprocess
lib.rs:
mod play_audio;
/// @export
#[extendr]
pub fn play(r_arr: RMatrix<f64>, sr: i32) {
let arr: ArrayView2<f64> = ArrayView2::from_robj(&r_arr).expect("cannot convert Robj to ArrayView2");
play_audio::play(&arr, sr as u32)
}
extendr_module! {
mod audior;
fn load;
//fn stream;
fn to_mono;
fn get_duration;
fn get_samplerate;
fn resample;
fn fft;
fn realfft;
fn get_window;
fn play;
}
play_audio.rs:
use ndarray::ArrayView2;
use cpal::{Sample, SampleFormat, SupportedStreamConfig, SampleRate, BufferSize, StreamConfig};
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
pub fn play(arr: &ArrayView2<f64>, sr: u32) {
let channels = arr.nrows();
let samples = arr.ncols();
// convert to interleaved
let mut data_interleaved = Vec::with_capacity(channels * samples);
for i in 0..samples {
for ch in 0..channels {
data_interleaved.push(arr[[ch, i]] as f32);
}
}
let host = cpal::default_host();
let device = host.default_output_device().expect("no output device available");
let config = StreamConfig {
channels: channels as u16,
sample_rate: SampleRate(sr), // Audio device default sample rate is set to 192000
buffer_size: BufferSize::Default,
};
let err_fn = |err| eprintln!("an error occurred on the output audio stream: {}", err);
let mut data_interleaved_iter = data_interleaved.into_iter();
let mut next_value = move || {
data_interleaved_iter.next().expect("cannot get next iter value")
};
let stream = device.build_output_stream(
&config,
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
write_data(data, channels, &mut next_value)
},
err_fn
).unwrap();
fn write_data<T: Sample>(output: &mut [T], channels: usize, next_sample: &mut dyn FnMut() -> f32) {
for frame in output.chunks_mut(channels) {
for sample in frame.iter_mut() {
let value: T = Sample::from(&next_sample());
*sample = value
}
}
}
stream.play().unwrap();
std::thread::sleep(std::time::Duration::from_millis(5000));
}
#[cfg(test)]
mod test_play {
use extendr_api::NA_REAL;
use crate::decode_symphonia;
use super::*;
use std::path::Path;
#[test]
fn test_play() {
let fname = "../../test_files/mono.wav";
let path = Path::new(fname);
let filetype = Path::extension(path)
.expect("couldn't extract the file extension")
.to_str()
.expect("cannot convert from &OsStr to &str");
let decoded_arr = decode_symphonia::load(path, false, 0., NA_REAL, filetype);
let sr = decode_symphonia::get_samplerate(path, filetype);
play(&decoded_arr.view(), sr);
}
}
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 19 (14 by maintainers)
Same, I jumped off my chair because it went over the audio of a film I was watching. Now trying to run it directly from R.
copying the full test straight into a function and export that to R does work
I’m just speculating, but if this problem happens at runtime, you may need to make sure that
/mnt/wd/projects/audior/src/
is inLD_LIBRARY_PATH