美文网首页
录音加vad

录音加vad

作者: cs1001 | 来源:发表于2017-06-19 19:29 被阅读0次

    #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");

    }

    相关文章

      网友评论

          本文标题:录音加vad

          本文链接:https://www.haomeiwen.com/subject/zurnqxtx.html