Recording each channel using ALSA API - audio

I'm using a playstation eye, plugged into a raspberry pi. I have the raspberry pi recognising the built in microphone array of the PSEye and I can sample input levels using
arecord -vv /dev/null -r 16000 -f S16_LE -c 4 -D iec958:CARD=CameraB409241,DEV=0 /dev/null < /dev/null
Now obviously this shows the levels for all 4 channels being summed together. What I wish to do is record each channel separately. Is this possible using the ALSA API?
I've looked through this http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html
And took a look at this http://www.linuxjournal.com/article/6735?page=0,2
But neither seemed to what I needed. This is also similar to sampling both channels of a stereo mic over ALSA as well I suppose. Eventually I want to be able to sample the dB from each microphone at a specific point in time.

To read into a separate buffer for each channel, replace SND_PCM_ACCESS_RW_INTERLEAVED with SND_PCM_ACCESS_RW_NONINTERLEAVED, and replace snd_pcm_readi with snd_pcm_readn.

If you want to record each channel to independent audio files, then you can use this application :
https://github.com/flatmax/gtkiostream/blob/master/applications/ALSACaptureSplitter.C
It needs to be compiled, which is described here :
https://lists.audioinjector.net/pipermail/people/2020-March/000028.html
To use the application specify the base file name and the extension, for example :
ALSACaptureSplitter /tmp/test wav
It can record to many different audio file formats.
You can use the options to change the device, specify the recording time, channel count, etc. Here is the help printed out by the application :
./applications/ALSACaptureSplitter -h
ALSACaptureSplitter : An application to capture input and save to
independent files.
Usage:
ALSACaptureSplitter [options] outFileNamePrefix ext
e.g. ALSACaptureSplitter [options] /tmp/out wav
-D : The name of the device : (-D hw:0)
-c : The number of channels to open, if the available number is less, then it is reduced to the available : (-c 2)
-t : The duration to sample for : (-t 2.1)
-r : The sample rate to use in Hz : (-r 48000)
AUDIO FILE FORMATS:The known output file extensions (output file formats) are the following :
8svx aif aifc aiff aiffc al amb amr-nb amr-wb anb au avr awb caf cdda cdr cvs cvsd cvu dat dvms f32 f4 f64 f8 fap flac fssd gsm gsrt hcom htk ima ircam la lpc lpc10 lu mat mat4 mat5 maud mp2 mp3 nist ogg paf prc pvf raw s1 s16 s2 s24 s3 s32 s4 s8 sb sd2 sds sf sl sln smp snd sndfile sndr sndt sou sox sph sw txw u1 u16 u2 u24 u3 u32 u4 u8 ub ul uw vms voc vorbis vox w64 wav wavpcm wv wve xa xi

Related

arecord records silence instead of audio output

I am trying to record what my device is currently playing using arecord (it is playing audio via mplayer).
I've done everything I have been able to read so far such as checking under which user mplayer is running, setting the user as per the command below, but it only ever records silence.
This is the list of users where my user is ID 1000:
user:x:1000:1000:,,,:/home/user:/bin/bash
This shows that what I am trying to record is running by that user:
user 1217 2.3 1.3 131704 25524 ? SL 09:11 12:15 /usr/bin/mplayer http://example.com/stream
This is the command I am running:
XDG_RUNTIME_DIR=/run/user/1000 /usr/bin/arecord -d 1 /home/user/rec.waw
The command will output:
Recording WAVE '/home/user/rec.waw' : Unsigned 8 bit, Rate 8000 Hz, Mono
And it writes the file, but the content is silent.
I have tried specifying --device but not sure how to specify it from the list of devices below (I tried --device=CARD=Headphones and --device=hw:CARD=Headphones but I get errors.
This is the output of arecord -L
user#device:~ $arecord -L
null
Discard all samples (playback) or generate zero samples (capture)
jack
JACK Audio Connection Kit
pulse
PulseAudio Sound Server
default
Playback/recording through the PulseAudio sound server
output
usbstream:CARD=b1
bcm2835 HDMI 1
USB Stream Output
usbstream:CARD=Headphones
bcm2835 Headphones
USB Stream Output
Any help would be appreciated.

Can I force arecord to record with a certain sampling rate if my sound card allows it?

I am using arecord to record audio using a USB microphone that allows recording up to 384k sampling rate. With Audacity I can easily record with other lower sampling rates (48k, 44.1k ..) but when I use:
arecord -vD hw:4,0 -f S16_LE -d 120 -r 48000 -c 1 sample.wav
It displays a warning message:
Warning: rate is not accurate (requested = 48000Hz, got = 384000Hz)
And records with 384000Hz.
I can't get to fix this.

Storing parameters in .asoundrc does not apply

I have a microphone and I can record voice like so:
arecord test.wav -r 22050 -f S32_LE -V mono
So far so good. However, when a third party software that I'm using (which I think uses ffmpeg internally), wants to use the microphone it fails, since it does not use the above described parameters.
I tried now to move those parameters into my .asoundrc so that they will be picked up by alsa.
The Alsa Wiki tells me that the plug plugin can be used in order to specify the rate and the format:
A more complex tool for conversion is the pcm type plug. the syntax
is:
type plug # Format adjusted PCM
slave STR # Slave name (see pcm_slave)
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
[format STR] # Slave format (default nearest) or "unchanged"
[channels INT] # Slave channels (default nearest) or "unchanged"
[rate INT] # Slave rate (default nearest) or "unchanged"
}
route_policy STR # route policy for automatic ttable generation
# STR can be 'default', 'average', 'copy', 'duplicate'
# average: result is average of input channels
# copy: only first channels are copied to destination
# duplicate: duplicate first set of channels
# default: copy policy, except for mono capture - sum
ttable { # Transfer table (bidimensional compound of
# cchannels * schannels numbers)
CCHANNEL {
SCHANNEL REAL # route value (0.0 ... 1.0)
}
}
So I setup a plugin like so:
pcm.!default {
type asym
playback.pcm {
type plug
slave.pcm "softvol"
}
capture.pcm {
type plug
slave {
pcm "plughw:0" # this works
rate 22050 # does not apply
format S32_LE # does not apply
}
}
}
The pcm "plughw:0" gets picked up however, the rate and the format fall back to 8 Bit and 8000Hz. Also I have to specify -V Mono so that I can record:
arecord test.wav -V mono
Recording WAVE 'test.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
############+ |
So unfortunately none of the required parameters can be added to my settings.
Update
I tried to record using ffmpeg in an attempt to mimic what :
ffmpeg -f alsa -ac 1 -i plughw:0 output.wav -ar 22050 -f S32_LE
The recording starts but no audio is recorded and the rate and format are mixed up again:
aplay output2.wav
Playing WAVE 'output2.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
Update with asym plugin
I did try an asymmetric approach as suggested.
pcm.my_mic {
type hw
card 0
channels 1
format S32_LE
}
pcm.duplex {
type asym
playback.pcm "dmixer"
capture.pcm "my_mic"
}
pcm.!default {
type plug
slave.pcm "duplex"
}
However, when I enter arecord test.wav I'm asked for the format despite the fact that it's configured in the .asoundrc.
When I do enter a format I get the following error:
arecord -f S32_LE
Recording WAVE 'stdin' : Signed 32 bit Little Endian, Rate 8000 Hz, Mono
ALSA lib pcm_params.c:2162:(snd1_pcm_hw_refine_slave) Slave PCM not usable
arecord: set_params:1270: Broken configuration for this PCM: no configurations available.
Update
With some ALSA magic by my friend Y.W. I was able to get arecord to work without parameters, however, it's still somehow using inferior settings when recording audio by default.
The key here it seems was to map the mono signal of my I2s card to a stereo signal.
This is the .asoundrc content:
# This section makes a reference to your I2S hardware, adjust the card name
# to what is shown in arecord -l after card x: before the name in []
# You may have to adjust channel count also but stick with default first
pcm.dmic_hw {
type hw
card raspisound
channels 2
format S32_LE
rate 48000
}
# This is the software volume control, it links to the hardware above and after
# saving the .asoundrc file you can type alsamixer, press F6 to select
# your I2S mic then F4 to set the recording volume and arrow up and down to adjust the volume
# After adjusting the volume - go for 50 percent at first, you can do something like
# arecord -D dmic_sv -c2 -r 48000 -f S32_LE -t wav -V mono -v myfile.wav
pcm.dmic_sv {
type softvol
slave.pcm dmic_hw
control {
name "Boost Capture Volume"
card raspisound
}
min_dB -3.0
max_dB 30.0
}
# This plugin converts the mono input to stereo.
pcm.mono2stereo {
type route
slave.pcm dmic_sv
slave.channels 2
# ttable.input_channel.output_channel volume_gain
ttable.0.0 1
ttable.0.1 1
}
# The "plug" plugin converts channels, rate and format on request.
# In our case it converts the 32 format to whatever the application request.
pcm.convert {
type plug
slave {
pcm mono2stereo
}
}
pcm.convertplayback {
type plug
slave {
pcm "hw:0"
}
}
# Default capture and playback devices
pcm.!default {
type asym
capture.pcm convert
playback.pcm convertplayback
}
By specifying the slave PCM device as plughw:0, you have created a chain of two plug plugins. This means that the application can use whatever sample format it pleases, the upper plugin will convert it to 22 kHz with 32 bits, and the lower plugin will convert it to any format the hardware supports.
To force the hardware to use the specified format, use it directly as slave, with hw:0.
You cannot prevent programs like arecord from using a different format; that is the whole purpose of the plug plugin. To check what format is actually used by the hardware, add the -v parameter to the arecord call.

Capture/Record Audio in Linux for Milliseconds

arecord -d 10 sample.wav
Here, this command will record sample.wav as a 10 second wave file.
From,
http://linuxcommand.org/man_pages/arecord1.html
http://linux.die.net/man/1/arecord
Here, in arecord, for duration (parameter -d) only second can be used.
But for my project, I need to record for 600 milliseconds or 2700 milliseconds. Here, is there any way to use millisecond or microsecond?
Do I need to modify ALSA code to achieve this?
You need to change arecord's source code (aplay.c in the alsa-utils package) to change the type and the parsing of the timelimit variable.
You can use the code i made. It's a C program to use alsa simply.
https://github.com/Waxo/ALSA_encapsulation
With ffmpeg, here to record a 5ms wav sample:
ffmpeg -y -loglevel panic -f alsa -ac 1 -ar 44100 -i hw:2 -t 0.05 volt.wav
The sound card list for the -i parameter:
arecord -l
Bonus! To analyse the sample peaks:
sox -S volt.wav -n stats
You can compile and use the ALSACaptureSplitter application, specifying the duration as a floating point number - which will allow you to specify any accuracy you want. For example :
ALSACaptureSplitter -t 0.6 /tmp/test wav
This command will save audio 600 ms of audio to individual files in the /tmp directory.
You can build the application for your system using this email as a guide.
Here is the help output from the ALSACaptureSplitter command :
ALSACaptureSplitter -h
ALSACaptureSplitter : An application to capture input and save to independent files.
Usage:
ALSACaptureSplitter [options] outFileNamePrefix ext
e.g. ALSACaptureSplitter [options] /tmp/out wav
-D : The name of the device : (-D hw:0)
-c : The number of channels to open, if the available number is less, then it is reduced to the available : (-c 2)
-t : The duration to sample for : (-t 2.1)
-r : The sample rate to use in Hz : (-r 48000)
AUDIO FILE FORMATS:The known output file extensions (output file formats) are the following :
8svx aif aifc aiff aiffc al amb amr-nb amr-wb anb au avr awb caf cdda cdr cvs cvsd cvu dat dvms f32 f4 f64 f8 fap flac fssd gsm gsrt hcom htk ima ircam la lpc lpc10 lu mat mat4 mat5 maud mp2 mp3 nist ogg paf prc pvf raw s1 s16 s2 s24 s3 s32 s4 s8 sb sd2 sds sf sl sln smp snd sndfile sndr sndt sou sox sph sw txw u1 u16 u2 u24 u3 u32 u4 u8 ub ul uw vms voc vorbis vox w64 wav wavpcm wv wve xa xi

How do I get an audio file sample rate using sox?

I would like to get the sample-rate of a given audio file using sox. Couldn't find the commandline to do that.
just use:
soxi <filename>
or
sox --i <filename>
to produce output such as:
Input File : 'final.flac'
Channels : 4
Sample Rate : 44100
Precision : 16-bit
Duration : 00:00:11.48 = 506179 samples = 860.849 CDDA sectors
File Size : 2.44M
Bit Rate : 1.70M
Sample Encoding: 16-bit FLAC
Comment : 'Comment=Processed by SoX'
The latter one is in case you're using the win32 version that doesn't include soxi, by default. To grab the sample rate only, just use:
soxi -r <filename>
or
sox --i -r <filename>
which will return the sample rate alone.

Resources