⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recordapi.c

📁 自己写的
💻 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(&params);
	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 + -