分类: LINUX
2012-04-06 17:13:33
linux 下 列出所有alsa设备代码
static void device_list(void)
{
snd_ctl_t *handle;
int card,
err, dev, idx;
snd_ctl_card_info_t *info;
snd_pcm_info_t
*pcminfo;
snd_ctl_card_info_alloca(&info);
snd_pcm_info_alloca(&pcminfo);
card = -1;
if
(snd_card_next(&card) < 0 || card < 0) {
error(_("no
soundcards found..."));
return;
}
printf(_("**** List
of %s Hardware Devices ****\n"),
snd_pcm_stream_name(stream));
while (card >= 0) {
char
name[32];
sprintf(name, "hw:%d", card);
if ((err =
snd_ctl_open(&handle, name, 0)) < 0) {
error("control open
(%i): %s", card, snd_strerror(err));
goto next_card;
}
if ((err = snd_ctl_card_info(handle, info)) < 0) {
error("control hardware info (%i): %s", card, snd_strerror(err));
snd_ctl_close(handle);
goto next_card;
}
dev = -1;
while (1) {
unsigned int count;
if (snd_ctl_pcm_next_device(handle, &dev)<0)
error("snd_ctl_pcm_next_device");
if (dev < 0)
break;
snd_pcm_info_set_device(pcminfo, dev);
snd_pcm_info_set_subdevice(pcminfo, 0);
snd_pcm_info_set_stream(pcminfo, stream);
if ((err =
snd_ctl_pcm_info(handle, pcminfo)) < 0) {
if (err !=
-ENOENT)
error("control digital audio info (%i): %s",
card, snd_strerror(err));
continue;
}
printf(_("card %i: %s [%s], device %i: %s [%s]\n"),
card, snd_ctl_card_info_get_id(info), snd_ctl_card_info_get_name(info),
dev,
snd_pcm_info_get_id(pcminfo),
snd_pcm_info_get_name(pcminfo));
count =
snd_pcm_info_get_subdevices_count(pcminfo);
printf( _("
Subdevices: %i/%i\n"),
snd_pcm_info_get_subdevices_avail(pcminfo), count);
for (idx =
0; idx < (int)count; idx++) {
snd_pcm_info_set_subdevice(pcminfo, idx);
if ((err =
snd_ctl_pcm_info(handle, pcminfo)) < 0) {
error("control digital audio playback info (%i): %s", card,
snd_strerror(err));
} else {
printf(_(" Subdevice #%i: %s\n"),
idx,
snd_pcm_info_get_subdevice_name(pcminfo));
}
}
}
snd_ctl_close(handle);
next_card:
if (snd_card_next(&card) < 0) {
error("snd_card_next");
break;
}
}
}
linux下ALSA播放声音的源程序
#include
/* Use the newer ALSA API */
#define
ALSA_PCM_NEW_HW_PARAMS_API
#include
int
main()
{
long loops;
int rc;
int size;
snd_pcm_t
*handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int
dir;
snd_pcm_uframes_t frames;
snd_pcm_uframes_t periodsize;
char *buffer;
FILE *fp = fopen("play.wav", "rb");
if(fp ==
NULL)
return 0;
fseek(fp, 100, SEEK_SET);
/* Open PCM
device for playback. */
rc = snd_pcm_open(&handle, "default",
SND_PCM_STREAM_PLAYBACK, 0);//SND_PCM_NONBLOCK);
if (rc
< 0) {
fprintf(stderr,
"unable to open pcm device:
%s\n",
snd_strerror(rc));
exit(1);
}
/*
Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it in 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);
/* Two channels
(stereo) */
snd_pcm_hw_params_set_channels(handle, params, 1);
/* 44100 bits/second sampling rate (CD quality) */
val = 8000;
snd_pcm_hw_params_set_rate_near(handle, params,
&val, &dir);
/* Set period size to
32 frames. */
frames = 32;
periodsize = frames * 2;
rc =
snd_pcm_hw_params_set_buffer_size_near(handle, params, &periodsize);
if (rc < 0)
{
printf("Unable to set buffer size %li :
%s\n", frames * 2, snd_strerror(rc));
}
periodsize /= 2;
rc = snd_pcm_hw_params_set_period_size_near(handle,
params, &periodsize, 0);
if (rc < 0)
{
printf("Unable to set period size %li : %s\n", periodsize,
snd_strerror(rc));
}
/* Write the parameters to the driver
*/
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr,
"unable to set hw parameters: %s\n",
snd_strerror(rc));
}
/* Use a buffer large enough to hold
one period */
snd_pcm_hw_params_get_period_size(params, &frames,
&dir);
size = frames * 2; /* 2
bytes/sample, 2 channels */
buffer = (char *) malloc(size);
fprintf(stderr,
"size = %d\n",
size);
/*
We want to loop for 5 seconds */
//snd_pcm_hw_params_get_period_time(params,
//
&val, &dir);
//snd_pcm_start(handle);
while (1)
{
rc =
fread(buffer, 1, size, fp);
if(rc == 0)
{
fprintf(stderr, "end of file on input\n");
break;
}
else if (rc != size)
{
}
while(rc = snd_pcm_writei(handle, buffer, frames)<0)
{
usleep(2000);
if (rc == -EPIPE)
{
/* EPIPE means underrun */
fprintf(stderr,
"underrun occurred\n");
snd_pcm_prepare(handle);
}
else if (rc < 0)
{
fprintf(stderr,
"error from writei: %s\n",
snd_strerror(rc));
}
}
//snd_pcm_drain(handle);
//usleep(7000);
//printf("#\n");
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
fclose(fp);
return
0;
}
linux下ALSA录制声音的源程序
/* Use the newer ALSA API */
#define
ALSA_PCM_NEW_HW_PARAMS_API
#include
/*
this buffer holds the digitized audio */
//unsigned char
buf[LENGTH*RATE*SIZE*CHANNELS/8];
typedef unsigned char BYTE;
typedef
unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned int
FOURCC; /* a four character code */
/* flags for 'wFormatTag' field of
WAVEFORMAT */
#define WAVE_FORMAT_PCM 1
/* MMIO macros */
#define
mmioFOURCC(ch0, ch1, ch2, ch3) \
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1)
<< 8) | \
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3)
<< 24))
#define FOURCC_RIFF mmioFOURCC ('R', 'I', 'F',
'F')
#define FOURCC_LIST mmioFOURCC ('L', 'I', 'S', 'T')
#define
FOURCC_WAVE mmioFOURCC ('W', 'A', 'V', 'E')
#define FOURCC_FMT
mmioFOURCC ('f', 'm', 't', ' ')
#define FOURCC_DATA mmioFOURCC ('d', 'a',
't', 'a')
typedef struct CHUNKHDR {
FOURCC ckid; /* chunk
ID */
DWORD dwSize; /* chunk size */
} CHUNKHDR;
/*
simplified Header for standard WAV files */
typedef struct WAVEHDR {
CHUNKHDR chkRiff;
FOURCC fccWave;
CHUNKHDR chkFmt;
WORD
wFormatTag; /* format type */
WORD nChannels; /* number of
channels (i.e. mono, stereo, etc.) */
DWORD nSamplesPerSec; /* sample
rate */
DWORD nAvgBytesPerSec; /* for buffer estimation */
WORD
nBlockAlign; /* block size of data */
WORD wBitsPerSample;
CHUNKHDR chkData;
} WAVEHDR;
#if BYTE_ORDER == BIG_ENDIAN
# define
cpu_to_le32(x) SWAP4((x))
# define cpu_to_le16(x) SWAP2((x))
# define
le32_to_cpu(x) SWAP4((x))
# define le16_to_cpu(x) SWAP2((x))
#else
#
define cpu_to_le32(x) (x)
# define cpu_to_le16(x) (x)
# define
le32_to_cpu(x) (x)
# define le16_to_cpu(x) (x)
#endif
static void
wav_init_header(WAVEHDR *fileheader)
{
/* stolen from cdda2wav
*/
int nBitsPerSample = 16;
int channels = 1;
int
rate = 8000;
unsigned long nBlockAlign = channels *
((nBitsPerSample + 7) / 8);
unsigned long nAvgBytesPerSec = nBlockAlign *
rate;
unsigned long temp = /* data length */ 0 +
sizeof(WAVEHDR) -
sizeof(CHUNKHDR);
fileheader->chkRiff.ckid =
cpu_to_le32(FOURCC_RIFF);
fileheader->fccWave =
cpu_to_le32(FOURCC_WAVE);
fileheader->chkFmt.ckid =
cpu_to_le32(FOURCC_FMT);
fileheader->chkFmt.dwSize =
cpu_to_le32(16);
fileheader->wFormatTag =
cpu_to_le16(WAVE_FORMAT_PCM);
fileheader->nChannels =
cpu_to_le16(channels);
fileheader->nSamplesPerSec =
cpu_to_le32(rate);
fileheader->nAvgBytesPerSec =
cpu_to_le32(nAvgBytesPerSec);
fileheader->nBlockAlign =
cpu_to_le16(nBlockAlign);
fileheader->wBitsPerSample =
cpu_to_le16(nBitsPerSample);
fileheader->chkData.ckid =
cpu_to_le32(FOURCC_DATA);
fileheader->chkRiff.dwSize =
cpu_to_le32(temp);
fileheader->chkData.dwSize = cpu_to_le32(0 /* data
length */);
}
static void wav_start_write(FILE* fd, WAVEHDR
*fileheader)
{
wav_init_header(fileheader);
fwrite(fileheader,1, sizeof(WAVEHDR), fd);
}
static void
wav_stop_write(FILE* fd, WAVEHDR *fileheader, int wav_size)
{
unsigned
long temp = wav_size + sizeof(WAVEHDR) - sizeof(CHUNKHDR);
fileheader->chkRiff.dwSize = cpu_to_le32(temp);
fileheader->chkData.dwSize = cpu_to_le32(wav_size);
fseek(fd,0,SEEK_SET);
fwrite(fileheader,1, sizeof(WAVEHDR),
fd);
}
int main()
{
long loops;
int rc;
int
size;
snd_pcm_t *rec_handle;
snd_pcm_hw_params_t
*rec_params;
unsigned int val;
int dir;
snd_pcm_uframes_t
frames;
char *buffer;
WAVEHDR wavheader;
int total_len =
0;
FILE *fp_rec = fopen("rec.wav", "wb");
if(fp_rec==NULL)
{
return 0;
}
wav_start_write(fp_rec,
&wavheader);
/* Open PCM device for recording (capture). */
rc
= snd_pcm_open(&rec_handle, "default",
SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) {
fprintf(stderr,
"unable to open pcm device: %s\n",
snd_strerror(rc));
exit(1);
}
/* Allocate
a hardware parameters object. */
snd_pcm_hw_params_alloca(&rec_params);
/* Fill it in with
default values. */
snd_pcm_hw_params_any(rec_handle,
rec_params);
/* Set the desired hardware parameters. */
/*
Interleaved mode */
snd_pcm_hw_params_set_access(rec_handle,
rec_params,
SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format
*/
snd_pcm_hw_params_set_format(rec_handle, rec_params,
SND_PCM_FORMAT_S16_LE);
/* Two channels
(stereo) */
snd_pcm_hw_params_set_channels(rec_handle, rec_params,
1);
/* 44100 bits/second sampling rate (CD quality) */
val =
8000;
snd_pcm_hw_params_set_rate_near(rec_handle, rec_params,
&val, &dir);
/* Set period
size to 32 frames. */
frames = 32;
snd_pcm_hw_params_set_period_size_near(rec_handle,
rec_params, &frames, &dir);
/*
Write the parameters to the driver */
rc = snd_pcm_hw_params(rec_handle,
rec_params);
if (rc < 0)
{
fprintf(stderr,
"unable to set hw parameters: %s\n",
snd_strerror(rc));
exit(1);
}
/* Use a buffer large
enough to hold one period */
snd_pcm_hw_params_get_period_size(rec_params, &frames, &dir);
size = frames * 2; /* 2 bytes/sample, 2 channels */
buffer = (char *)
malloc(size);
/* We want to loop for 5 seconds */
snd_pcm_hw_params_get_period_time(rec_params, &val, &dir);
loops
= 2000;
while (loops-- > 0)
{
rc =
snd_pcm_readi(rec_handle, buffer, frames);
if (rc == -EPIPE)
{
/* EPIPE means overrun */
fprintf(stderr, "overrun occurred\n");
snd_pcm_prepare(rec_handle);
}
else if (rc < 0)
{
fprintf(stderr, "error from read: %s\n",
snd_strerror(rc));
}
else if (rc != (int)frames)
{
fprintf(stderr, "short read, read %d frames\n", rc);
}
rc = fwrite(buffer, 1, size, fp_rec);
total_len +=
size;
printf("#\n");
if (rc != size)
fprintf(stderr,"short write: wrote %d bytes\n", rc);
}
wav_stop_write(fp_rec, &wavheader, total_len);
snd_pcm_drain(rec_handle);
snd_pcm_close(rec_handle);
free(buffer);
fclose(fp_rec);
return 0;
}