Introduction to Sound Programming with ALSA
1. 打印alsa中的类型及格式
Listing 1. Display Some PCM Types and Formats
#include "utils.h"
#include <alsa/asoundlib.h>
#include <stdlib.h>
int main ( int argc, char *argv[] )
{
int i;
printf("<----- 1="" -----="">ALSA library version=%s\n", SND_LIB_VERSION_STR);
printf("\n<----- 2="" -----="">PCM stream types:\n");
for(i=0; i<=SND_PCM_STREAM_LAST; i++)
printf("%s\n", snd_pcm_stream_name((snd_pcm_stream_t)i));
printf("\n<----- 3="" -----="">PCM access type:\n");
for(i=0; i<=SND_PCM_ACCESS_LAST; i++)
printf("%s\n", snd_pcm_access_name((snd_pcm_access_t)i));
printf("\n<----- 4="" -----="">PCM formats:\n");
for(i=0; i<=SND_PCM_FORMAT_LAST; i++)
{
if(NULL != snd_pcm_format_name((snd_pcm_format_t)i))
{
printf("%s:%s\n", snd_pcm_format_name((snd_pcm_format_t)i),
snd_pcm_format_description((snd_pcm_format_t)i));
}
}
printf("\n<----- 5="" -----="">PCM subformats:\n");
for(i=0; i<=SND_PCM_SUBFORMAT_LAST; i++)
{
printf("%s:%s\n", snd_pcm_subformat_name((snd_pcm_subformat_t)i),
snd_pcm_subformat_description((snd_pcm_subformat_t)i));
}
printf("\n<----- 6="" -----="">PCM state:\n");
for(i=0; i<=SND_PCM_STATE_LAST; i++)
{
printf("%s\n", snd_pcm_state_name((snd_pcm_state_t)i));
}
return EXIT_SUCCESS;
}
Makefile
EXE=start
CC=gcc
ALSA_PATH=/work/ffmpeg/test/alsa/alsa-lib-1.0.23/_install/
RESOURCE=/work/ffmpeg/test/resource/
CFLAGS=-g -O0
CFLAGS += -I$(ALSA_PATH)/include
LDFLAGS += -L$(ALSA_PATH)/lib/ -lrt -lasound -lm -ldl -lpthread
SRC=$(wildcard *.c)
OBJ=$(patsubst %.c,%.o,$(SRC))
DEP=$(patsubst %.c,.%.d,$(SRC))
$(EXE):$(OBJ)
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
$(DEP):.%.d:%.c
@set -e; rm -f $@; \
$(CC) -MM $< > $@.$$$$; \
sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
-include $(DEP)
clean:
@rm $(EXE) $(OBJ) $(DEP) -f
run:
export LD_LIBRARY_PATH=$(FFMPEG)/lib/ \
&& ./$(EXE) $(RESOURCE)/test.wav
#&& ./$(EXE) ../resource/test.wmv
二. param
#include "utils.h"
#include <alsa/asoundlib.h>
#include <stdlib.h>
int main ( int argc, char *argv[] )
{
int i;
int ret;
int dir;
unsigned int val, val2;
snd_pcm_t* handle;
snd_pcm_hw_params_t* params;
//1. open
if( (ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0)
{
dbmsg("open pcm device error:%s", snd_strerror(ret));
return -1;
}
//2. alloc and init param
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(handle, params);
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(handle, params, 2);
val = 44100;
snd_pcm_hw_params_set_rate_near(handle,params, &val, &dir);
//3. set param to driver
if((ret=snd_pcm_hw_params(handle, params)) < 0)
{
dbmsg("set hw params error:%s", snd_strerror(ret));
return -1;
}
printf("PCM handle name=%s\n", snd_pcm_name(handle));
printf("PCM state=%s\n", snd_pcm_state_name(snd_pcm_state(handle)));
snd_pcm_hw_params_get_access(params, (snd_pcm_access_t*)&val);
printf("access type=%s\n",snd_pcm_access_name((snd_pcm_access_t)val));
snd_pcm_hw_params_get_format(params, &val);
printf("format=%s (%s)\n",snd_pcm_format_name((snd_pcm_format_t)val),
snd_pcm_format_description((snd_pcm_format_t)val));
snd_pcm_close(handle);
return EXIT_SUCCESS;
}
三.play sound
3.1
#include "utils.h"
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include <stdlib.h>
int main ( int argc, char *argv[] )
{
int i;
int ret, dir, size;
long loops;
unsigned int val, val2;
char* buffer;
snd_pcm_t* handle;
snd_pcm_hw_params_t* params;
snd_pcm_uframes_t frames;
//1. open
if( (ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0)
{
dbmsg("open pcm device error:%s", snd_strerror(ret));
return -1;
}
//2. alloc and init param
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(handle, params);
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(handle, params, 2);
val = 44100;
snd_pcm_hw_params_set_rate_near(handle,params, &val, &dir);
frames = 32;
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
//3. set param to driver
if((ret=snd_pcm_hw_params(handle, params)) < 0)
{
dbmsg("set hw params error:%s", snd_strerror(ret));
return -1;
}
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
size = frames*4; //2byte/smaple, 2 channels
buffer = (char*)malloc(size);
snd_pcm_hw_params_get_period_time(params, &val, &dir);
loops = 5000000/val;
dbmsg("next in loop,loops=%ld,val=%d",loops, val);
while(loops>0)
{
loops --;
ret = read(0, buffer, size);
dbmsg("ret =%d", ret);
if(ret==0)
{
dbmsg("end of file");
return 0;
}else if (ret!=size)
{
dbmsg("short read");
}
ret = snd_pcm_writei(handle, buffer, frames);
if(ret == -EPIPE)
{
dbmsg("-EPIPE");
snd_pcm_prepare(handle);
}
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return EXIT_SUCCESS;
}
运行
cong@msi:/work/ffmpeg/test/alsa/testalsa/3play$ ./play < /dev/urandom