📄 recordapi.c
字号:
#include "recordAPI.h"
#include "formats.h"
//static char *command;
static snd_pcm_t *handle=0;
static struct
{
snd_pcm_format_t format;
unsigned int channels;
unsigned int rate;
} hwparams, rhwparams;
//static int timelimit = 0;
//static int quiet_mode = 0;
//static int file_type = FORMAT_DEFAULT;
//static unsigned int sleep_min = 0;
//static int open_mode = 0;
//static snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;//using
//static int mmap_flag = 0;
//static int interleaved = 1;
//static int nonblock = 0;
//static u_char *audiobuf = NULL;
static snd_pcm_uframes_t chunk_size = 0;
static unsigned period_time = 0;
static unsigned buffer_time = 0;
static snd_pcm_uframes_t period_frames = 0;
static snd_pcm_uframes_t buffer_frames = 0;
//static int avail_min = -1;
//static int start_delay = 0;
//static int stop_delay = 0;
//static int verbose = 0;
//static int buffer_pos = 0;
static size_t bits_per_sample, bits_per_frame;
//static size_t chunk_bytes;
//static snd_output_t *log;
//static int fd = -1;
//static off64_t pbrec_count = LLONG_MAX, fdcount;
//static int vocmajor, vocminor;
int AAI_record_open(char *pcm_name)
{
//initialize the driver
snd_pcm_info_t *info;
int err;
//file_type = FORMAT_WAVE;
//command = "arecord";
//start_delay = 1;
snd_pcm_info_alloca(&info);
err = snd_pcm_open(&handle, pcm_name, SND_PCM_STREAM_CAPTURE, 0 );
if (err < 0)
{
printf("open handle error!!\n");
return 1;
}
if ((err = snd_pcm_info(handle, info)) < 0)
return 1;
chunk_size = 1024;
hwparams = rhwparams;
return 0;
}
//void AAI_set_params(void)
void AAI_set_params(int sampleRate,int channels,int bitPersample)
{
snd_pcm_hw_params_t *params;
snd_pcm_sw_params_t *swparams;
snd_pcm_uframes_t buffer_size;
int err;
size_t n;
snd_pcm_uframes_t xfer_align;
unsigned int rate;
snd_pcm_uframes_t start_threshold = 0, stop_threshold = 0;
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_sw_params_alloca(&swparams);
err = snd_pcm_hw_params_any(handle, params);
if (err < 0) {
//error(_("Broken configuration for this PCM: no configurations available"));
//exit(EXIT_FAILURE);
printf("setparams error\n");
exit(0);
}
//if (mmap_flag) {
// snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());
// snd_pcm_access_mask_none(mask);
// snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
// snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
// snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
// err = snd_pcm_hw_params_set_access_mask(handle, params, mask);
//} else if (interleaved)
// err = snd_pcm_hw_params_set_access(handle, params,SND_PCM_ACCESS_RW_INTERLEAVED);
//else
// err = snd_pcm_hw_params_set_access(handle, params,SND_PCM_ACCESS_RW_NONINTERLEAVED);
// initilize some variables;
hwparams.rate = sampleRate;
hwparams.channels = channels;
hwparams.format = SND_PCM_FORMAT_S16_LE;//SND_PCM_FORMAT_S16_LE
printf("rate=%d channel=%d format=%d\n",sampleRate,channels,SND_PCM_FORMAT_S16_LE);
err = snd_pcm_hw_params_set_access(handle, params,SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0)
{
printf("setparams error\n");
//error(_("Access type not available"));
//exit(EXIT_FAILURE);
exit(0);
}
err = snd_pcm_hw_params_set_format(handle, params, hwparams.format);
if (err < 0) {
printf("setparams error\n");
//error(_("Sample format non available"));
//exit(EXIT_FAILURE);
exit(0);
}
err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);
if (err < 0) {
printf("setparams error\n");
//error(_("Channels count non available"));
//exit(EXIT_FAILURE);
exit(0);
}
rate = hwparams.rate;
err = snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0);
if (err < 0) {
printf("setparams error\n");
//error(_("Channels count non available"));
//exit(EXIT_FAILURE);
exit(0);
}
assert(err >= 0);
//confirm the rate in the required range;
/*
if ((float)rate * 1.05 < hwparams.rate || (float)rate * 0.95 > hwparams.rate)
{
if (!quiet_mode)
{
char plugex[64];
const char *pcmname = snd_pcm_name(handle);
fprintf(stderr, "Warning: rate is not accurate (requested = %iHz, got = %iHz)\n", rate, hwparams.rate);
if (! pcmname || strchr(snd_pcm_name(handle), ':'))
*plugex = 0;
else
snprintf(plugex, sizeof(plugex), "(-Dplug:%s)",snd_pcm_name(handle));
//fprintf(stderr, _("please, try the plug plugin %s\n"),plugex);
}
}
*/
rate = hwparams.rate;
err = snd_pcm_hw_params_get_buffer_time_max(params,&buffer_time, 0);
if (err < 0) {
printf("setparams error\n");
//error(_("Channels count non available"));
//exit(EXIT_FAILURE);
exit(0);
}
assert(err >= 0);
if (buffer_time > 500000)
buffer_time = 500000;
//if (buffer_time == 0 && buffer_frames == 0)
//{
// err = snd_pcm_hw_params_get_buffer_time_max(params,&buffer_time, 0);
// assert(err >= 0);
// if (buffer_time > 500000)
// buffer_time = 500000;
//}
if (period_time == 0 && period_frames == 0)
{
if (buffer_time > 0)
period_time = buffer_time / 4;
else
period_frames = buffer_frames / 4;
}
if (period_time > 0)
err = snd_pcm_hw_params_set_period_time_near(handle, params,&period_time, 0);
else
err = snd_pcm_hw_params_set_period_size_near(handle, params,&period_frames, 0);
assert(err >= 0);
if (err < 0) {
printf("setparams error\n");
//error(_("Channels count non available"));
//exit(EXIT_FAILURE);
exit(0);
}
if (buffer_time > 0)
err = snd_pcm_hw_params_set_buffer_time_near(handle, params,&buffer_time, 0);
else
err = snd_pcm_hw_params_set_buffer_size_near(handle, params,&buffer_frames);
if (err < 0) {
printf("setparams error\n");
//error(_("Channels count non available"));
//exit(EXIT_FAILURE);
exit(0);
}
assert(err >= 0);
err = snd_pcm_hw_params(handle, params);
if (err < 0)
{
//error(_("Unable to install hw params:"));
printf("Unable to install hw params:\n");
//snd_pcm_hw_params_dump(params, log);
//exit(EXIT_FAILURE);
exit(0);
}
snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
printf("\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ chunk_size = %d \n",chunk_size);
if (chunk_size == buffer_size)
{
printf("setparams error\n");
//error(_("Can't use period equal to buffer size (%lu == %lu)"),chunk_size, buffer_size);
//exit(EXIT_FAILURE);
exit(0);
}
snd_pcm_sw_params_current(handle, swparams);
err = snd_pcm_sw_params_get_xfer_align(swparams, &xfer_align);
if (err < 0)
{
printf("setparams error\n");
//error(_("Unable to obtain xfer align\n"));
//exit(EXIT_FAILURE);
exit(0);
}
//if (sleep_min)
// xfer_align = 1;
//err = snd_pcm_sw_params_set_sleep_min(handle, swparams,sleep_min);
err = snd_pcm_sw_params_set_sleep_min(handle, swparams,0);
assert(err >= 0);
//if (avail_min < 0)
// n = chunk_size;
//else
// n = (double) rate * avail_min / 1000000;
n = chunk_size;
err = snd_pcm_sw_params_set_avail_min(handle, swparams, n);
/* round up to closest transfer boundary */
n = (buffer_size / xfer_align) * xfer_align;
//if (start_delay <= 0)
// start_threshold = n + (double) rate * start_delay / 1000000;
//else
// start_threshold = (double) rate * start_delay / 1000000;
start_threshold = 1;
if (start_threshold < 1)
start_threshold = 1;
if (start_threshold > n)
start_threshold = n;
err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
assert(err >= 0);
//if (stop_delay <= 0)
// stop_threshold = buffer_size + (double) rate * stop_delay / 1000000;
//else
// stop_threshold = (double) rate * stop_delay / 1000000;
stop_threshold = buffer_size;
err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
printf("start_threshold =%d stop_threshold=%d\n",start_threshold,stop_threshold);
assert(err >= 0);
err = snd_pcm_sw_params_set_xfer_align(handle, swparams, xfer_align);
assert(err >= 0);
if (snd_pcm_sw_params(handle, swparams) < 0) {
//error(_("unable to install sw params:"));
//snd_pcm_sw_params_dump(swparams, log);
//exit(EXIT_FAILURE);
printf("setparams error\n");
exit(0);
}
//if (verbose)
// snd_pcm_dump(handle, log);
bits_per_sample = snd_pcm_format_physical_width(hwparams.format);
bits_per_frame = bits_per_sample * hwparams.channels;
//chunk_bytes = chunk_size * bits_per_frame / 8;
//audiobuf = realloc(audiobuf, chunk_bytes);
//if (audiobuf == NULL) {
// error(_("not enough memory"));
// exit(EXIT_FAILURE);
//}
// fprintf(stderr, "real chunk_size = %i, frags = %i, total = %i\n", chunk_size, setup.buf.block.frags, setup.buf.block.frags * chunk_size);
}
/* I/O error handler */
static void record_xrun(void)
{
snd_pcm_status_t *status;
int res;
snd_pcm_status_alloca(&status);
if ((res = snd_pcm_status(handle, status))<0)
exit(0);
if(snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN)
{
printf("overrun!!!!!\n");
if ((res = snd_pcm_prepare(handle))<0)
exit(0);
return; /* ok, data should be accepted again */
}
if(snd_pcm_status_get_state(status) == SND_PCM_STATE_DRAINING)
{
//if (stream == SND_PCM_STREAM_CAPTURE)
{
if ((res = snd_pcm_prepare(handle))<0)
exit(0);
return;
}
}
exit(0);
}
/* I/O suspend handler */
static void record_suspend(void)
{
int i = 0;
int res;
while ((res = snd_pcm_resume(handle)) == -EAGAIN)
{
sleep(1); /* wait until suspend flag is released */
printf("record_suspend!!!\n");
i++;
if(i>100)
break;
}
if (res < 0)
{
if ((res = snd_pcm_prepare(handle)) < 0)
exit(0);
}
}
//chunk_size init in set_params
long AAI_pcm_read(char *data, long rcount)
{
ssize_t r;
size_t result = 0;
size_t count = rcount;
printf("chunk_size =%d\n",chunk_size);
//if (count != chunk_size)
//{
// count = chunk_size;
//}
//printf("#####AAI_pcm_read count=%d chunk_size=%d\n",count,chunk_size);
while (count > 0)
{
printf("count =%d\n",count);
r = snd_pcm_readi(handle, data, count);
printf("r =%d count =%d EAGAIN=%d,EPIPE=%d,ESTRPIPE=%d \n",r,count,EAGAIN,EPIPE,ESTRPIPE);
if (r == -EAGAIN || (r >= 0 && (size_t)r < count))
{
printf("before snd_pcm_wait\n");
snd_pcm_wait(handle, 1000);
printf("after snd_pcm_wait\n");
}
else if (r == -EPIPE)
{
printf("before xrun\n");
record_xrun();
printf("after xrun\n");
}
else if (r == -ESTRPIPE)
{
printf("before suspend\n");
record_suspend();
printf("after suspend\n");
}
else if (r < 0)
{
printf("read error:read data from driver error!\n");
exit(0);
}
if (r > 0)
{
result += r;
count -= r;
data += r * bits_per_frame / 8;
}
}
return rcount;
}
void AAI_record_close()
{
if(handle!=0)
{
snd_pcm_close(handle);
handle = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -