#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; // 當(dāng)前錄音是停止的int irstart = 0;// 判斷是否重啟char filename[1024] = "0";void? vad(char* ptr, int size){? ? int valitSize = 0;// 有效數(shù)據(jù)長度? ? int totalCount = size/512 + (size % 512) > 0 ? 1 : 0;// 總數(shù)據(jù)塊 數(shù)量? ? int useTotalCount = 1;// 使用過的數(shù)據(jù)塊 數(shù)量? ? int i, temp;? ? float indata[FRAME_LEN];? ? VadVars *vadstate;? ? wb_vad_init(&(vadstate));//vad初始化? ? while (useTotalCount <= totalCount)? ? {? ? ? ? int pos = 0;// 被處理的數(shù)據(jù)塊的使用偏移量? ? ? ? char *p = ptr + (useTotalCount -1) * 512;// 被處理數(shù)據(jù)塊在ptr 中的首地址? ? ? ? int cursize = (useTotalCount != totalCount) ? 512 : (size - (useTotalCount-1)*512);// 被處理的數(shù)據(jù)塊的大小? ? ? ? ++useTotalCount;? ? ? ? // 獲取并轉(zhuǎn)換成vad 待處理數(shù)據(jù)? ? ? ? for (i = 0; i65535 / 2)? ? ? ? ? ? ? ? indata[i] = indata[i] - 65536;? ? ? ? }// 存儲語音塊的信息到 global_full? ? ? ? BlockInfo* bi = new BlockInfo();? ? ? ? if (1 == wb_vad(vadstate, indata))//進(jìn)行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();}// 刪除有效語音塊中的數(shù)據(jù)(刪除所有、刪除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;? ? ? ? }? ? }}// 檢查有效語音塊集合的狀態(tài)// 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;}// 存儲語音塊集合中的數(shù)據(jù)到文件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;
// 對每一塊語音進(jìn)行檢查
while(global_full.size() > 0)
{
bi =? global_full.front();
global_full.pop();
printf("vaild count %d\n", global_valid.size());
// 判斷有效語音集合的狀態(tài)
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);
}
// 針對有效語音塊集合的狀態(tài) 做對應(yīng)動作( 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("準(zhǔn)備錄音...\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);
// 錄音結(jié)束
printf("錄音完成提澎,準(zhǔn)備寫入文件\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");
}