preloader
blog-post

nway_buffer新版,自动降噪、自动增益、自动VAD、自动录音

author image

nway_buffer新版,自动降噪、自动增益、自动VAD、自动录音

  之前因为某些应用的需求,把fs_buffer改了下,后来就增加的功能点越来越多,《nway_buffer,一个用于缓存音视频流的buffer以及降噪、自动增益、自动vad的windows及linux库》。现在新的版本更新了,不再显式vad,不再显式降噪,不再显示增益,都由库自身完成。

调用demo:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <process.h>
#include "../nway_utils.h"
nway_buffer_t* thread_buffer;  //全局的buffer,从read中读取,从write中写入
int is_read; //全局变量,用于标明是否读完了,读完了,那么在延时一个时间后,就可以走退出流程了
int read_buffer_size = 320;
int write_buffer_size = 320;
int timeout = 20;//20 second
int read_timeout = 20;//20 milisecond
int max_buffer_size = 1024 * 512;
//sem_t semLock;   //用于访问is_read
HANDLE    hIOMutex;// = CreateMutex(NULL, FALSE, NULL);

void ReadFunc(void* args)
{
    char* data = NULL;
    data = (char*)malloc(1000* sizeof(char));
    int read_len = 0;
    if (!data) {
        printf("create data buffer error!\r\n");
        WaitForSingleObject(hIOMutex, INFINITE);
        is_read = 1;
        ReleaseMutex(hIOMutex);
        return;
    }
    FILE* fpRead = (FILE*)args;
     

     
    while (1)
    {
        memset(data, 0, 1000);
        read_len = fread(data,sizeof(char), read_buffer_size, fpRead);
        if (read_len < 1) {
            printf("read the end ,exit read thread\r\n");
            break;
        }
        
        nway_buffer_lock(thread_buffer);
        nway_buffer_write(thread_buffer, data, read_len);
        nway_buffer_unlock(thread_buffer);
        printf("%s %d read len:%d \r\n", __FUNCTION__, __LINE__, read_len);
        Sleep(20);
        
    }
    printf("read from file is successed\r\n");
    WaitForSingleObject(hIOMutex, INFINITE);
    is_read = 1;
    ReleaseMutex(hIOMutex);
    nway_safe_free(data);
    
}
void WriteFunc(void* args)
{
    char* data = NULL;
    data = (char*)malloc(1000);
    int read_len = 0;
    int  inuse = 0;
    if (!data) {
        printf("create write data buffer error!\r\n");
        WaitForSingleObject(hIOMutex, INFINITE);
        is_read = 1;
        ReleaseMutex(hIOMutex);
        return;
    }
    FILE* fpWrite = (FILE*)args;



    while (!feof(fpWrite))
    {
        memset(data, 0, 1000);
        
        nway_buffer_lock(thread_buffer);
        if (thread_buffer == NULL) {
            //nway_buffer_unlock(thread_buffer);
            printf("exited write thread \r\n");
            break;
        }
       
        inuse = nway_buffer_inuse(thread_buffer);
        if (inuse < 1) {
            nway_buffer_unlock(thread_buffer);
            printf("inuse less than %d ,continue\r\n", 1);
            Sleep(20);
            continue;
        }
        
        read_len = nway_buffer_read(thread_buffer, data, write_buffer_size);

        nway_buffer_unlock(thread_buffer);
        if (read_len > 0) {
            printf("%s %d write len:%d \r\n", __FUNCTION__, __LINE__, read_len);
            fwrite(data, 1, read_len, fpWrite);
        }
        
    }
    printf("write itno file is successed\r\n");
     
    nway_safe_free(data);
}

int mycallback(int flag,const char* record_file,...){
    if (flag == 1)
    printf("this vad file:%s\n",record_file);
    else
    printf("this not a vad file\n");
}
int main(int argc,char *argv[])
{
    FILE* fin = NULL, * fout = NULL;
    printf("this is test program\r\n");
    char* inputfile = NULL;// = strdup(argv[1]);
    char* outputfile = NULL;// strdup(argv[2]);
    if (argc < 3) {
        printf("usage: demo.exe in.wav out.wav\r\n");
        //return -1;
        inputfile = strdup("d:\\microsip.exe");
        outputfile = strdup("d:\\nwaysip.exe");
    }else{
        inputfile = strdup(argv[1]);
        outputfile = strdup(argv[2]);
    }
   
    fin = fopen(inputfile, "r");
    if (fin == NULL) {
        printf("open input file failed\r\n");
        return -1;
    }
    fout = fopen(outputfile, "wb+");
    if (fout == NULL) {
        printf("open outfile failed\r\n");
        return -1;
    }
    fseek(fin, 0, SEEK_END);
    int file_size = ftell(fin);
    printf("this program use multi thread to read file from %s ,len:%d,then write into %s\r\n", inputfile, file_size,outputfile);
    rewind(fin);
   // sem_init(&semLock, 0, 1);
    nway_buffer_create_dynamic(&thread_buffer, max_buffer_size, 1024 * 64, 0);
    nway_use_vad(thread_buffer);//设定使用vad
    nway_set_callback(thread_buffer,mycallback);
    nway_set_record_path(thread_buffer,"./");
    is_read = 0;
    HANDLE    hIOMutex = CreateMutex(NULL, FALSE, NULL);
    _beginthread(ReadFunc, 0, fin);
    _beginthread(WriteFunc, 0, fout);
    while (1) {
        WaitForSingleObject(hIOMutex, INFINITE);
        if (is_read == 1) {
            ReleaseMutex(hIOMutex);
            Sleep(timeout * 1000);
            
            break;
        }
        ReleaseMutex(hIOMutex);
        Sleep(20);
    }
    CloseHandle(hIOMutex);

    nway_buffer_destroy(&thread_buffer);
    if (inputfile) nway_safe_free(inputfile);
    if (outputfile) nway_safe_free(outputfile);
    fclose(fin);
    fclose(fout);

}

库头文件:

#ifndef NWAY_BUFFER_H
#define NWAY_BUFFER_H
#include "nway_buffer_define.h"

NWAY_BEGIN_EXTERN_C
/**
 * @defgroup nway_buffer Buffer Routines
 * @ingroup core1
 * The purpose of this module is to make a plain buffering interface that can be used for read/write buffers
 * throughout the application.  The first implementation was done to provide the functionality and the interface
 * and I think it can be optimized under the hood as we go using bucket brigades and/or ring buffering techniques.
 * @{
 */
//typedef struct apr_pool_t nway_memory_pool_t;
//typedef nway_buffer ;

nway_status_t
nway_buffer_create_partition(nway_memory_pool_t *pool, nway_buffer_t **buffer, void *data, nway_size_t datalen);
nway_status_t
nway_buffer_set_partition_data(nway_buffer_t *buffer, void *data, nway_size_t datalen);
nway_status_t
nway_buffer_reset_partition_data(nway_buffer_t *buffer);

/*! \brief Allocate a new nway_buffer
 * \param pool Pool to allocate the buffer from
 * \param buffer returned pointer to the new buffer
 * \param max_len length required by the buffer
 * \return status
 */
nway_status_t
nway_buffer_create(_In_ nway_memory_pool_t *pool, _Out_ nway_buffer_t **buffer, _In_ nway_size_t max_len);

/*! \brief Allocate a new dynamic nway_buffer
 * \param buffer returned pointer to the new buffer
 * \param blocksize length to realloc by as data is added
 * \param start_len ammount of memory to reserve initially
 * \param max_len length the buffer is allowed to grow to
 * \return status
 */
nway_status_t nway_buffer_create_dynamic(_Out_ nway_buffer_t **buffer, _In_ nway_size_t blocksize, _In_ nway_size_t start_len,
                     _In_ nway_size_t max_len);

nway_status_t nway_mutex_create(NWAY_HANDLE *mymutex);

void nway_buffer_add_mutex(_In_ nway_buffer_t *buffer, _In_ NWAY_HANDLE *mutex);
void nway_buffer_lock(_In_ nway_buffer_t *buffer);
nway_status_t nway_buffer_trylock(_In_ nway_buffer_t *buffer);
void nway_buffer_unlock(_In_ nway_buffer_t *buffer);

/*! \brief Get the length of a nway_buffer_t
 * \param buffer any buffer of type nway_buffer_t
 * \return int size of the buffer.
 */
nway_size_t
nway_buffer_len(_In_ nway_buffer_t *buffer);

/*! \brief Get the freespace of a nway_buffer_t
 * \param buffer any buffer of type nway_buffer_t
 * \return int freespace in the buffer.
 */
nway_size_t
nway_buffer_freespace(_In_ nway_buffer_t *buffer);

/*! \brief Get the in use amount of a nway_buffer_t
 * \param buffer any buffer of type nway_buffer_t
 * \return int ammount of buffer curently in use
 */
nway_size_t
nway_buffer_inuse(_In_ nway_buffer_t *buffer);

/*! \brief Read data from a nway_buffer_t up to the ammount of datalen if it is available.  Remove read data from buffer.
 * \param buffer any buffer of type nway_buffer_t
 * \param data pointer to the read data to be returned
 * \param datalen amount of data to be returned
 * \return int ammount of data actually read
 */
nway_size_t
nway_buffer_read(_In_ nway_buffer_t *buffer, _In_ void *data, _In_ nway_size_t datalen);

/*! \brief Read data from a nway_buffer_t up to the ammount of datalen if it is available, without removing read data from buffer.
 * \param buffer any buffer of type nway_buffer_t
 * \param data pointer to the read data to be returned
 * \param datalen amount of data to be returned
 * \return int ammount of data actually read
 */
nway_size_t
nway_buffer_peek(_In_ nway_buffer_t *buffer, _In_ void *data, _In_ nway_size_t datalen);

nway_size_t
nway_buffer_peek_zerocopy(_In_ nway_buffer_t *buffer, _Out_ const void **ptr);

/*! \brief Read data endlessly from a nway_buffer_t
 * \param buffer any buffer of type nway_buffer_t
 * \param data pointer to the read data to be returned
 * \param datalen amount of data to be returned
 * \return int ammount of data actually read
 * \note Once you have read all the data from the buffer it will loop around.
 */
nway_size_t
nway_buffer_read_loop(_In_ nway_buffer_t *buffer, _In_ void *data, _In_ nway_size_t datalen);

/*! \brief Assign a number of loops to read
 * \param buffer any buffer of type nway_buffer_t
 * \param loops the number of loops (-1 for infinite)
 */
void nway_buffer_set_loops(_In_ nway_buffer_t *buffer, _In_ int32_t loops);

/*! \brief Write data into a nway_buffer_t up to the length of datalen
 * \param buffer any buffer of type nway_buffer_t
 * \param data pointer to the data to be written
 * \param datalen amount of data to be written
 * \return int amount of buffer used after the write, or 0 if no space available
 */
nway_size_t
nway_buffer_write(_In_ nway_buffer_t *buffer, _In_bytecount_(datalen) const void *data, _In_ nway_size_t datalen);

/*! \brief Remove data from the buffer
 * \param buffer any buffer of type nway_buffer_t
 * \param datalen amount of data to be removed
 * \return int size of buffer, or 0 if unable to toss that much data
 */
nway_size_t
nway_buffer_toss(_In_ nway_buffer_t *buffer, _In_ nway_size_t datalen);

/*! \brief Remove all data from the buffer
 * \param buffer any buffer of type nway_buffer_t
 */
void nway_buffer_zero(_In_ nway_buffer_t *buffer);

nway_size_t
nway_buffer_slide_write(nway_buffer_t *buffer, const void *data, nway_size_t datalen);

/*! \brief Destroy the buffer
 * \param buffer buffer to destroy
 * \note only neccessary on dynamic buffers (noop on pooled ones)
 */
void nway_buffer_destroy(nway_buffer_t **buffer);

nway_size_t
nway_buffer_zwrite(_In_ nway_buffer_t *buffer, _In_bytecount_(datalen) const void *data, _In_ nway_size_t datalen);

void *
nway_buffer_get_head_pointer(nway_buffer_t *buffer);

void *nway_core_alloc(nway_memory_pool_t *pool, nway_size_t memory);
#define nway_assert(expr)                \
  do                                   \
  {                                    \
    if (!(expr))                     \
    {                                \
      fprintf(stderr, "MEMERR\n"); \
      abort();                     \
    }                                \
  } while (0)
void nway_safe_free(void *p);
/// @brief /
/// @param buffer 
void nway_use_vad(_In_ nway_buffer_t *buffer);
void nway_unuse_vad(_In_ nway_buffer_t *buffer);
void nway_set_record_path(_In_ nway_buffer_t *buffer,_In_ const char* record_path);

/// @brief 设置回调函数,一个变量只声明一次
/// @param buffer 
/// @param callback 
void nway_set_callback(_In_ nway_buffer_t *buffer,buffer_callback callback);

/// @brief 自动生成当前要进行vad的录音文件路径和名称,结合record_path
/// @param buffer 
/// @return 
char* nway_gen_record_file(_In_ nway_buffer_t *buffer);

/// @brief 设置要进行vad的参数
/// @param buffer 
/// @param min_speak_tm 
/// @param max_record_tm 
/// @param max_wait_tm 
/// @param min_pause_tm 
/// @param auto_gain 
void nway_set_vad_params(_In_ nway_buffer_t *buffer,uint32_t min_speak_tm,uint32_t max_record_tm,
uint32_t max_wait_tm,uint32_t min_pause_tm,uint32_t auto_gain);

/// @brief 设置要进行完整的录音文件路径,会自动设置auto_record 为1
/// @param buffer 
/// @param full_record_file 由外部应用传进的完整路径和文件名
void nway_set_full_record_file(_In_ nway_buffer_t *buffer,const char* full_record_file);
///////////////////////////////////////////////////////////////////////////////


NWAY_END_EXTERN_C
#endif

Recent Articles

blog-post

限时免费实时质检、免费座席助手中间件

 注意,本次应用的能力为半实时,即不是每个语音包流都要送往识别,而是VAD后才送,识别后通过ESL发送消息后进行处理,用于座席辅助或半实时质检均可。部署方式为:云主机、物理机、测试型的内部虚拟机均可。识别特性:座席助手,或当检测到有异常,实 …