#include#include#include#include#include//#include "stdio.h"#include "wb_vad.h"#include#includeusing namespace std;// 用于存储语言块的信息class BlockInfo{ public: bool valid;// 是否有效语音 char* p;// 语音块的首地址 int len;// 语言块的大小 public: BlockInfo() { valid = false; p = NULL; len = 0; } ~BlockInfo() { if(NULL == p) return; delete p; } void set(char* ptr, int length) { p = ptr; valid = true; len = length; }};queueglobal_full;queueglobal_valid;int flag = 0; // 当前录音是停止的int irstart = 0;// 判断是否重启char filename[1024] = "0";void vad(char* ptr, int size){ int valitSize = 0;// 有效数据长度 int totalCount = size/512 + (size % 512) > 0 ? 1 : 0;// 总数据块 数量 int useTotalCount = 1;// 使用过的数据块 数量 int i, temp; float indata[FRAME_LEN]; VadVars *vadstate; wb_vad_init(&(vadstate));//vad初始化 while (useTotalCount <= totalCount) { int pos = 0;// 被处理的数据块的使用偏移量 char *p = ptr + (useTotalCount -1) * 512;// 被处理数据块在ptr 中的首地址 int cursize = (useTotalCount != totalCount) ? 512 : (size - (useTotalCount-1)*512);// 被处理的数据块的大小 ++useTotalCount; // 获取并转换成vad 待处理数据 for (i = 0; i65535 / 2) indata[i] = indata[i] - 65536; }// 存储语音块的信息到 global_full BlockInfo* bi = new BlockInfo(); if (1 == wb_vad(vadstate, indata))//进行vad检测 { char* buf = new char[pos]; memcpy(buf, p, pos); bi->set(buf, pos); valitSize += cursize; } global_full.push(bi); } wb_vad_exit(&(vadstate)); fcloseall();}// 删除有效语音块中的数据(删除所有、删除3s)void clean_queue(queue* q, bool cleanall){ if(NULL == q) return ; BlockInfo* bi = NULL; if(cleanall) { while(q->size() > 0) { bi = q->front(); q->pop(); delete bi; } } else { int count = 62*3; while(q->size() > 0 && count > 0) { bi = q->front(); q->pop(); delete bi; --count; } }}// 检查有效语音块集合的状态// 0:save, 1: clean all, 2:clean by 3s, 3:ingoreint check_save(bool flag){ int size = global_valid.size(); if(flag) { return(size > 62*3*2) ? 2 : 3; } else { return (size < 62 || size > 62*3) ? 1 : 0; }}char* get_time(){ struct tm *newtime; char* outfile = new char[128]{0}; time_t t1 = time(NULL); newtime = localtime(&t1); strftime(outfile,128,"data_%Y%m%d_%H%M%S.wav",newtime); return outfile;}// 存储语音块集合中的数据到文件void save_queue(queue* q)
{
if(NULL == q) return;
char* savename = get_time();
int fd = open(savename, O_CREAT|O_WRONLY|O_TRUNC, 0777);
if(fd < 0)
{
printf("Fail to open or create file!\n");
exit(1);
}
BlockInfo* bi = NULL;
while(global_valid.size() > 0)
{
bi = global_valid.front();
global_valid.pop();
write(fd, bi->p, bi->len);
delete bi;
}
delete savename;
close(fd);
}
// 检查语音块集合
void check_queue()
{
if(0 ==global_full.size()) return;
BlockInfo* bi = NULL;
int check_save_ret = 0;
// 对每一块语音进行检查
while(global_full.size() > 0)
{
bi = global_full.front();
global_full.pop();
printf("vaild count %d\n", global_valid.size());
// 判断有效语音集合的状态
if(false == bi->valid)
{
delete bi;
check_save_ret = check_save(false);
// 0:save, 1: clean all, 2:clean by 3s, 3:ingore
}
else
{
global_valid.push(bi);
// 0:save, 1: clean all, 2:clean by 3s, 3:ingore
check_save_ret = check_save(true);
}
// 针对有效语音块集合的状态 做对应动作( 0:save, 1: clean all, 2:clean by 3s, 3:ingore)
switch(check_save_ret)
{
// 0:save, 1: clean all, 2:clean by 3s, 3:ingore
case 0:
save_queue(&global_valid);
break;
case 1:
clean_queue(&global_valid, true);
break;
case 2:
clean_queue(&global_valid, false);
break;
case 3:
break;
default:
printf("logic err\n");
break;
}
}
}
void start()
{
printf("准备录音...\n");
flag = 1;
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;
char *buffer;
rc = snd_pcm_open(&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(¶ms);
/* Fill it in with default values. */
if((rc=snd_pcm_hw_params_any(handle, params))<0)
{
fprintf(stderr,"cannot initialize hd params (%s)\n",snd_strerror(rc));
exit(1);
}
/* Set the desired hardware parameters. */
/* Interleaved mode */
if((rc=snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED))<0)
{
fprintf(stderr,"cannot set access type (%s)\n",snd_strerror(rc));
exit(1);
}
/* Signed 16-bit little-endian format */
if((rc=snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE))<0)
{
fprintf(stderr,"cannot set sample format (%s)\n",snd_strerror(rc));
exit(1);
}
/* One channels (stereo) */
if((rc=snd_pcm_hw_params_set_channels(handle, params, 1))<0)
{
fprintf(stderr,"cannot set channels (%s)\n",snd_strerror(rc));
exit(1);
}
/* 16000 bits/second sampling rate (CD quality) */
val = 16000;
if((rc=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir))<0)
{
fprintf(stderr,"cannot set sample rate_near (%s)\n",snd_strerror(rc));
exit(1);
}
/* Set period size to 32 frames. */
frames = 32;
if((rc=snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir))<0)
{
fprintf(stderr,"cannot set perios_size_near (%s)\n",snd_strerror(rc));
exit(1);
}
/* 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));
exit(1);
}
/* Use a buffer large enough to hold one period */
if((rc=snd_pcm_hw_params_get_period_size(params, &frames, &dir))<0)
{
fprintf(stderr,"cannot get period_size (%s)\n",snd_strerror(rc));
exit(1);
}
size = frames*8; /* 2 bytes/sample, 1 channels */
buffer = (char *) malloc(size);
printf("%d\n",frames);
printf("%d\n",size);
while (flag)
{
rc = snd_pcm_readi(handle, buffer, frames*4);
if (rc == -EPIPE)
{
/* EPIPE means overrun */
fprintf(stderr, "overrun occurred\n");
snd_pcm_prepare(handle);
}
else if (rc < 0)
{
fprintf(stderr, "error from read: %s\n", snd_strerror(rc));
}
else if (rc != (int)frames*4)
{
fprintf(stderr, "short read, read %d frames\n", rc);
}
vad(buffer,size);
// 检查语音块集合
check_queue();
}
if((rc=snd_pcm_drain(handle))<0)
{
fprintf(stderr,"cannot drain (%s)\n",snd_strerror(rc));
exit(1);
}
if((snd_pcm_close(handle))<0)
{
fprintf(stderr,"cannot close (%s)\n",snd_strerror(rc));
exit(1);
}
free(buffer);
// 录音结束
printf("录音完成,准备写入文件\n");
if(irstart)
{
start();
}
}
void _savename(const char* savename)
{
strncpy(filename, savename, strlen(savename));
}
void stop()
{
// 让录音停止
flag = 0;
irstart = 0;
}
void rstart(const char* savename)
{
_savename(savename);
stop();
irstart = 1;
}
void* thread_cb(void* savename)
{
_savename((char*)savename);
start();
return NULL;
}
void start_with_thread(const char* savename)
{
pthread_t pid;
pthread_create(&pid, NULL, thread_cb, (void*)savename);
pthread_detach(pid);
}
int main(void)
{
int test = 0;
// 1 录音
// 2 停止录音
// 3 重启
while(1)
{
scanf("%d", &test);
if(1 == test)
{
start_with_thread("start.wav");
}
else if(2 == test)
{
stop();
//savefile();
}
else if(3 == test)
{
rstart("restartname.wav");
}
else
{
break;
}
}
sleep(1);
printf("程序退出\n");
}