ALSA: Full duplex C example? - c

is there an example of a full-duplex ALSA connection in C? I've read that it is supported, but all the introductory examples I saw did either record or play a sound sample, but I'd like to have one handler that can do both for my VoIP-app.
Big thanks for help,
Jens

Some guy named Alan has published this good (but old) tutorial, Full Duplex ALSA, which is written in C.

You provide a link to both handles and pump them in turn.
Here's alan's code elided and commented.
// the device plughw handle dynamic sample rate and type conversion.
// there are a range of alternate devices defined in your alsa.conf
// try:
// locate alsa.conf
// and check out what devices you have in there
//
// The following device is PLUG:HW:Device:0:Subdevice:0
// Often simply plug, plughw, plughw:0, will have the same effect
//
char *snd_device_in = "plughw:0,0";
char *snd_device_out = "plughw:0,0";
// handle constructs to populate with our links
snd_pcm_t *playback_handle;
snd_pcm_t *capture_handle;
//this is the usual construct... If not fail BLAH
if ((err = snd_pcm_open(&playback_handle, snd_device_out, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
fprintf(stderr, "cannot open output audio device %s: %s\n", snd_device_in, snd_strerror(err));
exit(1);
}
// And now the CAPTURE
if ((err = snd_pcm_open(&capture_handle, snd_device_in, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
fprintf(stderr, "cannot open input audio device %s: %s\n", snd_device_out, snd_strerror(err));
exit(1);
}
then config and pump them.
A ring mod could do the job: http://soundprogramming.net/programming_and_apis/creating_a_ring_buffer or you could use alans way outlined above.

It was my first requirements to a Linux/Unix VoIP projects where I need to know about all of the available audio devices capability and name. Then I need to use these devices to capture and playback the audio.
For everyone's help I have made a (.so) library and a sample Application demonstrating the use of this library in c++.
The output of my library is like-
[root#~]# ./IdeaAudioEngineTest
HDA Intel plughw:0,0
HDA Intel plughw:0,2
USB Audio Device plughw:1,0
The library provides functionality to capture and playback real-time audio data.
Full source with documentation is available in IdeaAudio library with Duplex Alsa Audio
Library source is now open at github.com

See also latency.c, included in alsa-lib source; on the ALSA wiki:
http://www.alsa-project.org/main/index.php/Test_latency.c

Related

libusb can't open CDC device on Windows but it can on Linux

I'm trying to communicate with a CDC device using libusb. The code I test is listed below;
/* Initialize libusb
*/
rc = libusb_init(NULL);
if (rc < 0) {
fprintf(stderr, "Error initializing libusb: %s\n", libusb_error_name(rc));
exit(1);
}
/* Set debugging output to max level.
*/
libusb_set_debug(NULL, 3);
/* Look for a specific device and open it.
*/
devh = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!devh) {
fprintf(stderr, "Error finding USB device\n");
goto out;
}
Not: I take the code from https://github.com/tytouf/libusb-cdc-example/blob/master/cdc_example.c
I built the project for both windows and linux. In linux, program worked as expected. Device is successfully opened. But in windows, libusb cant open the device. Always return error "UNKNOWN_ERROR" (error code is 0xFFFFFFFb)
What could be error?
I encountered the same problem today(only windows).
It turns out that libusb only works with the winUSB-Drivers.
You have to install them explicitly to your Device. Easiest for me was to use the zadig installer(see link in the link in the comments above) to remove usbser driver and exchange it by the winusb one(for this one device).
Now the Device doesn't get enumerated as COM-Device, but registered as libusb32-Device/libusbKDevice or just USB-Device.
But i can open it in my host application.

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

Getting the device address by device tree file in C

I am working on Linux; when Linux starts up
the DTS (device tree), the file will be loaded by Linux kernel.
My question is, is there have any way to get device address by DTS file using the C lanugage?
For example:
Some part of the DTS file is like:
soc#ffe00000{
.......
i2c#112000{
.......
}
}
I want to get device name(soc,i2c),and address(ffe00000,112000)...
Hi CK vir,
Your question isn't very clear. I'm assuming you are looking for some sort of function that takes as an argument the contents of the dts file and returns a bunch of (device, address) pairs. Is that correct?
Also, it would be useful if you told us what sort of device you are using. Is it a raspberry pi? A beaglebone black? or a full desktop computer? What distro and version of linux are you using?
This might not be exactly what you are looking for, but a while ago, I used a nice library posted here on github. For instance, to get the address for the device named "ethernet", you would do the following.
int err = dtree_open("/proc/device-tree");
if(err != 0)
{
printf("failed to open device tree\n");
exit(1);
}
struct dtree_dev_t *eth = dtree_byname("ethernet");
if(eth == 0)
{
printf("failed to find device named \"ethernet\"\n");
exit(1);
}
//print the base address of the ethernet hardware
printf("base address of ethernet is %i\n", eth->base);
dtree_dev_free(eth);
dtree_close();
I hope this library is as useful for you as it was for me.
If that doesn't help, it is a trivial task to implement a dts parser in C. The "language" for dts isn't terribly complex. A number of details regarding the syntax can be found here.
Best,
John

Set wireless channel using netlink API

I am developing a WiFi tool in Ubuntu Linux 12.04 environment and I need to switch the WiFi interface between different channels.
Currently I found the solution in Wireshark source code ws80211_utils.c in function called ws80211_set_freq but I do not know how to implement it into my source code and which libs to include and how to compile so I could test it.
The problem is that there are too many arguments and flags you have to use. Also, this is the first time I develop a netlink wifi tool.
If there are any good manuals available where to start and how to use netlink calls for WiFi please provide me with the link.
Thanks a lot i advance!
In current Linux versions, nl80211 is the right way to "talk" to the wireless subsystem. Be aware that you cannot arbitrarily set a channel with every driver and every operating mode (master, client, monitor etc.) Some drivers allow a channel change only when the corresponding interface is "down". In modes such as client ("managed"), the channel cannot be set at all because it is defined by the access point.
Also note that not all wireless device drivers use mac80211/cfg80211. For those drivers not using it, you either have to use the old wireless extensions API or (even worse) a driver-specific proprietary API.
Sadly, there seems to be no up-to-date and complete documentation of the nl80211 interface. Please correct me if I am wrong!
Your approach of looking into the source code of other programs seems to be a reasonable way. You could also use the source code of the iw command line utility. iw has an option to set the channel:
$ iw --help
Usage: iw [options] command
Options:
--debug enable netlink debugging
--version show version (3.2)
Commands:
…
dev <devname> set channel <channel> [HT20|HT40+|HT40-]
…
In iw's phy.c, line 91ff. you can find the code called when iw wlan0 set channel is executed. However, this code is definitely not easy to read. It looks like the
NL80211_CMD_SET_WIPHYcommand in conjunction with the NL80211_ATTR_WIPHY_FREQ attribute is the way to go.
In this SO answer you can find a skeleton program for using nl80211. Also, the code of Aircrack-ng (src/osdep/linux.c, function linux_set_channel_nl80211) could act as a blueprint.
The accepted answer is currently correct, but there's no example code posted yet which solves the OP's question (even if nearly 4 years late), so I thought I would add this here for any future search engine users. It's adapted from this SO question and the specific Aircrack-ng file (/src/aircrack-osdep/linux.c, line 1050) that were both previously mentioned.
#include <net/if.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <linux/nl80211.h>
int main(int argc, char *argv[])
{
/* The device's name and the frequency we wish to set it to. */
char *device = "wlan1";
int frequencyMhz = 2442;
/* Create the socket and connect to it. */
struct nl_sock *sckt = nl_socket_alloc();
genl_connect(sckt);
/* Allocate a new message. */
struct nl_msg *mesg = nlmsg_alloc();
/* Check /usr/include/linux/nl80211.h for a list of commands and attributes. */
enum nl80211_commands command = NL80211_CMD_SET_WIPHY;
/* Create the message so it will send a command to the nl80211 interface. */
genlmsg_put(mesg, 0, 0, genl_ctrl_resolve(sckt, "nl80211"), 0, 0, command, 0);
/* Add specific attributes to change the frequency of the device. */
NLA_PUT_U32(mesg, NL80211_ATTR_IFINDEX, if_nametoindex(device));
NLA_PUT_U32(mesg, NL80211_ATTR_WIPHY_FREQ, frequencyMhz);
/* Finally send it and receive the amount of bytes sent. */
int ret = nl_send_auto_complete(sckt, mesg);
printf("%d Bytes Sent\n", ret);
nlmsg_free(mesg);
return EXIT_SUCCESS;
nla_put_failure:
nlmsg_free(mesg);
printf("PUT Failure\n");
return EXIT_FAILURE;
}
Compile this with gcc main.c $(pkg-config --cflags --libs libnl-3.0 libnl-genl-3.0).
Once executed, check the frequency/channel of your device with e.g. iw wlan1 info or iwconfig. There's no serious error checking here, so all you will notice is if the message was sent or not. Hopefully this helps anyone like me making the transition from Wireless Extensions to cfg80211 and nl80211.

Why does PortAudio not play nicely with other audio programs or how can I get it to?

I am trying to write an audio application using PortAudio, but if any other audio programs (usually Firefox) are running at the time which I try to run my program, I get the following error:
PaHost_OpenStream: could not open /dev/dsp for O_WRONLY
PaHost_OpenStream: ERROR - result = -10000
An error occured while using the portaudio stream
Error number: -10000
Error message: Host error.
Obviously, this makes my program pretty useless since it won't work if another program is using sound. Is there a way to get around this or should I just not use PortAudio?
You need to choose a device named "pulse" for PortAudio to work with PulseAudio, which is the sound server used for sound card sharing on the biggest Linux distros nowadays. The error message suggests that it is trying to use the OSS /dev/dsp interface, which does not support card sharing at all.
You can use code like this for listing the devices:
for (int i = 0, end = Pa_GetDeviceCount(); i != end; ++i) {
PaDeviceInfo const* info = Pa_GetDeviceInfo(i);
if (!info) continue;
printf("%d: %s\n", i, info->name);
}
Then supply the right number to OpenStream within stream parameter.
Notice that you need PortAudio v19. The older v18 only supported OSS.

Resources