Send bidirectional signal from bluetooth PCM to loopback to use it in linphone - alsa

I have a bluetooth-speaker (with microphone) connected to my system. I am using bluez 5.50 and bluealsa 1.3.1 and my ~/.asoundrc currently looks like this:
pcm.!default {
type asym
playback.pcm "looptest"
capture.pcm "looprec"
}
pcm.looptest {
type plug
slave {
pcm {
type bluealsa
device E4:22:A5:58:09:95
profile "a2dp"
}
}
hint {
show on
description "Calisto"
}
}
ctl.looptest {
type bluealsa
}
pcm.looprec {
type plug
slave {
pcm {
type bluealsa
interface "hci0"
device E4:22:A5:58:09:95
profile "sco"
}
}
hint {
show on
description "Calisto REC"
}
}
ctl.looprec {
type bluealsa
}
When playing audio with aplay the bluetoothspeaker is used as default, so I only have to type aplay soundfile.wav. Also when recording audio using arecord -f cd record.wav the sound gets recorded correctly.
My main problem is, that when using linphone, only "real" soundcards can be selected as playback/capture devices. What somehow helped was to create an alsa-loopback device. When starting alsaloop -P "hw:Loopback,1,0" -C "looptest" -t 500000 -d and then making a call in linphone, I can hear the voice of the callee. But the callee can not hear my voice, which is obvious, as until now, I did not configure a way of the microphone to the loopback device.
How to create this channel? I tried alsaloop -P "hw:Loopback,1,1" -C "looprec" -t 500000 -r 44100 and also tried several other loopback index-combinations like 0,0 0,1 1,0 but none did the trick. As my current alsa-knowledge is very limited, any hints what I might do wrong? Maybe even the Loopback solution is not needed and the trick can be done with some asoundrc-magic? Or are there other solutions? The only thing I want to avoid is Pulseaudio, as it does not work well with bluealsa

I finally solved the problem by using pulseaudio which correctly worked with the Bluetooth speaker and also is supported by linphone.
In case anyone is interested in my summary, how to connect to Bluetooth speakers and make calls with linphone under a Raspberry Pi with Raspbian Stretch have a look at https://gist.github.com/stefan-wegener/db61bd83a19b4901a2dbc6d78e237b63

Related

how does the rate plugin work in the alsa-lib?

I'm using the alsa-lib in my embeded linux. The next is my .asoundrc.
pcm.rate16k {
type plug
slave {
pcm "hw:0,0"
rate 16000
}
}
It works well when I play a mono audio file(rate is 48000Hz and format is S16_LE) using commands aplay -D rate16k -c 1 -r 48000 -f S16_LE test_48k.raw.
What I am confused is where the resample process implemented. I read the alsa-project introduction and read source code of alsa-lib and analyze the snd_pcm_open API.
snd_pcm_open ==> _snd_pcm_plug_open ==> _snd_pcm_hw_open ==> snd_pcm_hw_open ==> snd_pcm_hw_open_fd and here return the slave pcm pointer. Then aplay then calls snd_pcm_writei to write audio data and eventually calls snd_pcm_mmap_writei.
I try to analyze snd_pcm_mmap_writei but the alsa-lib is so complex that I still have no idea about how the rate converted. Please help or try to give some ideas how to analyze this process.

libsox: record from default microphone

I need to open the default audio capture device and start recording. libsox seems to be a nice cross-platform solution. Using the binary frontend, I can just rec test.wav and the default microphone is activated.
However, when browsing the documentation, no similar functionality exists. This thread discusses precisely the same topic as my question, but doesn't seem to have reached a solution.
Where could an example of using libsox for recording from the default audio device be located?
You can record using libsox. Just set the input file to "default" and set the filetype to the audio driver (e.g. coreaudio on mac, alsa or oss on linux)
const char* audio_driver = "alsa";
sox_format_t* input = sox_open_read("default", NULL, NULL, audio_driver);
Look at some examples for more info on how to structure the rest of the code.
You need to record with alsa first and use libsox for the right format. libsox is not for recording. see example: https://gist.github.com/albanpeignier/104902

how to run alsa application without killing pulseaudio?

I am writing an application that uses alsa. I have to kill pulseaudio each time I run my program, otherwise I have a "ressource busy" error message. I use the "default" device in my alsa program.
Here is my asoundrc:
pcm.!default {
type plug
slave.pcm "dmixer"
}
pcm.dmixer {
type dmix
ipc_key 1024
slave {
pcm "hw:1,0"
period_time 0
period_size 1024
buffer_size 4096
rate 44100
}
bindings {
0 0
1 1
}
}
ctl.dmixer {
type hw
card 1
}
Your .asoundrc explicitly bypasses PulseAudio.
The purpose of these definitions is to do software mixing, and to use the second card by default.
Both can be done with PulseAudio, so just remove this file.
To suspend (without killing nor uninstalling) pulseaudio to run a program use the pasuspender application. Like so :
pasuspender -- program args
For example, with aplay :
pasuspender -- aplay music.wav
There is a second potential problem in that pulse audio can override your asoundrc default device. This is a problem on some Linux distributions when you want to run ALSA applications using the default device in the ~/.asoundrc file. For some reason, ALSA still decides to override our default specification (in the ~/.asoundrc file) and use pulse instead.
The reason why this happens on some distributions is that alsa.conf searches many places for configuration files (as well as your ~/.asoundrc file). One of the places it searchs is /etc/alsa/conf.d/. On my system /etc/alsa/conf.d/ has the file 99-pulseaudio-default.conf.example which seems to be processed last and overrides any personal choices for default. The 99-pulseaudio-default.conf.example file sets the following :
pcm.!default pulse
One way to override pulse as your default device (without uninstalling pulseaudio) is to put a load hook into your ~/.asoundrc file. At the top of your ~/.asoundrc file, instruct ALSA to re-load the config file ~/.asoundrc. An example ~/.asoundrc file is as follows :
#hooks [
{
func load
files [
"~/.asoundrc"
]
errors false
}
]
pcm.!default {
type hw
card "AudioInjector.Pro"
}
ctl.!default {
type hw
card "AudioInjector.Pro"
}

ALSA Api: How to play two wave files simultaneously?

What is the required API configuration/call for playing two independent wavefiles overlapped ?
I tried to do so , I am getting resource busy error. Some pointers to solve the problem will be very helpful.
Following is the error message from snd_pcm_prepare() of the second wavefile
"Device or resource busy"
You can configure ALSA's dmix plugin to allow multiple applications to share input/output devices.
An example configuration to do this is below:
pcm.dmixed {
type dmix
ipc_key 1024
ipc_key_add_uid 0
slave.pcm "hw:0,0"
}
pcm.dsnooped {
type dsnoop
ipc_key 1025
slave.pcm "hw:0,0"
}
pcm.duplex {
type asym
playback.pcm "dmixed"
capture.pcm "dsnooped"
}
# Instruct ALSA to use pcm.duplex as the default device
pcm.!default {
type plug
slave.pcm "duplex"
}
ctl.!default {
type hw
card 0
}
This does the following:
creates a new device using the dmix plugin, which allows multiple apps to share the output stream
creates another using dsnoop which does the same thing for the input stream
merges these into a new duplex device that will support input and output using the asym plugin
tell ALSA to use the new duplex device as the default device
tell ALSA to use hw:0 to control the default device (alsamixer and so on)
Stick this in either ~/.asoundrc or /etc/asound.conf and you should be good to go.
For more information see http://www.alsa-project.org/main/index.php/Asoundrc#Software_mixing.
ALSA does not provide a mixer. If you need to play multiple audio streams at the same time, you need to mix them together on your own.
The easiest way this can be accomplished is by decoding the WAV files to float samples, add them, and clip them when converting them back to integer samples.
Alternatively, you can try to open the default audio device (and not a hardware device like "hw:0") multiple times, once for each stream you wish to play, and hope that the dmix ALSA plugin is loaded and will provide the mixing functionality.
As ALSA provides a mixer device by default (dmix), you can simply use aplay, like so :
aplay song1.wav &
aplay -Dplug:dmix song2.wav
If your audio files are the same rate and format, then you don't need to use plug. It becomes :
aplay song1.wav &
aplay -Ddmix song2.wav
If however you want to program this method, there are some C++ audio programming tutorials here. These tutorials show you how to load audio files and operate different audio subsystems, such as jackd and ALSA.
In this example it demonstrates playback of one audio file using ALSA. It can be modified by opening a second audio file like so :
Sox<short int> sox2;
res=sox2.openRead(argv[2]);
if (res<0 && res!=SOX_READ_MAXSCALE_ERROR)
return SoxDebug().evaluateError(res);
Then modify the while loop like so :
Eigen::Array<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> buffer, buffer2;
size_t totalWritten=0;
while (sox.read(buffer, pSize)>=0 && sox2.read(buffer2, pSize)>=0){
if (buffer.rows()==0 || buffer.rows()==0) // end of the file.
break;
// as the original files were opened as short int, summing will not overload the int buffer.
buffer+=buffer2; // sum the two waveforms together
playBack<<buffer; // play the audio data
totalWritten+=buffer.rows();
}
You can use this configuration also
pcm.dmix_stream
{
type dmix
ipc_key 321456
ipc_key_add_uid true
slave.pcm "hw:0,0"
}
pcm.mix_stream
{
type plug
slave.pcm dmix_stream
}
Update it in ~/.asoundrc or /etc/asound.conf
You can use command
For wav file
aplay -D mix_stream "filename"
For raw or pcmfile
aplay -D mix_stream -c "channels" -r "rate" -f "format" "filename"
Enter the value for channels, rate, format and filename as per your audio file
following is a very simplified multi-thread playback solution (assuming both files are the same sample format, same channel number and same frequency):
starting buffer based thread per each file decoding (have to make this code 2 times - for file1 and for file2):
import wave
import threading
periodsize = 160
f = wave.open(file1Wave, 'rb')
file1Alive = True
file1Thread = threading.Thread(target=_playFile1)
file1Thread.daemon = True
file1Thread.start()
file decoding thread itself (also has to be defined twice - for file1 and for file2) :
def _playFile1():
# Read data from RIFF
while file1Alive:
if file1dataReady:
time.sleep(.001)
else:
data1 = f.readframes(periodsize)
if not data1:
file1Alive = False
f.close()
else:
file1dataReady == True
starting merging thread (aka funnel) to merge file decodings
import alsaaudio
import threading
sink = alsaaudio.PCM(alsaaudio.PCM_PLAYBACK, device="hw:CARD=default")
sinkformat = 2
funnelalive = True
funnelThread = threading.Thread(target=self._funnelLoop)
funnelThread.daemon = True
funnelThread.start()
merge and play (aka funnel) thread
def _funnelLoop():
# Reading all Inputs
while funnelalive:
# if nothing to play - time to selfdestruct
if not file1Alive and not file2Alive:
funnelalive = False
sink.close()
else:
if file1dataReady and file2dataReady:
# merging data from others but first
datamerged = audioop.add(data2, data2, sinkformat)
file1dataReady = False
file2dataReady = False
sink.write(datamerged)
time.sleep(.001)

need AT-Command to copy files from sd-card

i have usb-modem that i can comunicate with it using AT-Command.
i can send and recive sms using it.
we know that we can insert an SD-Card into the usb-modem and use it as a storage device
but i been stuck for days searching how i can work on files on sd card using AT-Command??
please help. thanks in advance
I don't think you can do this. The AT command-set is only for doing "phonestuff". Calling, texting (which in itself is an extension), and such.
The usual reason for usb-modems to have built-in storage is so you can store the drivers there. This would let you use the modem on any computer without needing to connect to the internet to get the drivers.
Are you sure the modem doesn't expose the card as a drive as other USB devices do (e.g cameras, phones, etceteras)? I can't see a way of retrieving files off it using ATxx commands.
Edit, I did a little digging and found this:
https://wiki.archlinux.org/index.php/Huawei_E1550_3G_modem#AT_commands
And I am wondering if any of the following can point you in the right direction:
AT^U2DIAG=0 - the device is only Modem
AT^U2DIAG=1 - device is in modem mode + CD ROM
AT^U2DIAG=255 - the device in modem mode + CD ROM + Card Reader
AT^U2DIAG=256 - the device in modem mode + Card Reader
AT+CPIN=<PIN-CODE> - enter PIN-code
AT+CUSD=1,<PDU-encoded-USSD-code>,15 - USSD request, result can be found (probably) in /dev/ttyUSB2.
So it would appear you can put the device in a card-reader mode using AT^U2DIAG=256. I'd be interested to see if, when you execute this, whether your drive will then be mapped. I can't really find anything to get files off it after you do this.

Resources