wavy
wavy copied to clipboard
Default microphone seems not to record
- wavy v0.9.1
- OS Arch linux
- Confirmed default microphone to work in slack, discord, zoom, cpal crate
use anyhow::Result;
use std::thread::sleep;
use std::time::Duration;
// This example records audio for 5 seconds and writes to a raw PCM file.
use fon::{mono::Mono32, Audio, Frame};
use wavy::{Microphone, MicrophoneStream};
/// An event handled by the event loop.
enum Event<'a> {
/// Microphone has recorded some audio.
Record(MicrophoneStream<'a, Mono32>),
}
/// Shared state between tasks on the thread.
struct State {
/// Temporary buffer for holding real-time audio samples.
buffer: Audio<Mono32>,
}
impl State {
/// Event loop. Return false to stop program.
fn event(&mut self, event: Event<'_>) {
match event {
Event::Record(microphone) => {
println!("Recording");
self.buffer.extend(microphone);
if self.buffer.len() >= 48_000 * 10 {
write_pcm(&self.buffer);
}
}
}
}
}
/// Save a Raw PCM File from an audio buffer.
fn write_pcm(buffer: &Audio<Mono32>) {
let mut pcm: Vec<u8> = Vec::new();
for frame in buffer.iter() {
let sample: f32 = frame.channels()[0].into();
pcm.extend(sample.to_le_bytes().iter());
}
dbg!(&pcm);
}
async fn wait() -> Result<()> {
sleep(Duration::from_millis(2000));
Ok(())
}
#[tokio::main]
async fn main() -> Result<()> {
let mut state = State {
buffer: Audio::with_silence(48_000, 0),
};
let mut microphone = Microphone::default();
state.event(Event::Record(microphone.record().await));
wait().await?;
dbg!("finished");
Ok(())
}
It logs "recording" once, but never reaches to the limit of the buffers to write.
@beckend Thanks, I'll look into why this might be happening.
I can observe the same issue on a fresh install of Ubuntu 22.10. It works on another system running Pop!_OS.
I tested the mic and speaker in other applications and they work without a hitch.
Running sudo arecord -l
also displays my mic.
I also tried connecting a second mic, which shows up using the above command and also runs on all other apps but doesn't with wavy.
I tried the "play" example and that doesn't seem to work either using the default speakers.
I already wrote a bunch of code using wavy on my primary system so I hope I can fix this so I won't have to rewrite that to run it on my second system. I can provide any details necessary to debug this. Thanks. @AldaronLau
EDIT: For some additional context
- I used Microphone::query() according to this comment and get the following panic:
ALSA lib pcm_direct.c:1643:(snd1_pcm_direct_initialize_secondary_slave) unable to mmap channels
ALSA lib pcm_dsnoop.c:632:(snd_pcm_dsnoop_open) unable to initialize slave
ALSA lib pcm_dsnoop.c:566:(snd_pcm_dsnoop_open) unable to open slave
thread 'main' panicked at 'Microphone doesn't exist', examples/play.rs:37:14
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
- I used cpal examples to play and record and both work as expected.
It seems that the code isn't going past the Pending
stage for both record and play examples.
Thanks, @AnkushMalaker! I haven't had as much time as I would like to work on Wavy recently, but I will use some of my holiday time off to look at this, and updating Wavy. I think this might be related to the case where Wavy is not able to get the requested format of F32LE from ALSA, and doesn't properly handle fallbacks. Can you provide a list of the supported I16/F32/etc., interleaved/non-interleaved, and number of channels settings for the default speakers and microphones of both systems?
Sure! Where/how can I get this info? @AldaronLau
@AnkushMalaker you can get it by running:
arecord --dump-hw-params default
Which on my machine, produces
Warning: Some sources (like microphones) may produce inaudible results
with 8-bit sampling. Use '-f' argument to increase resolution
e.g. '-f S16_LE'.
Recording WAVE 'default' : Unsigned 8 bit, Rate 8000 Hz, Mono
HW Params of device "(null)":
--------------------
ACCESS: MMAP_INTERLEAVED MMAP_NONINTERLEAVED RW_INTERLEAVED RW_NONINTERLEAVED
FORMAT: U8 S16_LE S24_LE S32_LE FLOAT_LE S24_3LE S24_3BE
SUBFORMAT: STD
SAMPLE_BITS: [8 32]
FRAME_BITS: [8 2048]
CHANNELS: [1 64]
RATE: [1 384000]
PERIOD_TIME: (0 4294967295)
PERIOD_SIZE: (0 2097152]
PERIOD_BYTES: [128 2097152]
PERIODS: [2 1024]
BUFFER_TIME: (2 4294967295]
BUFFER_SIZE: [1 4194304]
BUFFER_BYTES: [256 4194304]
TICK_TIME: ALL
--------------------
Then,
aplay --dump-hw-params default
Which on my machine, produces:
Playing WAVE 'default' : Unsigned 8 bit, Rate 8000 Hz, Mono
HW Params of device "(null)":
--------------------
ACCESS: MMAP_INTERLEAVED MMAP_NONINTERLEAVED RW_INTERLEAVED RW_NONINTERLEAVED
FORMAT: U8 S16_LE S24_LE S32_LE FLOAT_LE S24_3LE S24_3BE
SUBFORMAT: STD
SAMPLE_BITS: [8 32]
FRAME_BITS: [8 2048]
CHANNELS: [1 64]
RATE: [1 384000]
PERIOD_TIME: (0 4294967295)
PERIOD_SIZE: (0 2097152]
PERIOD_BYTES: [128 2097152]
PERIODS: [2 1024]
BUFFER_TIME: (2 4294967295]
BUFFER_SIZE: [1 4194304]
BUFFER_BYTES: [256 4194304]
TICK_TIME: ALL
--------------------
Thanks. Here it is. @AldaronLau On the machine where its NOT working:
$arecord --dump-hw-params default
Warning: Some sources (like microphones) may produce inaudiable results
with 8-bit sampling. Use '-f' argument to increase resolution
e.g. '-f S16_LE'.
Recording WAVE 'default' : Unsigned 8 bit, Rate 8000 Hz, Mono
HW Params of device "default":
--------------------
ACCESS: MMAP_INTERLEAVED MMAP_NONINTERLEAVED MMAP_COMPLEX RW_INTERLEAVED RW_NONINTERLEAVED
FORMAT: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE MU_LAW A_LAW IMA_ADPCM S20_LE S20_BE U20_LE U20_BE S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE U18_3BE
SUBFORMAT: STD
SAMPLE_BITS: [4 64]
FRAME_BITS: [4 640000]
CHANNELS: [1 10000]
RATE: [4000 4294967295)
PERIOD_TIME: (21333 21334)
PERIOD_SIZE: (85 91628833)
PERIOD_BYTES: (42 4294967295)
PERIODS: (0 17247242)
BUFFER_TIME: [1 4294967295]
BUFFER_SIZE: [170 1466015503]
BUFFER_BYTES: [85 4294967295]
TICK_TIME: ALL
--------------------
$aplay --dump-hw-params default
Playing WAVE 'default' : Unsigned 8 bit, Rate 8000 Hz, Mono
HW Params of device "default":
--------------------
ACCESS: MMAP_INTERLEAVED MMAP_NONINTERLEAVED MMAP_COMPLEX RW_INTERLEAVED RW_NONINTERLEAVED
FORMAT: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE MU_LAW A_LAW IMA_ADPCM S20_LE S20_BE U20_LE U20_BE S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE U18_3BE
SUBFORMAT: STD
SAMPLE_BITS: [4 64]
FRAME_BITS: [4 640000]
CHANNELS: [1 10000]
RATE: [4000 4294967295)
PERIOD_TIME: (21333 21334)
PERIOD_SIZE: (85 91628833)
PERIOD_BYTES: (42 4294967295)
PERIODS: (0 17247242)
BUFFER_TIME: [1 4294967295]
BUFFER_SIZE: [170 1466015503]
BUFFER_BYTES: [85 4294967295]
TICK_TIME: ALL
--------------------
On the system where it is working:
$ arecord --dump-hw-params default
Warning: Some sources (like microphones) may produce inaudible results
with 8-bit sampling. Use '-f' argument to increase resolution
e.g. '-f S16_LE'.
Recording WAVE 'default' : Unsigned 8 bit, Rate 8000 Hz, Mono
HW Params of device "default":
--------------------
ACCESS: RW_INTERLEAVED
FORMAT: U8 S16_LE S16_BE S24_LE S24_BE S32_LE S32_BE FLOAT_LE FLOAT_BE MU_LAW A_LAW S24_3LE S24_3BE
SUBFORMAT: STD
SAMPLE_BITS: [8 32]
FRAME_BITS: [8 1024]
CHANNELS: [1 32]
RATE: [1 384000]
PERIOD_TIME: (2 4294967295)
PERIOD_SIZE: [1 1398102)
PERIOD_BYTES: [128 1398102)
PERIODS: [3 1024]
BUFFER_TIME: (7 4294967295]
BUFFER_SIZE: [3 4194304]
BUFFER_BYTES: [384 4194304]
TICK_TIME: ALL
--------------------
$ aplay --dump-hw-params default
Playing WAVE 'default' : Unsigned 8 bit, Rate 8000 Hz, Mono
HW Params of device "default":
--------------------
ACCESS: RW_INTERLEAVED
FORMAT: U8 S16_LE S16_BE S24_LE S24_BE S32_LE S32_BE FLOAT_LE FLOAT_BE MU_LAW A_LAW S24_3LE S24_3BE
SUBFORMAT: STD
SAMPLE_BITS: [8 32]
FRAME_BITS: [8 1024]
CHANNELS: [1 32]
RATE: [1 384000]
PERIOD_TIME: (2 4294967295)
PERIOD_SIZE: [1 1398102)
PERIOD_BYTES: [128 1398102)
PERIODS: [3 1024]
BUFFER_TIME: (7 4294967295]
BUFFER_SIZE: [3 4194304]
BUFFER_BYTES: [384 4194304]
TICK_TIME: ALL
--------------------
Do note that the audio recording and playing using above command worked on both systems, ie, I could hear the playback in second command of what I recorded in first command.
@AldaronLau Hope you had great holidays. Following up on this, is there an update or workaround I can do based on our previous discussion or should I wait for a fix from you and use a different library in the meantime?
@AnkushMalaker I wasn't able to put aside as much time as I would like to look at this. But, it looks like the issue is not what I thought it was. I now suspect it has to do with the something in the poll()
implementation. A timeout followed by re-polling the future might fix the issue as a hack-y work around (in the past, there's been similar bugs with this library, just might have missed an edge case in the last fix). I think once I re-implement the poll()
method to receive from a channel (a planned change) it may fix the issue.