I am New to audio programming.I want to create small application which is capable of playing and gives volume control . I am using alsa-lib.
I want to know what is the purpose of switch (ex.Master Playback switch), enum in mixer elements and what value should i set to those switchs .
Please suggest me some tutorial for mixer settings as well as alsa programming .
Just collecting some here, that have example code:
ALSA Programming HOWTO v.1.0.0 [alsamodular.sourceforge.net]
A tutorial on using the ALSA Audio API [equalarea.com] 2002
A close look at ALSA [volkerschatz.com]
ALSA API - Sample Programs With Source Code By Aquiles Yanez 2005
Introduction to Sound Programming with ALSA | Linux Journal (pg3 with example code) 2004
Note that some of these are old, and API may have changed in the meantime... you can also look up aplay.c (the source for the command line arecord and aplay), but that one is not the easiest to read for starters...
You'll have a tough time finding anything concrete on ALSA, as I have have found from just starting learning it too. The best place to begin is the ALSA project homepage where they link to a number of tutorials, the best one being Dr Nagorni's one IMO.
From what it sounds like you're trying to do, JACK would most likely be a quicker and easier solution, though.
Check out the docs. There are some good examples.
http://www.alsa-project.org/alsa-doc/alsa-lib/examples.html
Be aware of the safe alsa subset.
https://www.winehq.org/pipermail/wine-bugs/2009-June/179698.html
Here's something small I put together using the various sources I could find. It miiiiiiiiiight be a good starting point.
/* Compile with gcc -lasound -pthread threadaudio.c */
#include <alsa/asoundlib.h>
#include <pthread.h>
#include <stdio.h>
unsigned char audiobuffer[0x400];
pthread_mutex_t audiomutex = PTHREAD_MUTEX_INITIALIZER;
void changeaudio (int volume) {
int i;
pthread_mutex_lock(&audiomutex);
for (i = 0; i < sizeof(audiobuffer); i++)
audiobuffer[i] = (random() & 0xff) * volume / 10;
pthread_mutex_unlock(&audiomutex);
}
void *startaudio (void *param)
{
static char *device = "default";
snd_output_t *output = NULL;
int *audiostop = (int*)param;
int err;
snd_pcm_t *handle;
snd_pcm_sframes_t frames;
changeaudio(5);
if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
printf("Playback open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
if ((err = snd_pcm_set_params(handle,
SND_PCM_FORMAT_U8,
SND_PCM_ACCESS_RW_INTERLEAVED,
1,
48000,
1,
100000)) < 0) { /* 0.1sec */
printf("Playback open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
while (!*audiostop) {
err = snd_pcm_wait(handle, 1000);
if (err < 0) {
fprintf (stderr, "poll failed (%d)\n", err);
break;
}
pthread_mutex_lock(&audiomutex);
frames = snd_pcm_writei(handle, audiobuffer, sizeof(audiobuffer));
pthread_mutex_unlock(&audiomutex);
if (frames < 0)
err = snd_pcm_recover(handle, frames, 0);
if (err < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
break;
}
if (frames > 0 && frames < (long)sizeof(audiobuffer))
printf("Short write (expected %li, wrote %li)\n", (long)sizeof(audiobuffer), frames);
}
snd_pcm_close(handle);
}
int main(void)
{
pthread_t audiothread;
int audiostop = 0;
int volume;
pthread_create(&audiothread, NULL, startaudio, &audiostop);
while (1) {
printf("Enter volume 1 through 10. [0 to quit.]: ");
scanf("%d", &volume);
if (volume == 0) break;
changeaudio(volume);
}
audiostop = 1;
pthread_join(audiothread, NULL);
return 0;
}
And after reading the code above you'll probably want to read this article regarding (among other things) not using locks.
http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing
Related
I'm trying to replicate the behavior of a Windows app on Linux. Specifically, to control the backlighting on a keyboard.
Using Wireshark (on the linux host) to observer what the Windows tool does (when run on a Windows guest), I see a pair of URB_INTERRUPT out messages followed by a pair of URB_INTERRUPT in messages (one of each in each direction).
I've never used libusb before, but reading docs and examples, I've put together the code below. When run, libusb_interrupt_transfer() returns LIBUSB_ERROR_IO. Maybe I'm passing the wrong parameters, maybe I missed some initialization step, this is where my lack of experience with libusb really shines.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libusb-1.0/libusb.h>
int main(int argc, char *argv[]) {
unsigned int interface = 2;
int bSent = 0;
int retval = 0;
unsigned char msg[64];
unsigned char bytes[] = "\x51\x2c\x00\x00\xff\x64\x00\xff\xff\x72\x67\x62";
bzero(msg, sizeof(msg));
memcpy(msg, bytes, sizeof(bytes));
libusb_device_handle *devh;
libusb_init(NULL);
devh = libusb_open_device_with_vid_pid(NULL, 0x0b05, 0x1875);
if (devh) {
printf("Found device\n");
} else {
printf("ERROR: can't find device\n");
exit(1);
}
retval = libusb_set_auto_detach_kernel_driver(devh, interface);
if (!retval) {
printf("Set auto detach kernel driver\n");
} else {
printf("ERROR: failed to set auto detach kernel driver: %s\n", libusb_strerror(retval));
exit(1);
}
retval = libusb_claim_interface(devh, interface);
if (retval < 0) {
printf("ERROR: failed to claim interface %d: %s\n", interface, libusb_strerror(retval));
exit(1);
} else {
printf("Claimed interface %d\n", interface);
}
retval = libusb_interrupt_transfer(devh, interface, msg, sizeof(msg), &bSent, 1000);
if (retval < 0) {
printf("ERROR: libusb_interrupt_transfer() returned %d: %s\n", retval, libusb_strerror(retval));
} else {
printf("libusb_interrupt_transfer() sent %d bytes\n", bSent);
}
libusb_release_interface(devh, interface);
libusb_close(devh);
libusb_exit(NULL);
return(0);
}
Output:
Found device
Set auto detach kernel driver
Claimed interface 2
ERROR: libusb_interrupt_transfer() returned -1: Input/Output Error
I'm working on a embedded linux system (yocto based) and I'm trying to simply get a list of the camera USB video devices (webcams) numbers with the related connected usb port from a C program.
I'm able to get the devices list with vendor ID and connected port doing this:
void usbdevs()
{
libusb_device*** list=NULL;
libusb_context *context = NULL;
ssize_t count;
uint8_t port;
char ncameras=0;
libusb_init(&context);
count = libusb_get_device_list(context,&list);
for(int i=0; i < MAX_NUM_CAMS; i++)
usb_dev_list[i]=0;
for (size_t idx = 0; idx < count; ++idx) {
libusb_device *device = list[idx];
struct libusb_device_descriptor desc = {0};
libusb_get_device_descriptor(device, &desc);
port = libusb_get_port_number(device);
printf("Vendor:Device = %04x:%04x Port: %d\n", desc.idVendor, desc.idProduct,port);
}
libusb_free_device_list(list, count);
libusb_exit(context);
}
What I need now is to know (from the C application) what v4l2 device number is related to the usb camera port, eg. I've got two webcam (same vendor ID) connected which appear as /dev/video0 and /dev/video1 respectively and I can get the connected port for each one using the above code, but, how can I know which ports are connected each one?
I tried to get information from the devices using ioctl calls as it is recommended in this question but when I run the code:
int checkvideodev()
{
int fd;
struct video_capability video_cap;
struct video_window video_win;
struct video_picture video_pic;
if((fd = open("/dev/video0", O_RDONLY)) == -1){
perror("cam_info: Can't open device");
return 1;
}
if(xioctl(fd, VIDIOCGCAP, &video_cap) == -1)
perror("cam_info: Can't get capabilities");
else {
printf("Name:\t\t '%s'\n", video_cap.name);
printf("Minimum size:\t%d x %d\n", video_cap.minwidth, video_cap.minheight);
printf("Maximum size:\t%d x %d\n", video_cap.maxwidth, video_cap.maxheight);
}
if(xioctl(fd, VIDIOCGWIN, &video_win) == -1)
perror("cam_info: Can't get window information");
else
printf("Current size:\t%d x %d\n", video_win.width, video_win.height);
if(xioctl(fd, VIDIOCGPICT, &video_pic) == -1)
perror("cam_info: Can't get picture information");
else
printf("Current depth:\t%d\n", video_pic.depth);
close(fd);
return 0;
}
I've got the next errors:
cam_info: Can't get capabilities: Inappropriate ioctl for device
cam_info: Can't get window information: Inappropriate ioctl for device
cam_info: Can't get picture information: Inappropriate ioctl for device
If I'm checking through command line for instance I can get the capabilities without issues running:
v4l2-ctl --device-/dev/video0 --list-formats-ext
Any ideas how can this be done?
Thanks in advance.
I don't know if this specifically answers your question, but you can get useful information by globbing certain patterns under /dev or /sys, for example this will return the full device path (including PCI bus) of each video device,
#include <glob.h>
#include <unistd.h>
void list_videos() {
int i;
glob_t globbuf;
if (glob("/sys/class/video4linux/video*", 0, NULL, &globbuf) != 0) {
perror("glob");
return;
}
for (i=0; i < globbuf.gl_pathc; i++) {
char buf[256] = {};
if (readlink(globbuf.gl_pathv[i], buf, sizeof(buf)-1) > 0) {
puts(buf);
}
}
}
On one system with 2 cameras this prints,
../../devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1.1/2-1.1:1.0/video4linux/video0
../../devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3:1.0/video4linux/video1
Other interesting glob strings include /dev/v4l/by-id/* and /dev/v4l/by-path/*.
I need to transfer data to BeagleBone Black via Modbus RTU using Rs485. To work with Modbus RTU,but I don't know how to toggle rts in rs-485.HELP
Modbus RTU data transmission code
how to add RS485 code to this,to use the Modbus library libmodbus
#include "modbus-rtu.h"
#include <stdio.h>
#include <errno.h>
int main(){
int connected;
modbus_t *ctx;
uint16_t tab_reg[64];
int rc;
int i;
ctx = modbus_new_rtu("/dev/ttyS4", 9600, 'N', 8, 1);
if(ctx == NULL) {
fprintf(stderr, "Unable to create the libmodbus context\n");
}
else {
modbus_set_slave(ctx, 1);
modbus_set_debug(ctx, TRUE);
connected = modbus_connect(ctx);
printf("modbus_set_slave return: %d\n", rc);
if (rc != 0)
{
printf("modbus_set_slave: %s \n"modbus_strerror(errno));
}
rc = modbus_read_registers(ctx, 0, 3, tab_reg);
for (i = 0; i < rc; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
if(rc == -1)
{
fprintf(stderr, "%s\n", modbus_strerror(errno));
}
modbus_close(ctx);
modbus_free(ctx);
}
return 0;
}
First I would check if your hardware support automatic (hardware) half-duplex direction control.
If not, then you can take a look at this answer. In there you have all the details you need to compile and install libmodbus with support for toggling the line with software.
I'm using this solution in my RPi and CHIP computers but you should be able to use it right away on your BBB. You might find a small caveat if the GPIO file name has a 3 or 4-digit number (take a look in /sys/class/gpio). If that's the case, take a look here, I had to modify the code to correct that problem.
I want to implement a specific functionality to my project which includes continuously playing a sample-default.wav in the background and play a sample-specific.wav file when some specific condition matches. What I really want is that, when sample-specific.wav file is running, volume of sample-default.wav file becomes 0 (or simply, I want to mute sample-default.wav file when sample-specific.wav is running).
I am trying to implement this functionality using alsa-library for c. I have tried almost every approach to achieve this but nothing seems to works for me.
My current approach
I am trying to add two virtual sound devices using dmix plugin of alsa leaving default for system sounds. I searched google and find that I need to edit /etc/asound.conf file for creating different sound devices.
I added two sound devices, named notification and sample-sound. My current /etc/asound.conf file looks something like the one below:-
pcm.notification {
type dmix
ipc_key 1024
slave {
pcm "hw:1,0"
}
}
ctl.notification {
type hw
card 2
}
pcm.sample-sound {
type dmix
ipc_key 1025
slave {
pcm "hw:1,0"
}
}
ctl.sample-sound {
type hw
card 3
}
This works perfectly fine with aplay i.e. when I am playing sample-default.wav file using aplay by the following command:-
aplay -D plug:notification sample-default.wav
It works, but when i am trying to run the following code to play sample-default.wav using alsa library on my notification device:-
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#include <pthread.h>
void default_sound (char * str) {
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
snd_pcm_uframes_t frames;
/* Open PCM device for playback */
int status = snd_pcm_open(&handle, "notification", SND_PCM_STREAM_PLAYBACK, 0);
if (status < 0) {
printf("Unable to open pcm deveice%s\n", snd_strerror(status));
return;
}
/* Allocate a hardware parameter obejct */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it with default values */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
/* Single Channel (mono) */
snd_pcm_hw_params_set_channels(handle, params, 1);
/* sampling rate */
unsigned int sample_rate = 16000;
int dir;
snd_pcm_hw_params_set_rate_near(handle, params, &sample_rate, &dir);
/* set period size to 32 frames */
frames = 32;
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
/* Write the parameters to the driver */
status = snd_pcm_hw_params(handle, params);
if(status < 0) {
printf("Unable to set hw params: %s\n", snd_strerror(status));
return;
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
int size = frames * 2;
char *buffer = (char *)malloc(size);
int readfd = open("sample-call.wav", O_RDONLY);
if(readfd < 0) {
printf("Error in opening wav file\n");
exit(1);
}
int readval;
while(readval = read(readfd, buffer, size) > 0) {
status = snd_pcm_writei(handle, buffer, frames);
if(status == -EPIPE) {
printf("underrun occured\n");
snd_pcm_prepare(handle);
}
else if(status < 0) {
printf("Error from writei: %s\n", snd_strerror(status));
}
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
}
int main() {
pthread_t pthread_id;
int status = pthread_create(&pthread_id, NULL, default_sound, "running");
if (status != 0) {
printf("Error in creating thread\n");
}
pthread_join(pthread_id, NULL);
return 0;
}
It compiles successfully but throws run-time error :-
8211 segmentation fault (core dumped) ./play-multiple-sound
I don't know what's going wrong with the above code.
If the above code works fine then I will play two sound files on two devices (notification and sample-sound) and control the volume of these devices using the alsa-mixer library which I have already implemented.
I am trying to achieve this from the past few weeks and none of the solution seems to work for me, so please help me out with this and if you know a better approach then please suggest.
I'm looking for a way to get hold of network stats in C on Linux and MacOSX. Specifically, I need to monitor the number of bytes uploaded and downloaded from each network adapter on the system - I don't need to do packet inspection, or differentiate between protocols, just a 'total bytes' counter which I can poll at intervals would be fine. In Windows I can do this using the iphlpapi.dll library via GetIfTable (to list the network adapters) and GetIfEntry (to read the stats), but I can't find the Linux/OSX equivalents. My knowledge of C is fairly basic so I would appreciate a solution that isn't too involved. Any help would be much appreciated!
The Darwin netstat source code uses sysctl.
Here's some code that prints the number of bytes in and out on OSX:
#import <Foundation/Foundation.h>
#include <sys/sysctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/route.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int mib[] = {
CTL_NET,
PF_ROUTE,
0,
0,
NET_RT_IFLIST2,
0
};
size_t len;
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
fprintf(stderr, "sysctl: %s\n", strerror(errno));
exit(1);
}
char *buf = (char *)malloc(len);
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
fprintf(stderr, "sysctl: %s\n", strerror(errno));
exit(1);
}
char *lim = buf + len;
char *next = NULL;
u_int64_t totalibytes = 0;
u_int64_t totalobytes = 0;
for (next = buf; next < lim; ) {
struct if_msghdr *ifm = (struct if_msghdr *)next;
next += ifm->ifm_msglen;
if (ifm->ifm_type == RTM_IFINFO2) {
struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
totalibytes += if2m->ifm_data.ifi_ibytes;
totalobytes += if2m->ifm_data.ifi_obytes;
}
}
printf("total ibytes %qu\tobytes %qu\n", totalibytes, totalobytes);
[pool drain];
return 0;
}
I can't speak to OSX but on linux take a look at /proc/net/dev.
If you do 'cat /proc/net/dev' you should see statistics including 'bytes' - the total number of bytes of data transmitted or received by the interface. You can read the file within your own program.
EDIT:
I didn't read your whole question. This article should help you get started with /proc and has a section on /proc/net/dev.
Also, to list the interfaces you can call ioctl with the SIOCGIFCONF option. You can Google for a decent code example on how to loop through the returned data. Or you can simply pull it out of the /proc.net/dev data mentioned above, which should be easier.
on Linux:
low level: check /sys/class/net/eth0/statistics/
slightly higher level: ip -s link show eth0
graphical: iftop
interactive: iptraf