zoukankan      html  css  js  c++  java
  • fader

    fader在音频处理中是比较基础的处理。通常用于平滑的调节音量,或是音频的渐入和渐出效果。

    比较常见的fader有line和cubic线型的fader。

    line fader即fader的渐变过程是线性的。cubic的渐变过程是三次曲线。

    fader主要有三个参数,attuationDb, type, timeMs.

    line fader:

    通过当前的音量curVolumDb,计算fader的初始gain值:startGain = dbToGain(curVolumDb)

    fader结束音量为curVolumDb + attuationDb,那么fader结束的gain值为:endGain = dbToGain(curVolumDb + curVolumDb)

    将fader的开始到结束的时间timeMs转化为sample为单位:timeInSample = timeMs * sampleRate / 1000.

    那么line fader的step为:step = (endGain - startGain) / timeInSample.

    初始化curSample为0, curGain= startGain.

    每处理一个sample(sample * curGain), curSample加1. curGain加step,直至curSample等于timeInSample,整个fader过程结束。

    5s内衰减5db

    5s时间fader in

    cubic fader:

    cubic fader的原理为,将0~1划分为多个段(假设为segNum)。计算每个Segment端点的gain值:segGain.

    由于有segNum个段,那么0~1被离散为segNum + 1个点,每个点的segGain[n]值为(n/(segNum +1))^3. n=0,1,2...segNum+1;

    将0~1之间的segGain map到startGain ~ endGain之间。

    对于0~timeInSample之间的点,我们计算当前的sample处于哪个segment,当curSample是当前segment的第一个点时,将curGain设置成segGain[n].

    当前segment按line fader一样的方法计算每个点的gain,每处理一个sample, curGain加step.

    5s内衰减5db

     

     5s时间fader in

     

     实现代码如下:

    在main函数创建两个thread,readThread, ppThread.

    readThread每次读取wav文件256个sample,并每次取出64 sample转化成non-interleave的数据,发送到ppThread中。

    定义一个全局的三维数组gPpBuf[chNum][bankNum][sampleNum],将转化成non-interleave的数据放到数组中,维护rp和wp来记录readThread和ppThread的当前读写的bank位置。

    在ppThread中,每次接收到64sample做fader处理。

    #include<stdio.h>
    #include<stdlib.h>
    #include<errno.h>
    #include<string.h>
    #include<pthread.h>
    #include<math.h>
    typedef struct{
    char chunkId[4];//"RIFF"
    unsigned long chunkSize;
    char format[4];//"WAVE"
    }WAVE_RIFF;
    typedef struct{
    char chunkId[4];//"fmt"
    unsigned long chunkSize;
    unsigned short audioFormat;
    unsigned short chNum;
    unsigned long sampleRate;
    unsigned long byteRate;//SampleRate * NumChannels * BitsPerSample/8
    unsigned short blockAlign;//NumChannels * BitsPerSample/8
    unsigned short bitsPerSample;//8,16,32
    }WAVE_FMT;
    typedef struct{
    char chunkId[4];//"data"
    unsigned long chunkSize;//NumSamples * NumChannels * BitsPerSample/8
    }WAVE_DATA;
    typedef struct
    {
        char fileName[256];
        FILE *fp;
        long pos;
        unsigned long totalSampleNum;
        WAVE_RIFF riffChunk;
        WAVE_FMT fmtChunk;
        WAVE_DATA dataChunk;
    }WAVE_INFO;
    
    #define READ_SAMPLES 256
    #define PP_SAMPLES 64
    typedef struct
    {
        unsigned short chNum;
        unsigned short bankNum;
        unsigned long samplesPerBank;
        unsigned short bytesPerSample;
        unsigned short bankRp;
        unsigned short bankWp;
        unsigned char ***pData;
        unsigned char fgEos;
    }PP_BUF_T;
    
    typedef enum
    {
        FADER_TYPE_LINE,
        FADER_TYPE_CUBIC,
    }FADER_TYPE_E;
    typedef struct
    {
        float attuationDb;
        FADER_TYPE_E type;
        unsigned long timeMs;
    }FADER_PARAM_T;
    
    typedef struct
    {
        FADER_PARAM_T faderParams;
        unsigned long timeInSample;
        float curVolumDb;
        float curGain;
        float startGain;
        float targetGain;
        unsigned long curSample;
        unsigned long sampleRate;
        float *segGain;
        unsigned short segNum;
    }FADER_HANDLE_T;
    typedef struct
    {
        short **pData;
        unsigned short chNum;
        unsigned short samples;
        unsigned short bytesPerSample;
    }DATA_INFO_T;
    PP_BUF_T gPpBuf;
    FADER_HANDLE_T gFaderHandle;
    unsigned char fgEnd = 0;
    float mapSegGainToRealGain(FADER_HANDLE_T *pFaderHandle, float segGain)
    {
        float deltaGain = pFaderHandle->targetGain - pFaderHandle->startGain;
        float realGain = deltaGain * segGain + pFaderHandle->startGain;
        return realGain;
    }
    void faderPrepareShape(FADER_HANDLE_T *pFaderHandle, unsigned short segNum)
    {
        unsigned short segIdx;
        pFaderHandle->segGain = (float *)malloc((segNum + 1) * sizeof(float));
        pFaderHandle->segNum = segNum;
        float tmp;
        if (pFaderHandle->faderParams.type != FADER_TYPE_CUBIC)
             return;
        //0~1 divide into N seg.
        for (segIdx = 0; segIdx < segNum + 1; segIdx++)
        {
            tmp = (float)segIdx / segNum;
            pFaderHandle->segGain[segIdx] = tmp * tmp * tmp;
            pFaderHandle->segGain[segIdx] = mapSegGainToRealGain(pFaderHandle, pFaderHandle->segGain[segIdx]);
        }
    }
    float dbToGain(float db)
    {
        return pow(10, db/20);
    }
    void faderInit(FADER_HANDLE_T *pFaderHandle, float attuationDb, FADER_TYPE_E type, unsigned long timeMs, unsigned long sampleRate, float curVolumDb)
    {
        pFaderHandle->faderParams.attuationDb = attuationDb;
        pFaderHandle->faderParams.type = type;
        pFaderHandle->faderParams.timeMs = timeMs;
        pFaderHandle->timeInSample = timeMs * sampleRate / 1000;
        pFaderHandle->curGain = pFaderHandle->startGain = dbToGain(curVolumDb);
        pFaderHandle->targetGain = dbToGain(curVolumDb + attuationDb);
        pFaderHandle->curSample = 0;
        faderPrepareShape(pFaderHandle, 20);
        printf("faderInit
    ");
    }
    
    void faderCalGain(FADER_HANDLE_T *pFaderHandle)
    {
        printf("faderCalcGain
    ");
        float startGainInCurSeg, endGainInCurSeg, step;
        float deltaGain = pFaderHandle->targetGain - pFaderHandle->startGain;
        unsigned long samplesInSeg = pFaderHandle->timeInSample / pFaderHandle->segNum;
        unsigned short curSeg = (float)pFaderHandle->curSample / samplesInSeg;
        unsigned long startSampleInCurSeg = samplesInSeg * curSeg;
        switch (pFaderHandle->faderParams.type)
        {
            case FADER_TYPE_LINE:
                step = deltaGain / pFaderHandle->timeInSample;
                pFaderHandle->curGain += deltaGain / pFaderHandle->timeInSample;
                //pFaderHandle->curGain = pFaderHandle->startGain + deltaGain * pFaderHandle->curSample / pFaderHandle->timeInSample;
                break;
            case FADER_TYPE_CUBIC:
                startGainInCurSeg = pFaderHandle->segGain[curSeg];
                endGainInCurSeg = pFaderHandle->segGain[curSeg + 1];
                step = (endGainInCurSeg - startGainInCurSeg) / samplesInSeg;
                if (pFaderHandle->curSample == startSampleInCurSeg)
                    pFaderHandle->curGain = startGainInCurSeg;
                else
                    pFaderHandle->curGain += step;
                break;
        }
        printf("curGain:%f, curSample:%ld, timeInSample:%ld
    ", pFaderHandle->curGain, pFaderHandle->curSample, pFaderHandle->timeInSample);
    }
    
    void fader(FADER_HANDLE_T *pFaderHandle, DATA_INFO_T *pDataInfo)
    {
        unsigned short sampleIdx, chIdx;
        for (sampleIdx = 0; sampleIdx < pDataInfo->samples; sampleIdx++)
        {
            if (pFaderHandle->curSample != pFaderHandle->timeInSample)
            {
                faderCalGain(pFaderHandle);
                pFaderHandle->curSample++;
            }
            for (chIdx = 0; chIdx < pDataInfo->chNum; chIdx++)
            {
                pDataInfo->pData[chIdx][sampleIdx] *= pFaderHandle->curGain;
            }
        }
    }
    void printWaveHeader(WAVE_INFO *pWaveInfo)
    {
        printf("fileName:%s
    ", pWaveInfo->fileName);
        printf("riff chunk:
    ");
        printf("chunkId:%c%c%c%c
    ", pWaveInfo->riffChunk.chunkId[0], pWaveInfo->riffChunk.chunkId[1], pWaveInfo->riffChunk.chunkId[2], pWaveInfo->riffChunk.chunkId[3]);
        printf("chunkSize:%ld
    ", pWaveInfo->riffChunk.chunkSize);
        printf("format:%c%c%c%c
    ", pWaveInfo->riffChunk.format[0], pWaveInfo->riffChunk.format[1], pWaveInfo->riffChunk.format[2], pWaveInfo->riffChunk.format[3]);
        printf("fmt chunk:
    ");
        printf("chunkId:%c%c%c
    ", pWaveInfo->fmtChunk.chunkId[0], pWaveInfo->fmtChunk.chunkId[1], pWaveInfo->fmtChunk.chunkId[2]);
        printf("chunkSize:%ld
    ", pWaveInfo->fmtChunk.chunkSize);
        printf("audioFormat:%d
    ", pWaveInfo->fmtChunk.audioFormat);
        printf("chNum:%d
    ", pWaveInfo->fmtChunk.chNum);
        printf("sampleRate:%ld
    ", pWaveInfo->fmtChunk.sampleRate);
        printf("byteRate:%ld
    ", pWaveInfo->fmtChunk.byteRate);
        printf("blockAlign:%d
    ", pWaveInfo->fmtChunk.blockAlign);
        printf("bitsPerSample:%d
    ", pWaveInfo->fmtChunk.bitsPerSample);
        printf("data chunk:
    ");
        printf("chunkId:%c%c%c%c
    ", pWaveInfo->dataChunk.chunkId[0], pWaveInfo->dataChunk.chunkId[1], pWaveInfo->dataChunk.chunkId[2], pWaveInfo->dataChunk.chunkId[3]);
        printf("chunkSize:%ld
    ", pWaveInfo->dataChunk.chunkSize);
        
    }
    void initWaveInfo(WAVE_INFO *pWaveInfo, unsigned short chNum, unsigned long sampleRate, unsigned short bitsPerSample)
    {
        //strncpy(pWaveInfo->riffChunk.chunkId, "RIFF", 4);
        pWaveInfo->riffChunk.chunkId[0] = 'R';
        pWaveInfo->riffChunk.chunkId[1] = 'I';
        pWaveInfo->riffChunk.chunkId[2] = 'F';
        pWaveInfo->riffChunk.chunkId[3] = 'F';
        pWaveInfo->riffChunk.chunkSize = 0;
        //strncpy(pWaveInfo->riffChunk.format, "WAVE", 4);
        pWaveInfo->riffChunk.format[0] = 'W';
        pWaveInfo->riffChunk.format[1] = 'A';
        pWaveInfo->riffChunk.format[2] = 'V';
        pWaveInfo->riffChunk.format[3] = 'E';
        //strncpy(pWaveInfo->fmtChunk.chunkId, "fmt", 3);
        pWaveInfo->fmtChunk.chunkId[0] = 'f';
        pWaveInfo->fmtChunk.chunkId[1] = 'm';
        pWaveInfo->fmtChunk.chunkId[2] = 't';
        pWaveInfo->fmtChunk.chunkId[3] = ' ';
        pWaveInfo->fmtChunk.chunkSize = sizeof(WAVE_FMT) - 8;
        pWaveInfo->fmtChunk.audioFormat = 1;
        pWaveInfo->fmtChunk.chNum = chNum;
        pWaveInfo->fmtChunk.sampleRate = sampleRate;
        pWaveInfo->fmtChunk.byteRate = sampleRate * chNum * bitsPerSample / 8;
        pWaveInfo->fmtChunk.blockAlign = chNum * bitsPerSample / 8;
        pWaveInfo->fmtChunk.bitsPerSample = bitsPerSample;
        //strncpy(pWaveInfo->dataChunk.chunkId, "data", 4);
        pWaveInfo->dataChunk.chunkId[0] = 'd';
        pWaveInfo->dataChunk.chunkId[1] = 'a';
        pWaveInfo->dataChunk.chunkId[2] = 't';
        pWaveInfo->dataChunk.chunkId[3] = 'a';
        
        pWaveInfo->dataChunk.chunkSize = 0;
        pWaveInfo->totalSampleNum = 0;
        ///printWaveHeader(pWaveInfo);
    }
    
    void rwRiffChunk(WAVE_INFO *pWaveInfo, unsigned char fgRead)
    {
        if (fgRead)
        {
            fread((char *)&pWaveInfo->riffChunk.chunkId, 4, 1, pWaveInfo->fp);
            fread((char *)&pWaveInfo->riffChunk.chunkSize, 4, 1, pWaveInfo->fp);
            fread((char *)&pWaveInfo->riffChunk.format, 4, 1, pWaveInfo->fp);
        }
        else
        {
            fwrite((char *)&pWaveInfo->riffChunk.chunkId, 4, 1, pWaveInfo->fp);
            fwrite((char *)&pWaveInfo->riffChunk.chunkSize, 4, 1, pWaveInfo->fp);
            fwrite((char *)&pWaveInfo->riffChunk.format, 4, 1, pWaveInfo->fp);
        }
    }
    void rwFmtChunk(WAVE_INFO *pWaveInfo, unsigned char fgRead)
    {
        if (fgRead)
        {
            fread((char *)&pWaveInfo->fmtChunk.chunkId, 4, 1, pWaveInfo->fp);
            fread((char *)&pWaveInfo->fmtChunk.chunkSize, 4, 1, pWaveInfo->fp);
            fread((char *)&pWaveInfo->fmtChunk.audioFormat, 2, 1, pWaveInfo->fp);
            fread((char *)&pWaveInfo->fmtChunk.chNum, 2, 1, pWaveInfo->fp);
            fread((char *)&pWaveInfo->fmtChunk.sampleRate, 4, 1, pWaveInfo->fp);
            fread((char *)&pWaveInfo->fmtChunk.byteRate, 4, 1, pWaveInfo->fp);
            fread((char *)&pWaveInfo->fmtChunk.blockAlign, 2, 1, pWaveInfo->fp);
            fread((char *)&pWaveInfo->fmtChunk.bitsPerSample, 2, 1, pWaveInfo->fp);
        }
        else
        {
            fwrite((char *)&pWaveInfo->fmtChunk.chunkId, 4, 1, pWaveInfo->fp);
            fwrite((char *)&pWaveInfo->fmtChunk.chunkSize, 4, 1, pWaveInfo->fp);
            fwrite((char *)&pWaveInfo->fmtChunk.audioFormat, 2, 1, pWaveInfo->fp);
            fwrite((char *)&pWaveInfo->fmtChunk.chNum, 2, 1, pWaveInfo->fp);
            fwrite((char *)&pWaveInfo->fmtChunk.sampleRate, 4, 1, pWaveInfo->fp);
            fwrite((char *)&pWaveInfo->fmtChunk.byteRate, 4, 1, pWaveInfo->fp);
            fwrite((char *)&pWaveInfo->fmtChunk.blockAlign, 2, 1, pWaveInfo->fp);
            fwrite((char *)&pWaveInfo->fmtChunk.bitsPerSample, 2, 1, pWaveInfo->fp);
            
        }
    }
    void rwDataChunk(WAVE_INFO *pWaveInfo, unsigned char fgRead)
    {
        if (fgRead)
        {
            fread((char *)&pWaveInfo->dataChunk.chunkId, 4, 1, pWaveInfo->fp);
            fread((char *)&pWaveInfo->dataChunk.chunkSize, 4, 1, pWaveInfo->fp);
        }
        else
        {
            fwrite((char *)&pWaveInfo->dataChunk.chunkId, 4, 1, pWaveInfo->fp);
            fwrite((char *)&pWaveInfo->dataChunk.chunkSize, 4, 1, pWaveInfo->fp);
        }
    }
    
    void readWaveHeader(char *fileName, WAVE_INFO *pWaveInfo)
    {
        size_t retSize;
        strncpy(pWaveInfo->fileName, fileName, strlen(fileName));
        pWaveInfo->fp = fopen(fileName, "rb");
        if (pWaveInfo->fp == NULL)
        {
            printf("fopen fail, errno:%d
    ", errno);
            return;
        }
        #if 0
        retSize = fread((char *)&pWaveInfo->riffChunk, sizeof(WAVE_RIFF), 1, pWaveInfo->fp);
        retSize = fread((char *)&pWaveInfo->fmtChunk, sizeof(WAVE_FMT), 1, pWaveInfo->fp);
        retSize = fread((char *)&pWaveInfo->dataChunk, sizeof(WAVE_DATA), 1, pWaveInfo->fp);
        #endif
        rwRiffChunk(pWaveInfo, 1);
        rwFmtChunk(pWaveInfo, 1);
        rwDataChunk(pWaveInfo, 1);
        pWaveInfo->pos = ftell(pWaveInfo->fp);
        pWaveInfo->totalSampleNum = pWaveInfo->dataChunk.chunkSize / (pWaveInfo->fmtChunk.bitsPerSample / 8);
        fclose(pWaveInfo->fp);
        printWaveHeader(pWaveInfo);
    }
    
    void initPpBuf(unsigned short chNum, unsigned short bankNum, unsigned long samplesPerBank, unsigned short bytesPerSample)
    {
        unsigned short chIdx, bankIdx;
        gPpBuf.chNum = chNum;    
        gPpBuf.bankNum = bankNum;    
        gPpBuf.samplesPerBank = samplesPerBank;
        gPpBuf.bytesPerSample = bytesPerSample;
    
        gPpBuf.bankRp = gPpBuf.bankWp = 0;
        gPpBuf.fgEos = 0;
        gPpBuf.pData = (unsigned char ***)malloc(chNum * sizeof(unsigned char **));
        for (chIdx = 0; chIdx < chNum; chIdx++)
        {
            gPpBuf.pData[chIdx] = (unsigned char **)malloc(bankNum * sizeof(unsigned char *));
            for (bankIdx =0; bankIdx < bankNum; bankIdx++)
            {
                gPpBuf.pData[chIdx][bankIdx] = (unsigned char *) malloc(samplesPerBank * bytesPerSample * sizeof(unsigned char));
            }
        }
    }
    
    int sendData(unsigned char *writeBuffer, unsigned short chNum)
    {
        unsigned short sampleIdx, chIdx, byteIdx;
        //printf("sendData, wp:%d, rp:%d
    ", gPpBuf.bankWp, gPpBuf.bankRp);
        if ((gPpBuf.bankWp + 1 ) % gPpBuf.bankNum == gPpBuf.bankRp)
        {
            //full
            return 1;
        }
        else
        {
            for (sampleIdx = 0; sampleIdx < PP_SAMPLES; sampleIdx++)
            {
                for (chIdx =0; chIdx < chNum; chIdx++)
                {
                    for (byteIdx = 0; byteIdx < gPpBuf.bytesPerSample; byteIdx++)
                    {
                   gPpBuf.pData[chIdx][gPpBuf.bankWp][sampleIdx * gPpBuf.bytesPerSample + byteIdx] = writeBuffer[(chIdx + sampleIdx * chNum) * gPpBuf.bytesPerSample + byteIdx];  
              }
                }
            }
            gPpBuf.bankWp = (gPpBuf.bankWp + 1) % gPpBuf.bankNum;
        }
        return 0;
    }
    
    int recvData(unsigned char **readBuffer)
    {
        unsigned short chIdx;
        //printf("recvData, wp:%d, rp:%d
    ", gPpBuf.bankWp, gPpBuf.bankRp);
        if (gPpBuf.bankWp == gPpBuf.bankRp)
        {
            //empty
            return 1;
        }
        else
        {
            for (chIdx = 0; chIdx < gPpBuf.chNum; chIdx++)
            {
                memcpy(&readBuffer[chIdx][0], &gPpBuf.pData[chIdx][gPpBuf.bankRp][0], PP_SAMPLES * gPpBuf.bytesPerSample * sizeof(unsigned char));
            }
            gPpBuf.bankRp = (gPpBuf.bankRp + 1) % gPpBuf.bankNum;
        }
        return 0;
    }
    void *readThread(void *arg)
    {
        char *fileName = (char *)arg;
        size_t retSize;
        WAVE_INFO waveInfo;
        memset(&waveInfo, 0, sizeof(WAVE_INFO));
        unsigned long bytesPerLoop;
        unsigned short loopIdx, loop;
        unsigned long readCount = 0;
        readWaveHeader(fileName, &waveInfo);
        unsigned long readSize = READ_SAMPLES * waveInfo.fmtChunk.chNum * waveInfo.fmtChunk.bitsPerSample / 8;
        printf("readSize:%ld
    ", readSize);
        unsigned char *readBuffer = (unsigned char *)malloc(readSize * sizeof(unsigned char));
        waveInfo.fp = fopen(fileName, "rb");
        fseek(waveInfo.fp,  waveInfo.pos, SEEK_SET);
        while (1)
        {
            retSize = fread(readBuffer, readSize, 1, waveInfo.fp);
            if (retSize <= 0)
            {
                 printf("fread fail,retSize:%d, %s, eof:%d, readCount:%ld
    ", (int) retSize, strerror(errno), feof(waveInfo.fp), readCount);
                 gPpBuf.fgEos = 1;
                 break;
            }
            else
            {
                 bytesPerLoop = PP_SAMPLES *waveInfo.fmtChunk.chNum * waveInfo.fmtChunk.bitsPerSample / 8;
                 loop = readSize / bytesPerLoop;
                 loopIdx = 0;
                 while (loopIdx < loop)
                 {
                     if (0 != sendData(readBuffer + loopIdx * bytesPerLoop, waveInfo.fmtChunk.chNum))
                     {
                         usleep(1000);
                     }
                     else
                     {
                         loopIdx++;
                     }
                 }
                 readCount++; 
            }
        }
        return NULL;
    }
    void pp(DATA_INFO_T *pDataInfo)
    {
        fader(&gFaderHandle, pDataInfo);
    }
    
    void saveOneChInWave(unsigned char *pData, unsigned long size, WAVE_INFO *pWaveInfo)
    {
       size_t retSize = 0;
       if (pWaveInfo->fp == NULL)
       {
           pWaveInfo->fp = fopen(pWaveInfo->fileName, "wb");
           #if 0
           retSize = fwrite((char *)&pWaveInfo->riffChunk, sizeof(WAVE_RIFF), 1, pWaveInfo->fp);
           retSize = fwrite((char *)&pWaveInfo->fmtChunk, sizeof(WAVE_FMT), 1, pWaveInfo->fp);
            retSize = fwrite((char *)&pWaveInfo->dataChunk, sizeof(WAVE_DATA), 1, pWaveInfo->fp);
            #endif
            rwRiffChunk(pWaveInfo, 0);
            rwFmtChunk(pWaveInfo, 0);
            rwDataChunk(pWaveInfo, 0);   
        } 
        retSize = fwrite(pData, size, 1, pWaveInfo->fp);
        pWaveInfo->totalSampleNum += (size / pWaveInfo->fmtChunk.chNum / (pWaveInfo->fmtChunk.bitsPerSample / 8));
        pWaveInfo->pos = ftell(pWaveInfo->fp);
    }
    
    void updateWaveHeader(WAVE_INFO *pWaveInfo)
    {
        size_t retSize;
        pWaveInfo->riffChunk.chunkSize = pWaveInfo->pos - 8;
        pWaveInfo->dataChunk.chunkSize = pWaveInfo->totalSampleNum * pWaveInfo->fmtChunk.chNum * pWaveInfo->fmtChunk.bitsPerSample / 8;
        fseek(pWaveInfo->fp,  0, SEEK_SET);
        #if 0
        retSize = fwrite((char *)&pWaveInfo->riffChunk, sizeof(WAVE_RIFF), 1, pWaveInfo->fp);
        retSize = fwrite((char *)&pWaveInfo->fmtChunk, sizeof(WAVE_FMT), 1, pWaveInfo->fp);
        retSize = fwrite((char *)&pWaveInfo->dataChunk, sizeof(WAVE_DATA), 1, pWaveInfo->fp);
        #endif    
        rwRiffChunk(pWaveInfo, 0);
        rwFmtChunk(pWaveInfo, 0);
        rwDataChunk(pWaveInfo, 0);   
        fclose(pWaveInfo->fp);
        
        printWaveHeader(pWaveInfo);
    }
    void *ppThread(void *arg)
    {
        char *fileName = (char *)arg;
        WAVE_INFO waveInfo;
        memset(&waveInfo, 0, sizeof(waveInfo));
        strncpy(waveInfo.fileName, fileName, strlen(fileName));
        printf("out file:%s
    ", waveInfo.fileName);
        waveInfo.fp = NULL;
        initWaveInfo(&waveInfo, 1, 48000, 16);
        unsigned char **readBuffer = (unsigned char **)malloc(gPpBuf.chNum * sizeof(unsigned char *));
        unsigned short chIdx;
        for(chIdx = 0; chIdx < gPpBuf.chNum; chIdx++)
        {
            readBuffer[chIdx] = (unsigned char *)malloc(PP_SAMPLES * gPpBuf.bytesPerSample * sizeof(unsigned char));
        }
        while (1)
        {
            if (0 != recvData(readBuffer))
            {
                if (gPpBuf.fgEos)
                    break;
                usleep(1000);
            }
            else
            {
                DATA_INFO_T dataInfo;
                dataInfo.chNum = gPpBuf.chNum;
                dataInfo.samples = PP_SAMPLES;
                dataInfo.bytesPerSample = gPpBuf.bytesPerSample;
                dataInfo.pData = (short **)readBuffer;
                pp(&dataInfo);
                saveOneChInWave(readBuffer[0], PP_SAMPLES * gPpBuf.bytesPerSample, &waveInfo);
            }
        }
        updateWaveHeader(&waveInfo);
        fgEnd = 1;
    }
    
    int main(int argc, char **argv)
    {
    #if 0
        WAVE_INFO inputWaveInfo, outputWaveInfo;
        readWaveHeader(argv[1], &inputWaveInfo);
        //initWaveInfo(&outputWaveInfo, 2, 48000, 16);
    #endif
        
    #if 1
        pthread_t readThreadId, ppThreadId;
        initPpBuf(6, 3, PP_SAMPLES, 2);
        memset(&gFaderHandle, 0, sizeof(FADER_HANDLE_T));
        float curVolumDb = -96;
        float attuationDb = 96;
        FADER_TYPE_E type = FADER_TYPE_LINE;
        unsigned long timeMs = 5000;
        unsigned long sampleRate = 48000;
        faderInit(&gFaderHandle, attuationDb, type, timeMs, sampleRate, curVolumDb);
        pthread_create(&readThreadId, NULL, readThread, argv[1]);
        pthread_create(&ppThreadId, NULL, ppThread, argv[2]);
        while(!fgEnd)
        {
            sleep(1);
        }
    #endif
        return 0;
    }
  • 相关阅读:
    DNNClassifier 深度神经网络 分类器
    浏览器对MP4视频 帧宽度 高度的兼容性
    UnicodeEncodeError:'latin-1' codec can't encode character
    文件夹下 文件计数
    the largest value you actually can transmit between the client and server is determined by the amount of available memory and the size of the communications buffers.
    the “identity” of an object
    广告特征 用户特征
    如果一个维度全覆盖,则有效维度应该对该维度全覆盖
    a high-level neural networks AP
    使用 LDA 挖掘的用户喜好主题
  • 原文地址:https://www.cnblogs.com/fellow1988/p/9589261.html
Copyright © 2011-2022 走看看