diwic / alsa-rs Goto Github PK
View Code? Open in Web Editor NEWThin but safe ALSA wrappers for Rust
License: Apache License 2.0
Thin but safe ALSA wrappers for Rust
License: Apache License 2.0
alsa::pcm::PCM::open (pcm.rs:135) due to (as far as i can tell) the variable 'r' being 0x0
I'm not sure how to proceed, the program i've been using to narrow it down was this from the synth-example
fn main() {
let args: Vec<_> = std::env::args().collect();
let req_devname = format!("hw:{}", args[1]);
let p = alsa::PCM::new(&req_devname, alsa::Direction::Playback, false);
}
Might it be an issue from alpine using musl?
For example, the following is safe today, but shouldn't be:
let ev = ... // some event that is not a `Connect` event
let connect = <Connect as EventData>::get_data(&ev)
Hi! I was trying to generically create an instance of the IO
struct from an instance of PCM
, depending on which format is being used. This is currently not easily possible, as something like
let io = pcm.io::<u32>()?;
is not possible. The reason is, of course, that the different PCM::io_*
methods perform checks based on instances of the Format
enum here.
So I ended up implementing a trait like this:
use alsa::pcm::{IO, PCM};
trait IoFromPcm: Copy {
fn io_from_pcm<'a>(pcm: &'a PCM) -> alsa::Result<IO<Self>>;
}
impl IoFromPcm for u8 {
fn io_from_pcm<'a>(pcm: &'a PCM) -> alsa::Result<IO<Self>> {
pcm.io_u8()
}
}
impl IoFromPcm for i8 {
fn io_from_pcm<'a>(pcm: &'a PCM) -> alsa::Result<IO<Self>> {
pcm.io_i8()
}
}
// and so on for u16, i16, u32, i32, f32, and f64
and then doing something like this in my application code:
fn play_something<T: IoFromPcm>(&self, buf: &[T]) -> alsa::Result<()> {
let io = T::io_from_pcm(&self.pcm)?;
io.writei(&buf)?;
// ...
}
(The above is greatly abridged, not sure if that would really compile, but I think you get the idea).
Maybe it would be cool to add a similar mechanism to the library, to make it easier to dynamically choose a format for the IO instance?
When trying to work with external hardware, I have noticed a possible bug in the Seq implementation that caused some me some trouble. Basically what happens is that after sending a piece of SysEx data every CC message becomes malformed, with their status byte zeroed out.
The issue seems to "fix" itself after sending a note event, which is what I currently use as a work around, ending every SysEx message with a note sent to an unused channel.
An easy way to reproduce this is to run the following piece of code and connect it to a raw MIDI endpoint, such as amidi
: https://gist.github.com/kelytha/24dfda03ab7eca203d34119a462e429c
The output looks like this on my end:
$ amidi -p virtual -d
90 08 7F // Note on
08 00 // Note off
B0 08 7F // CC up
08 00 // CC down
F0 00 21 09 15 00 4D 50 00 01 4D 01 F7 // SysEx
F0 00 21 09 15 00 4D 50 00 01 4D 00 F7 // SysEx
08 // ...
7F // ... garbled CC
08 // ...
00 // ...
90 08 7F // Note on
08 00 // Note off
B0 08 7F // Now CC looks good again!
08 00
Is this supported in android?
Hi @diwic !
I'd like to access PCMs from multiple threads (at least two) in order to:
In order to do that, there will be three threads.
Therefore, both capture and playback PCMs need to be shared with the status gathering thread, that'll periodically adjust an asynchronous resampler ratio.
In alsa-lib tests, the pcm-multi-thread.c example shows how it is possible in C.
It's simple, a single static snd_pcm_t *pcm
is declared on top and all threads call methods on it.
Would it be possible to do that with alsa-rs?
Right now, I get this error:
error[E0277]: the trait bound `*mut alsa_sys::snd_pcm_t: std::marker::Sync` is not satisfied in `&alsa::PCM`
--> src/alsa_audio_time.rs:155:9
|
155 | thread::spawn(|| {
| ^^^^^^^^^^^^^ `*mut alsa_sys::snd_pcm_t` cannot be shared between threads safely
When using pcm.drop()
the Rust compilers fails with:
error[E0040]: explicit use of destructor method
|
1011 | { let pcm = self.0.as_mut().unwrap(); pcm.drop().unwrap(); }
| ^^^^ explicit destructor calls not allowed
#89 (and the associated release) broke semver and caused our builds to fail in CI.
Users are running into the same problem with fresh builds: see this Discord thread.
Please yank the release; and let us know if there's anything we can do to help out :)
Hi,
We're looking to release software dependent on this crate, however find ourselves
having to carry a downstream branch frozen at 2fec79bd4cbf
. This is obviously
not ideal. Would it be possible to tag off a release so that we can get rid of our
downstream branch and use the crate properly?
Thanks :)
snd_seq_event_input
has some documentation about possible returned error codes (-EAGAIN
and -ENOSPC
). The wrapped API has no way to examine the error code.
This is the result of running cargo test
(on my PR branch, but I didn't change anything outside the seq
module), although sometimes this test passes:
failures:
---- pcm::playback_to_default stdout ----
PCM status: Prepared, HwParams(channels: Ok(1), rate: Ok(44100) Hz, format: Ok(S16LE), access: Ok(RWInterleaved), period size: Ok(2048) frames, buffer size: Ok(2097152) frames)
== PCM dump ==
ALSA <-> PulseAudio PCM I/O Plugin
Its setup is:
stream : PLAYBACK
access : RW_INTERLEAVED
format : S16_LE
subformat : STD
channels : 1
rate : 44100
exact rate : 44100 (44100/1)
msbits : 16
buffer_size : 2097152
period_size : 2048
period_time : 46439
tstamp_mode : NONE
tstamp_type : GETTIMEOFDAY
period_step : 1
avail_min : 2048
period_event : 0
start_threshold : 1
stop_threshold : 2097152
silence_threshold: 0
silence_size : 0
boundary : 4611686018427387904
thread 'pcm::playback_to_default' panicked at 'called `Result::unwrap()` on an `Err` value: Error(Some("snd_pcm_writei"), -32)', /checkout/src/libcore/result.rs:859
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
0: <core::result::Result<T, E>>::unwrap
at /checkout/src/libcore/result.rs:737
1: alsa::pcm::playback_to_default
at ./src/pcm.rs:750
2: <F as test::FnBox<T>>::call_box
at /checkout/src/libtest/lib.rs:1368
at /checkout/src/libcore/ops.rs:2606
at /checkout/src/libtest/lib.rs:140
3: std::panicking::try::do_call
at /checkout/src/libtest/lib.rs:1314
at /checkout/src/libstd/panic.rs:296
at /checkout/src/libstd/panicking.rs:454
4: __rust_maybe_catch_panic
at /checkout/src/libpanic_unwind/lib.rs:98
5: std::panicking::try::do_call
at /checkout/src/libstd/panicking.rs:433
at /checkout/src/libstd/panic.rs:361
at /checkout/src/libtest/lib.rs:1313
at /checkout/src/libstd/panic.rs:296
at /checkout/src/libstd/panicking.rs:454
6: __rust_maybe_catch_panic
at /checkout/src/libpanic_unwind/lib.rs:98
7: <F as alloc::boxed::FnBox<A>>::call_box
at /checkout/src/libstd/panicking.rs:433
at /checkout/src/libstd/panic.rs:361
at /checkout/src/libstd/thread/mod.rs:360
at /checkout/src/liballoc/boxed.rs:640
8: std::sys::imp::thread::Thread::new::thread_start
at /checkout/src/liballoc/boxed.rs:650
at /checkout/src/libstd/sys_common/thread.rs:21
at /checkout/src/libstd/sys/unix/thread.rs:84
9: start_thread
10: clone
failures:
pcm::playback_to_default
test result: FAILED. 20 passed; 1 failed; 0 ignored; 0 measured
It's been a while since you've released v0.5.0 and there have been at least a couple additions and fixes since then. A new release would be greatly appreciated. Maybe v0.5.1? Or whatever versioning scheme you're using? In my mind the next release wouldn't really be a major release but that's completely up to you.
The nix dependency version has been updated in 0.5.1 (c444589), but the nix's types are used in the public API of alsa, so this breaks downstreams such as cpal.
error[E0308]: mismatched types
--> /home/parallels/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.13.4/src/host/alsa/mod.rs:245:26
|
244 | let handle = match handle_result {
| ------------- this expression has type `std::result::Result<host::alsa::alsa::PCM, (host::alsa::alsa::Error, Option<host::alsa::alsa::nix::errno::Errno>)>`
245 | Err((_, Some(nix::errno::Errno::EBUSY))) => {
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `host::alsa::alsa::nix::errno::Errno`, found enum `nix::errno::Errno`
|
= note: perhaps two different versions of crate `nix` are being used?
Please, I very need example "Capture and Playback" (Stereo Microphone) in infinity loop.
failures:
---- src/pcm.rs - pcm (line 6) stdout ----
Test executable failed (exit code 101).
stderr:
ALSA lib confmisc.c:855:(parse_card) cannot find card '0'
ALSA lib conf.c:5111:(_snd_config_evaluate) function snd_func_card_inum returned error: No such file or directory
ALSA lib confmisc.c:422:(snd_func_concat) error evaluating strings
ALSA lib conf.c:5111:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory
ALSA lib confmisc.c:1334:(snd_func_refer) error evaluating name
ALSA lib conf.c:5111:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:5599:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM default
thread 'main' panicked at 'called Result::unwrap()
on an Err
value: Error("snd_pcm_open", Sys(ENOENT))', src/pcm.rs:8:59
note: run with RUST_BACKTRACE=1
environment variable to display a backtrace
I noticed that the snd_ctl_elem_id_set_*
functions are missing while the snd_ctl_elem_id_get_*
functions are present. Do you have plans to add them?
Hello.
It would be nice to have an API to know when the volume changes (using snd_mixer_set_callback
).
Thanks to add that.
On nightly there are some warnings on array bound checks:
Compiling alsa v0.1.3 (https://github.com/diwic/alsa-rs#7bc4f794)
warning: this expression will panic at run-time
--> /home/rbalt/.cargo/git/checkouts/alsa-rs-931cd3713a30a710/master/src/chmap.rs:74:49
|
74 | unsafe { slice::from_raw_parts_mut(&mut (*self.0).pos[0], (*self.0).channels as usize) }
| ^^^^^^^^^^^^^^^^ index out of bounds: the len is 0 but the index is 0
warning: this expression will panic at run-time
--> /home/rbalt/.cargo/git/checkouts/alsa-rs-931cd3713a30a710/master/src/chmap.rs:77:45
|
77 | unsafe { slice::from_raw_parts(&mut (*self.0).pos[0], (*self.0).channels as usize) }
| ^^^^^^^^^^^^^^^^ index out of bounds: the len is 0 but the index is 0
Not sure if we need to suppress the warning or changes in the way we use ffi?
Is there a reason why PortSubscribe::new()
is private? I can use PortSubscribe::empty()
instead, but I'm not sure what's the difference.
Calls get_channels instead.
On updating alsa-rs to 0.2.0 I noticed that you changed the way errors are handled now.
While I think the nix package provides a nice way of representing the errno in rust, I unfortunately don't see a nice way how to use pcm.recover(), which needs the original error code as an integer value.
Maybe it's a good idea to add the error code together with the code() method back to the Error struct to be able to use recover, or is there a better way of doing this?
Alternatively I could probably map nix::errno::{EINTR,EPIPE,ESTRPIPE} back to the libc:: values myself.
If this crate also contained the MIDI APIs, I could use it in https://github.com/Boddlnagg/midir. Since you say that these APIs are not implemented "mostly because nobody asked for them", I'm just going to ask for them now π
I'm currently wrapping some parts myself (https://github.com/Boddlnagg/midir/blob/master/src/backend/alsa/wrappers.rs), mostly to be able to use RAII, but I'm not sure if those wrappers are actually safe. They are used in https://github.com/Boddlnagg/midir/blob/master/src/backend/alsa/mod.rs (ALSA is actually the most complicated of the backends in midir ...).
I got a bug report on my DSP project, where it panics when reading the state of a pcm.
The panic comes from here : https://github.com/diwic/alsa-rs/blob/master/src/pcm.rs#L159
I'm guessing the card returns an invalid value for the state, but it doesn't happen with any of the hardware I have so I can't check that.
Anyway, would it be an option to add an "Invalid" or "Unknown" state variant to avoid a panic with misbehaving hardware? Or let state() return a Result?
I can implement something and make a PR, but let's agree on the ifs and how's first :)
I'm rewriting a C utility in Rust using alsa, and when looking at alsa::seq::EventData::get_data
's content it feels like it is meant to do an unchecked cast. Shouldn't it be marked as unsafe? It feels inherently unsafe to me.
Additionally, you tell us "Donβt use these directly, use generic methods on Event instead". It seems like you tell this so we don't miss-use get_data
, as using it in the wrong context can lead to UB, if I understood correctly. So making it unsafe feels right to me.
This is a follow-up after #16, because I took some time now to look at it. And I'm impressed, the current version contains almost everything that I needed, awesome work! π
I'm missing only one function: snd_seq_control_queue
. Actually I'm using snd_seq_start_queue
and snd_seq_stop_queue
, but those are defined as macros in the original API (wrapping snd_seq_control_queue
). Maybe you can create functions for them also.
I'm not very familiar with the ALSA API, but the way I interpret http://www.alsa-project.org/main/index.php/SMP_Design, it seems that it is possible to send PCM handles across thread boundaries?
In a very simple application with a single audio thread, I'd love to be able to open the PCM device in the main thread, that way I don't have to propagate open/hwparam errors/unwraps back.
However, since *mut alsa_sys::snd_pcm_t
isn't Send
, neither is alsa::PCM
, among other things because no explicit Send
implementation has been added.
While PCM
is definitely not Sync
, I think Send
fits?
Hello!
I just started learning Rust and Alsa and I am trying to access my audio interface (Focusrite Scarlett 18i8 2.gen).
My goal is to have a simple Rust program that can make changes to the interfaces mixer (e.g. muting channel 1, ...).
I started with the following lines to access the interface:
let mixer: Mixer = Mixer::new("hw:3", false).unwrap();
let sid: SelemId = SelemId::new("????", 0);
let selem: Selem = mixer.find_selem(&sid).expect("Coundn't find SelemId");
The code fails trying to find the selem. I dont know which values are expected of the SelemId.
Is this the name/index of an mixer element?
Where can I get these infos?
Thank you in advance!
The links to the ALSA website in the readme and crate-level documentation do not work. Looking at the code this is because it says http://http://
instead of just http://
.
Hi @diwic!
Thanks a lot for the great work on this crate, it's really useful.
For the MultiDSP project, I'm researching the best way to implement an asynchronous resampler that'll keep multiple sound cards in sync.
The best way seems to be leveraging the PCM status delay, avail and timestamps.
It is already possible to query that today but the timestamps seem to always of the default type: DMA.
For the use case of sound card synchronization, the link time and analog times are useful as well.
Documentation: https://www.kernel.org/doc/html/latest/sound/designs/timestamping.html
I rewrote in Rust alsa_time.c from alsa-lib for experimentation and am now testing from that.
Is timestamp type support something you're interested adding?
If I should implement it myself, would you have recommendations?
Compiling alsa v0.2.1
Running `rustc --crate-name alsa /home/rust/.cargo/registry/src/github.com-1ecc6299db9ec823/alsa-0.2.1/src/lib.rs --color always --crate-type lib --emit=dep-info,link -C opt-level=3 -C metadata=976c596c68b6c14b -C extra-filename=-976c596c68b6c14b --out-dir /home/rust/librespot/target/arm-unknown-linux-musleabihf/release/deps --target arm-unknown-linux-musleabihf -L dependency=/home/rust/librespot/target/arm-unknown-linux-musleabihf/release/deps -L dependency=/home/rust/librespot/target/release/deps --extern alsa_sys=/home/rust/librespot/target/arm-unknown-linux-musleabihf/release/deps/libalsa_sys-4c26c22d6bab838f.rlib --extern bitflags=/home/rust/librespot/target/arm-unknown-linux-musleabihf/release/deps/libbitflags-d29977ccc17621f8.rlib --extern libc=/home/rust/librespot/target/arm-unknown-linux-musleabihf/release/deps/liblibc-989e9cf5fcbc9d40.rlib --extern nix=/home/rust/librespot/target/arm-unknown-linux-musleabihf/release/deps/libnix-1ff35c4c0a502aed.rlib --cap-lints allow -L native=/usr/lib/arm-linux-gnueabihf`
error[E0308]: mismatched types
--> /home/rust/.cargo/registry/src/github.com-1ecc6299db9ec823/alsa-0.2.1/src/pcm_direct.rs:325:82
|
325 | mem: DriverMemory::new(fd, (bufsize as usize) * (channels as usize), info.offset, true)?,
| ^^^^^^^^^^^ expected i64, found i32
help: you can cast an `i32` to `i64`, which will sign-extend the source value
|
325 | mem: DriverMemory::new(fd, (bufsize as usize) * (channels as usize), info.offset.into(), true)?,
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: Could not compile `alsa`.
I could fix this error by changing the line 325 of pcm_direct.rs to:
mem: DriverMemory::new(fd, (bufsize as usize) * (channels as usize), info.offset as i64, true)?
Did others experience the same issue and does this error occur on other platforms as well?
Can't find it in docs, and searched in the source code. There seems to be no way to subscribe to events with snd_ctl_subscribe_events
.
What I want to do is to wait for events, then get volume information. Waiting for events can be done like this in C:
const char *ctlname = "default";
snd_ctl_t *ctl;
assert( snd_ctl_open(&ctl, ctlname, SND_CTL_READONLY) == 0 );
assert( snd_ctl_subscribe_events(ctl, 1) == 0 );
struct pollfd* fd = malloc(sizeof(struct pollfd));
snd_ctl_poll_descriptors(ctl, fd, 1);
while (1) {
err = poll(fd, 1, -1);
while (snd_ctl_read(ctl, event) > 0) {
..... etc .....
I'm quite new to rust, and was wondering what the best way to achieve the following is?
As the SelemId is borrowed from the Mixer, there isn't much I can do correct?
fn get_selem(card: &str, mixer: &str) -> Result<(mixer::Selem), Box<Error>> {
let selem_id = mixer::SelemId::new(mixer, 0);
let mixer = mixer::Mixer::new(card, false)?;
let selem = mixer.find_selem(&selem_id)?;
Ok((selem))
}
error[E0106]: missing lifetime specifier
--> playback/src/mixer/alsamixer.rs:12:50
|
12 | fn get_selem(card: &str, mixer: &str) -> Result<(mixer::Selem), Box<Error>> {
| ^^^^^^^^^^^^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `card` or `mixer`
nix
has since updated to 0.26, currently this library is still on 0.24, which is causing duplicated code and slower compilations. Just as in #103 is there any chance of updating this dependency? It looks like it should be backwards compatible in what this library uses from it for a quick look.
I've been using alsa-rs for a while now, and I have to say that it's my favorite audio streaming & MIDI crate by far. It allows me to do almost everything I once did in C with ALSA, but without the all the super verbose error handling.
I've successfully integrated alsa-rs in my real-time synthesizer engine, and it works like a charm. Superficially, audio capture also works in this engine, but when it starts using more CPU time (>50%), the audio drop outs start. Disable capture and you can push it up to 90%. I'm doing 512 frame latency @ 48 kHz on a PREEMPT kernel, and capturing from the same device as I'm playing on.
What I'm trying to do here is mixing captured audio directly with synthesized sound. I think for this to work you'd need to fill up your playback stream, forward your capture stream, and then start capturing. I'm linking playback and capture via alsa::pcm::link()
. The problem is that forwarding is not supported in alsa-rs.. Is there any way around this?
Seq::open
requires a name
parameter which (according to ALSA documentation) should usually be "default"
. I do not know when it does not need to be "default"
.
Maybe the parameter could be turned into an Option<&CStr>
instead, and if None
is passed, we can use the following without an allocation or runtime check:
CStr::from_bytes_with_nul_unchecked(b"default\0")
.
Hi, are there any plans to add snd_ctl_elem_read and snd_ctl_elem_write functions ?
I would like to be able to do from safe rust basically what this command does:
amixer -c 0 cset numid=26 64,4,0
Please see https://fossies.org/linux/alsa-utils/amixer/amixer.c @ line 1128 for amixer cset function.
Thanks!
I'm currently working on a project that uses this crate heavily, much thanks for all the hard work.
I am currently using the following logic to obtain a HCtl
instance:
use alsa::{Ctl, HCtl};
use alsa::card::{Iter as CardIter};
let mut card_iter = CardIter::new();
while let Some(Ok(card)) = card_iter.next() {
let ctl = Ctl::from_card(&card, true).unwrap();
let hctl = HCtl::new(format!("hw:{}", card.get_index()).as_str(), true).unwrap();
// do work
}
Fetching a HCtl
instance from the device name is error-prone perhaps, as there's no direct way to go from a Card
instance to an HCtl
instance. It's possible to go from Card
to Ctl
using Ctl::from_card
, but no way to go from either Card
or Ctl
to HCtl
.
In the underlying alsa-sys
crate, and thus the C library, snd_hctl_open_ctl
allows creation of a snd_hctl_t
handle from an existing snd_ctl_t
. Therefore, it shouldn't be too difficult to implement a method like HCtl::from_ctl
to make it easier to get a HCtl
from a Ctl
.
I may be able to contribute some work here, but it will have to wait a few days at best.
Hello, I am using this library for sound card development, but I find that this library lacks the snd_pcm_set_params API interface. Can you support this interface?
I've been looking at the alsa api to use the mixer to set volume of individual channels. Do we need to add a wrapper for the snd_mixer_*
and/or snd_mixer_selem_*
?
Consider the following example:
use alsa::seq::{Addr, PortSubscribe};
fn foo(sub: &PortSubscribe) {
sub.set_dest(Addr {
client: 123,
port: 45,
});
}
fn main() {
let sub = PortSubscribe::empty().unwrap();
println!("{:?}", sub.get_dest());
foo(&sub);
println!("{:?}", sub.get_dest());
}
This just feels unsound to me, mutating the state of ALSA types without requiring mutable references. PortSubscribe
is not the only one affected by this, there are dozens of setter functions in this crate without proper mutability constraints.
I was having some issues with setting the volume via the Mixer api, and after some head scratching realised that my user space was 32bit, so all my i64
volume values were overflowing.
Would it make sense to switch to isize
instead of i64
- where the underlying api uses c_long
?
Like at:
Lines 339 to 341 in 8666041
MidiEvent::encode
really needs documentation as to what it does.
From the signature and the implementation I can see that it returns (in case of success) the number of bytes consumed from the buffer as well as the encoded event (or None
if no complete message was encoded).
Then it also needs to be documented that the event buffer is copied for long (sysex) messages. I guess this is because the documentation of snd_midi_event_encode
states that
When this function returns a system exclusive sequencer event (ev->type is SND_SEQ_EVENT_SYSEX), the data pointer (ev->data.ext.ptr) points into the MIDI event parser's buffer. Therefore, the sequencer event can only be used as long as that buffer remains valid, i.e., until the next call to snd_midi_event_encode, snd_midi_event_encode_byte, snd_midi_event_resize_buffer, snd_midi_event_init, snd_midi_event_reset_encode, or snd_midi_event_free for that MIDI event parser.
This makes me wonder whether it might be possible to encode this in the Rust typesystem using lifetimes, instead of requiring a copy?
Furthermore, the documentation of snd_seq_event_input
(where currently the data is also copied by Event::extract
) has no such comment, which makes me wonder if the buffer there is managed by the event itself (because there is no separate underlying buffer).
Hi @diwic!
Following on #33 (comment)
Here is a test program:
https://github.com/supercurio/asrc-rs-research/blob/master/src/alsa_direct_status_test.rs
Runs on a amd64 desktop Ubuntu 17.04 with all ALSA cards.
Fails with Error("mmap (of driver memory)", Sys(ENXIO))', libcore/result.rs:945:5
on Raspberry Pi 3+ 4.14.30-v7+ capture and playback with:
Hi @diwic :)
Also for the MultiDSP project, it would be useful to gain the ability to link/unlink PCMs.
It's a feature which helps to reach the lowest latency without xrun when capturing then playing at the same sample rate from ADC/DAC running from the same master clock + PLL or crystal.
The way it works is by preparing and starting PCMs to their running state at the same time.
I haven't come across hardware where it is applicable but it is also possible to link more than two in a group.
Sorry for opening an issue for this, but I wanted to reach out to discuss how I might be able to contribute to this crate in terms of documentation and code. If you're on discord, my username is naftulikay
, if email works better, you can reach me at me
AT my first name DOT w t f
. Tried emailing at your ubuntu email address but it wouldn't route through. I'm also @naftulikay
on twitter if that's a preferred method of communication.
Thanks for this very nice library! I'm using it in a DSP project and it's working very well.
But now I'm pretty stuck on an issue and need a little help. As far as I understand, when there is no data coming and we are in blocking mode, then readi (https://docs.rs/alsa/0.4.3/alsa/pcm/struct.IO.html#method.readi) should just wait forever or return with one of EBADFD, EPIPE or ESTRPIPE.
My problem is that I get EIO. The specific case I'm struggling with is when capturing from an spdif input on a Raspberry Pi with a Hifiberry DigiIO, and the source stops the datastream. What happens then is that readi waits for about 3 seconds, then returns with EIO.
Shoud this be possible? What does it actually mean?
I would like to handle the situation so that things can just continue when the signal comes back. After starting the spdif stream again I have tried just readi again but that's no good. I also tried prepare(), but that gives EBUSY. Should I try recover()?
One problem here is that I don't have a card that behaves like this myself, so testing many different things is quite slow. Any ideas to narrow down the number of things to try would be highly appreciated!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.