原理参考之前转载的matlab上关于DRC的描述。

目前主要实现了compressor和expander.

compressor:

Limit:

expander:

实现代码:

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<pthread.h>
#include<math.h>
typedef struct{
char chunkId[];//"RIFF"
unsigned long chunkSize;
char format[];//"WAVE"
}WAVE_RIFF;
typedef struct{
char chunkId[];//"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[];//"data"
unsigned long chunkSize;//NumSamples * NumChannels * BitsPerSample/8
}WAVE_DATA;
typedef struct
{
char fileName[];
FILE *fp;
long pos;
unsigned long totalSampleNum;
WAVE_RIFF riffChunk;
WAVE_FMT fmtChunk;
WAVE_DATA dataChunk;
}WAVE_INFO; #define READ_SAMPLES 1024
#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;
unsigned char fgInited;
}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 = ; typedef struct
{
unsigned long attackTimeMs;
unsigned long releaseTimeMs;
unsigned short ratio;
float thresholdDb;
}DRC_COMPRESSOR_PARAM_T;
typedef struct
{
unsigned long attackTimeMs;
unsigned long releaseTimeMs;
float thresholdDb;
}DRC_LIMITER_PARAM_T;
typedef struct
{
unsigned long attackTimeMs;
unsigned long releaseTimeMs;
unsigned long holdTimeMs;
unsigned short ratio;
float thresholdDb;
}DRC_EXPANDER_PARAM_T;
typedef enum
{
DRC_TYPE_COMPRESSOR,
DRC_TYPE_LIMITER,
DRC_TYPE_EXPANDER,
DRC_TYPE_AUTO,
}DRC_TYPE_E;
typedef struct
{
DRC_TYPE_E eDrcType;
union {
DRC_COMPRESSOR_PARAM_T compressorParams;
DRC_LIMITER_PARAM_T limiterParams;
DRC_EXPANDER_PARAM_T expanderParams;
}uDrcParams;
float curGain;
float curSmoothGainDb;
float alphaAttack;
float alphaRelease;
unsigned long attackHoldCounter;
unsigned long releaseHoldCounter;
}DRC_HANDLE_T; typedef struct
{
short sampleValue;
short bytesPerSample;
}SAMPLE_INFO_T; float dbToGain(float db);
DRC_HANDLE_T gDrcHandle;
void drcInit(DRC_HANDLE_T *pDrcHandle, void * pDrcParams, DRC_TYPE_E eDrcType)
{
DRC_COMPRESSOR_PARAM_T *pCompressorParams;
DRC_LIMITER_PARAM_T *pLimiterParams;
DRC_EXPANDER_PARAM_T *pExpanderParams;
if (pDrcHandle == NULL || pDrcParams == NULL || eDrcType > DRC_TYPE_AUTO)
return;
pDrcHandle->eDrcType = eDrcType;
switch (eDrcType)
{
case DRC_TYPE_COMPRESSOR:
pCompressorParams = (DRC_COMPRESSOR_PARAM_T *)pDrcParams;
memcpy(&pDrcHandle->uDrcParams.compressorParams, pCompressorParams, sizeof(DRC_COMPRESSOR_PARAM_T));
pDrcHandle->alphaAttack = expf(-logf() / ( * pCompressorParams->attackTimeMs / 1000));
pDrcHandle->alphaRelease = expf(-logf() / ( * pCompressorParams->releaseTimeMs / 1000));
break;
case DRC_TYPE_LIMITER:
pLimiterParams = (DRC_LIMITER_PARAM_T *)pDrcParams;
memcpy(&pDrcHandle->uDrcParams.limiterParams, pLimiterParams, sizeof(DRC_LIMITER_PARAM_T));
pDrcHandle->alphaAttack = expf(-logf() / ( * pLimiterParams->attackTimeMs / 1000));
pDrcHandle->alphaRelease = expf(-logf() / ( * pLimiterParams->releaseTimeMs / 1000));
break;
case DRC_TYPE_EXPANDER:
pExpanderParams = (DRC_EXPANDER_PARAM_T *)pDrcParams;
memcpy(&pDrcHandle->uDrcParams.expanderParams, pExpanderParams, sizeof(DRC_EXPANDER_PARAM_T));
pDrcHandle->alphaAttack = expf(-logf() / ( * pExpanderParams->attackTimeMs / 1000));
pDrcHandle->alphaRelease = expf(-logf() / ( * pExpanderParams->releaseTimeMs / 1000));
break;
case DRC_TYPE_AUTO:
break;
}
pDrcHandle->curGain = ;
pDrcHandle->curSmoothGainDb = ;
pDrcHandle->attackHoldCounter = ;
pDrcHandle->releaseHoldCounter = ;
} float sampleValueToDb(SAMPLE_INFO_T *pSampleInfo)
{
if (pSampleInfo == NULL)
return ;
if (pSampleInfo->sampleValue == )
pSampleInfo->sampleValue = ;
short maxSampleValue = (( << (pSampleInfo->bytesPerSample * )) - ) / ;
float db = * log10f((float)abs(pSampleInfo->sampleValue) / maxSampleValue);
//printf("maxSampleValue:%d, sampleValue:%d, db:%f\n", maxSampleValue, pSampleInfo->sampleValue, db);
return db;
} float drcComputeGainDb(DRC_HANDLE_T *pDrcHandle, float sampleDb)
{
if (pDrcHandle == NULL)
return ;
float staticChract;
switch (pDrcHandle->eDrcType)
{
case DRC_TYPE_COMPRESSOR:
if (sampleDb < pDrcHandle->uDrcParams.compressorParams.thresholdDb)
{
staticChract = sampleDb;
}
else
{
staticChract = pDrcHandle->uDrcParams.compressorParams.thresholdDb + (sampleDb - pDrcHandle->uDrcParams.compressorParams.thresholdDb) / pDrcHandle->uDrcParams.compressorParams.ratio;
}
break;
case DRC_TYPE_LIMITER:
if (sampleDb < pDrcHandle->uDrcParams.limiterParams.thresholdDb)
{
staticChract = sampleDb;
}
else
{
staticChract = pDrcHandle->uDrcParams.limiterParams.thresholdDb;
}
break;
case DRC_TYPE_EXPANDER:
if (sampleDb >= pDrcHandle->uDrcParams.expanderParams.thresholdDb)
{
staticChract = sampleDb;
}
else
{
staticChract = pDrcHandle->uDrcParams.expanderParams.thresholdDb + (sampleDb - pDrcHandle->uDrcParams.expanderParams.thresholdDb) / pDrcHandle->uDrcParams.expanderParams.ratio;
}
break;
case DRC_TYPE_AUTO:
break;
}
//printf("staticChract:%f, sampleDb:%f\n", staticChract, sampleDb);
return staticChract - sampleDb; } float drcCompressorSmoothGain(DRC_HANDLE_T *pDrcHandle, float computeGainDb)
{
float smoothGainDb;
if (computeGainDb < pDrcHandle->curSmoothGainDb)
{
smoothGainDb = pDrcHandle->alphaAttack * pDrcHandle->curSmoothGainDb + ( - pDrcHandle->alphaAttack) * computeGainDb;
}
else
{
smoothGainDb = pDrcHandle->alphaRelease * pDrcHandle->curSmoothGainDb + ( - pDrcHandle->alphaRelease) * computeGainDb;
}
return smoothGainDb;
} float drcExpanderSmoothGain(DRC_HANDLE_T *pDrcHandle, float computeGainDb)
{
float smoothGainDb;
unsigned long holdTimeInSample = pDrcHandle->uDrcParams.expanderParams.holdTimeMs * / ;
if (pDrcHandle->attackHoldCounter >= holdTimeInSample && computeGainDb > pDrcHandle->curSmoothGainDb)
{
smoothGainDb = pDrcHandle->alphaAttack * pDrcHandle->curSmoothGainDb + ( - pDrcHandle->alphaAttack) * computeGainDb;
}
else if (pDrcHandle->attackHoldCounter < holdTimeInSample && computeGainDb > pDrcHandle->curSmoothGainDb)
{
smoothGainDb = pDrcHandle->curSmoothGainDb;
pDrcHandle->attackHoldCounter++;
pDrcHandle->releaseHoldCounter = ;
}
else if (pDrcHandle->releaseHoldCounter >= holdTimeInSample && computeGainDb <= pDrcHandle->curSmoothGainDb)
{
smoothGainDb = pDrcHandle->alphaRelease * pDrcHandle->curSmoothGainDb + ( - pDrcHandle->alphaRelease) * computeGainDb;
}
else if (pDrcHandle->releaseHoldCounter < holdTimeInSample && computeGainDb <= pDrcHandle->curSmoothGainDb)
{
smoothGainDb = pDrcHandle->curSmoothGainDb;
pDrcHandle->releaseHoldCounter++;
pDrcHandle->attackHoldCounter = ;
}
return smoothGainDb;
}
float drcSmoothGain(DRC_HANDLE_T *pDrcHandle, float computeGainDb)
{
if (pDrcHandle == NULL)
return ;
float smoothGainDb;
switch (pDrcHandle->eDrcType)
{
case DRC_TYPE_COMPRESSOR:
case DRC_TYPE_LIMITER:
smoothGainDb = drcCompressorSmoothGain(pDrcHandle, computeGainDb);
break;
case DRC_TYPE_EXPANDER:
smoothGainDb = drcExpanderSmoothGain(pDrcHandle, computeGainDb);
break;
case DRC_TYPE_AUTO:
break;
}
return smoothGainDb;
}
void drcCalGain(DRC_HANDLE_T *pDrcHandle, SAMPLE_INFO_T *pSampleInfo)
{
if (pDrcHandle == NULL || pSampleInfo == NULL)
return;
float sampleDb = sampleValueToDb(pSampleInfo);
float computeGainDb = drcComputeGainDb(pDrcHandle, sampleDb);
pDrcHandle->curSmoothGainDb = drcSmoothGain(pDrcHandle, computeGainDb);
pDrcHandle->curGain = dbToGain(pDrcHandle->curSmoothGainDb);
printf("sampleDb:%f, computeGainDb:%f, smoothGainDb:%f, curGain:%f\n",
sampleDb, computeGainDb, pDrcHandle->curSmoothGainDb, pDrcHandle->curGain);
} void drc(DRC_HANDLE_T *pDrcHandle, DATA_INFO_T *pDataInfo)
{
unsigned short sampleIdx, chIdx;
SAMPLE_INFO_T sampleInfo;
for (chIdx = ; chIdx < pDataInfo->chNum; chIdx++)
{
for (sampleIdx = ; sampleIdx < pDataInfo->samples; sampleIdx++)
{
sampleInfo.bytesPerSample = ;
sampleInfo.sampleValue = pDataInfo->pData[chIdx][sampleIdx];
drcCalGain(pDrcHandle, &sampleInfo);
pDataInfo->pData[chIdx][sampleIdx] *= pDrcHandle->curGain;
}
}
} 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 + ) * sizeof(float));
pFaderHandle->segNum = segNum;
float tmp;
if (pFaderHandle->faderParams.type != FADER_TYPE_CUBIC)
return;
//0~1 divide into N seg.
for (segIdx = ; segIdx < segNum + ; 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(, db/);
}
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 / ;
pFaderHandle->curGain = pFaderHandle->startGain = dbToGain(curVolumDb);
pFaderHandle->targetGain = dbToGain(curVolumDb + attuationDb);
pFaderHandle->curSample = ;
faderPrepareShape(pFaderHandle, );
printf("faderInit\n");
} void faderCalGain(FADER_HANDLE_T *pFaderHandle)
{
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 + ];
step = (endGainInCurSeg - startGainInCurSeg) / samplesInSeg;
if (pFaderHandle->curSample == startSampleInCurSeg)
pFaderHandle->curGain = startGainInCurSeg;
else
pFaderHandle->curGain += step;
break;
}
printf("curGain:%f, curSample:%ld, timeInSample:%ld, curSeg:%d, startGain:%f, endGain:%f\n", pFaderHandle->curGain, pFaderHandle->curSample, pFaderHandle->timeInSample, curSeg, startGainInCurSeg, endGainInCurSeg);
} void fader(FADER_HANDLE_T *pFaderHandle, DATA_INFO_T *pDataInfo)
{
unsigned short sampleIdx, chIdx;
for (sampleIdx = ; sampleIdx < pDataInfo->samples; sampleIdx++)
{
if (pFaderHandle->curSample != pFaderHandle->timeInSample)
{
faderCalGain(pFaderHandle);
pFaderHandle->curSample++;
}
for (chIdx = ; chIdx < pDataInfo->chNum; chIdx++)
{
pDataInfo->pData[chIdx][sampleIdx] *= pFaderHandle->curGain;
}
}
}
void printWaveHeader(WAVE_INFO *pWaveInfo)
{
printf("fileName:%s\n", pWaveInfo->fileName);
printf("riff chunk:\n");
printf("chunkId:%c%c%c%c\n", pWaveInfo->riffChunk.chunkId[], pWaveInfo->riffChunk.chunkId[], pWaveInfo->riffChunk.chunkId[], pWaveInfo->riffChunk.chunkId[]);
printf("chunkSize:%ld\n", pWaveInfo->riffChunk.chunkSize);
printf("format:%c%c%c%c\n", pWaveInfo->riffChunk.format[], pWaveInfo->riffChunk.format[], pWaveInfo->riffChunk.format[], pWaveInfo->riffChunk.format[]);
printf("fmt chunk:\n");
printf("chunkId:%c%c%c\n", pWaveInfo->fmtChunk.chunkId[], pWaveInfo->fmtChunk.chunkId[], pWaveInfo->fmtChunk.chunkId[]);
printf("chunkSize:%ld\n", pWaveInfo->fmtChunk.chunkSize);
printf("audioFormat:%d\n", pWaveInfo->fmtChunk.audioFormat);
printf("chNum:%d\n", pWaveInfo->fmtChunk.chNum);
printf("sampleRate:%ld\n", pWaveInfo->fmtChunk.sampleRate);
printf("byteRate:%ld\n", pWaveInfo->fmtChunk.byteRate);
printf("blockAlign:%d\n", pWaveInfo->fmtChunk.blockAlign);
printf("bitsPerSample:%d\n", pWaveInfo->fmtChunk.bitsPerSample);
printf("data chunk:\n");
printf("chunkId:%c%c%c%c\n", pWaveInfo->dataChunk.chunkId[], pWaveInfo->dataChunk.chunkId[], pWaveInfo->dataChunk.chunkId[], pWaveInfo->dataChunk.chunkId[]);
printf("chunkSize:%ld\n", 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[] = 'R';
pWaveInfo->riffChunk.chunkId[] = 'I';
pWaveInfo->riffChunk.chunkId[] = 'F';
pWaveInfo->riffChunk.chunkId[] = 'F';
pWaveInfo->riffChunk.chunkSize = ;
//strncpy(pWaveInfo->riffChunk.format, "WAVE", 4);
pWaveInfo->riffChunk.format[] = 'W';
pWaveInfo->riffChunk.format[] = 'A';
pWaveInfo->riffChunk.format[] = 'V';
pWaveInfo->riffChunk.format[] = 'E';
//strncpy(pWaveInfo->fmtChunk.chunkId, "fmt", 3);
pWaveInfo->fmtChunk.chunkId[] = 'f';
pWaveInfo->fmtChunk.chunkId[] = 'm';
pWaveInfo->fmtChunk.chunkId[] = 't';
pWaveInfo->fmtChunk.chunkId[] = ' ';
pWaveInfo->fmtChunk.chunkSize = 16;//sizeof(WAVE_FMT) - ;
pWaveInfo->fmtChunk.audioFormat = ;
pWaveInfo->fmtChunk.chNum = chNum;
pWaveInfo->fmtChunk.sampleRate = sampleRate;
pWaveInfo->fmtChunk.byteRate = sampleRate * chNum * bitsPerSample / ;
pWaveInfo->fmtChunk.blockAlign = chNum * bitsPerSample / ;
pWaveInfo->fmtChunk.bitsPerSample = bitsPerSample;
//strncpy(pWaveInfo->dataChunk.chunkId, "data", 4);
pWaveInfo->dataChunk.chunkId[] = 'd';
pWaveInfo->dataChunk.chunkId[] = 'a';
pWaveInfo->dataChunk.chunkId[] = 't';
pWaveInfo->dataChunk.chunkId[] = 'a'; pWaveInfo->dataChunk.chunkSize = ;
pWaveInfo->totalSampleNum = ;
///printWaveHeader(pWaveInfo);
} void rwRiffChunk(WAVE_INFO *pWaveInfo, unsigned char fgRead)
{
if (fgRead)
{
fread((char *)&pWaveInfo->riffChunk.chunkId, , , pWaveInfo->fp);
fread((char *)&pWaveInfo->riffChunk.chunkSize, , , pWaveInfo->fp);
fread((char *)&pWaveInfo->riffChunk.format, , , pWaveInfo->fp);
}
else
{
fwrite((char *)&pWaveInfo->riffChunk.chunkId, , , pWaveInfo->fp);
fwrite((char *)&pWaveInfo->riffChunk.chunkSize, , , pWaveInfo->fp);
fwrite((char *)&pWaveInfo->riffChunk.format, , , pWaveInfo->fp);
}
}
void rwFmtChunk(WAVE_INFO *pWaveInfo, unsigned char fgRead)
{
if (fgRead)
{
fread((char *)&pWaveInfo->fmtChunk.chunkId, , , pWaveInfo->fp);
fread((char *)&pWaveInfo->fmtChunk.chunkSize, , , pWaveInfo->fp);
fread((char *)&pWaveInfo->fmtChunk.audioFormat, , , pWaveInfo->fp);
fread((char *)&pWaveInfo->fmtChunk.chNum, , , pWaveInfo->fp);
fread((char *)&pWaveInfo->fmtChunk.sampleRate, , , pWaveInfo->fp);
fread((char *)&pWaveInfo->fmtChunk.byteRate, , , pWaveInfo->fp);
fread((char *)&pWaveInfo->fmtChunk.blockAlign, , , pWaveInfo->fp);
fread((char *)&pWaveInfo->fmtChunk.bitsPerSample, , , pWaveInfo->fp);
}
else
{
fwrite((char *)&pWaveInfo->fmtChunk.chunkId, , , pWaveInfo->fp);
fwrite((char *)&pWaveInfo->fmtChunk.chunkSize, , , pWaveInfo->fp);
fwrite((char *)&pWaveInfo->fmtChunk.audioFormat, , , pWaveInfo->fp);
fwrite((char *)&pWaveInfo->fmtChunk.chNum, , , pWaveInfo->fp);
fwrite((char *)&pWaveInfo->fmtChunk.sampleRate, , , pWaveInfo->fp);
fwrite((char *)&pWaveInfo->fmtChunk.byteRate, , , pWaveInfo->fp);
fwrite((char *)&pWaveInfo->fmtChunk.blockAlign, , , pWaveInfo->fp);
fwrite((char *)&pWaveInfo->fmtChunk.bitsPerSample, , , pWaveInfo->fp); }
}
void rwDataChunk(WAVE_INFO *pWaveInfo, unsigned char fgRead)
{
if (fgRead)
{
fread((char *)&pWaveInfo->dataChunk.chunkId, , , pWaveInfo->fp);
fread((char *)&pWaveInfo->dataChunk.chunkSize, , , pWaveInfo->fp);
}
else
{
fwrite((char *)&pWaveInfo->dataChunk.chunkId, , , pWaveInfo->fp);
fwrite((char *)&pWaveInfo->dataChunk.chunkSize, , , 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\n", errno);
return;
}
#if 0
retSize = fread((char *)&pWaveInfo->riffChunk, sizeof(WAVE_RIFF), , pWaveInfo->fp);
retSize = fread((char *)&pWaveInfo->fmtChunk, sizeof(WAVE_FMT), , pWaveInfo->fp);
retSize = fread((char *)&pWaveInfo->dataChunk, sizeof(WAVE_DATA), , pWaveInfo->fp);
#endif
rwRiffChunk(pWaveInfo, );
rwFmtChunk(pWaveInfo, );
rwDataChunk(pWaveInfo, );
pWaveInfo->pos = ftell(pWaveInfo->fp);
pWaveInfo->totalSampleNum = pWaveInfo->dataChunk.chunkSize / (pWaveInfo->fmtChunk.bitsPerSample / );
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 = ;
gPpBuf.fgEos = ;
gPpBuf.pData = (unsigned char ***)malloc(chNum * sizeof(unsigned char **));
for (chIdx = ; chIdx < chNum; chIdx++)
{
gPpBuf.pData[chIdx] = (unsigned char **)malloc(bankNum * sizeof(unsigned char *));
for (bankIdx =; bankIdx < bankNum; bankIdx++)
{
gPpBuf.pData[chIdx][bankIdx] = (unsigned char *) malloc(samplesPerBank * bytesPerSample * sizeof(unsigned char));
}
}
gPpBuf.fgInited = ;
} int sendData(unsigned char *writeBuffer, unsigned short chNum)
{
unsigned short sampleIdx, chIdx, byteIdx;
//printf("sendData, wp:%d, rp:%d\n", gPpBuf.bankWp, gPpBuf.bankRp);
if ((gPpBuf.bankWp + ) % gPpBuf.bankNum == gPpBuf.bankRp)
{
//full
return ;
}
else
{
for (sampleIdx = ; sampleIdx < PP_SAMPLES; sampleIdx++)
{
for (chIdx =; chIdx < chNum; chIdx++)
{
for (byteIdx = ; byteIdx < gPpBuf.bytesPerSample; byteIdx++)
{
gPpBuf.pData[chIdx][gPpBuf.bankWp][sampleIdx * gPpBuf.bytesPerSample + byteIdx] = writeBuffer[(chIdx + sampleIdx * chNum) * gPpBuf.bytesPerSample + byteIdx];
}
}
}
gPpBuf.bankWp = (gPpBuf.bankWp + ) % gPpBuf.bankNum;
}
return ;
} int recvData(unsigned char **readBuffer)
{
unsigned short chIdx;
//printf("recvData, wp:%d, rp:%d\n", gPpBuf.bankWp, gPpBuf.bankRp);
if (gPpBuf.bankWp == gPpBuf.bankRp)
{
//empty
return ;
}
else
{
for (chIdx = ; chIdx < gPpBuf.chNum; chIdx++)
{
memcpy(&readBuffer[chIdx][], &gPpBuf.pData[chIdx][gPpBuf.bankRp][], PP_SAMPLES * gPpBuf.bytesPerSample * sizeof(unsigned char));
}
gPpBuf.bankRp = (gPpBuf.bankRp + ) % gPpBuf.bankNum;
}
return ;
}
void *readThread(void *arg)
{
char *fileName = (char *)arg;
size_t retSize;
WAVE_INFO waveInfo;
memset(&waveInfo, , sizeof(WAVE_INFO));
unsigned long bytesPerLoop;
unsigned short loopIdx, loop;
unsigned long readCount = ;
readWaveHeader(fileName, &waveInfo);
initPpBuf(waveInfo.fmtChunk.chNum, , PP_SAMPLES, ); unsigned long readSize = READ_SAMPLES * waveInfo.fmtChunk.chNum * waveInfo.fmtChunk.bitsPerSample / ;
printf("readSize:%ld\n", readSize);
unsigned char *readBuffer = (unsigned char *)malloc(readSize * sizeof(unsigned char));
waveInfo.fp = fopen(fileName, "rb");
fseek(waveInfo.fp, waveInfo.pos, SEEK_SET);
while ()
{
retSize = fread(readBuffer, readSize, , waveInfo.fp);
if (retSize <= )
{
printf("fread fail,retSize:%d, %s, eof:%d, readCount:%ld\n", (int) retSize, strerror(errno), feof(waveInfo.fp), readCount);
gPpBuf.fgEos = ;
break;
}
else
{
bytesPerLoop = PP_SAMPLES *waveInfo.fmtChunk.chNum * waveInfo.fmtChunk.bitsPerSample / ;
loop = readSize / bytesPerLoop;
loopIdx = ;
while (loopIdx < loop)
{
if ( != sendData(readBuffer + loopIdx * bytesPerLoop, waveInfo.fmtChunk.chNum))
{
usleep();
}
else
{
loopIdx++;
}
}
readCount++;
}
}
return NULL;
}
void pp(DATA_INFO_T *pDataInfo)
{
//fader(&gFaderHandle, pDataInfo);
drc(&gDrcHandle, pDataInfo);
} void saveOneChInWave(unsigned char *pData, unsigned long size, WAVE_INFO *pWaveInfo)
{
size_t retSize = ;
if (pWaveInfo->fp == NULL)
{
pWaveInfo->fp = fopen(pWaveInfo->fileName, "wb");
#if 0
retSize = fwrite((char *)&pWaveInfo->riffChunk, sizeof(WAVE_RIFF), , pWaveInfo->fp);
retSize = fwrite((char *)&pWaveInfo->fmtChunk, sizeof(WAVE_FMT), , pWaveInfo->fp);
retSize = fwrite((char *)&pWaveInfo->dataChunk, sizeof(WAVE_DATA), , pWaveInfo->fp);
#endif
rwRiffChunk(pWaveInfo, );
rwFmtChunk(pWaveInfo, );
rwDataChunk(pWaveInfo, );
}
retSize = fwrite(pData, size, , pWaveInfo->fp);
pWaveInfo->totalSampleNum += (size / pWaveInfo->fmtChunk.chNum / (pWaveInfo->fmtChunk.bitsPerSample / ));
pWaveInfo->pos = ftell(pWaveInfo->fp);
} void updateWaveHeader(WAVE_INFO *pWaveInfo)
{
size_t retSize;
pWaveInfo->riffChunk.chunkSize = pWaveInfo->pos - ;
pWaveInfo->dataChunk.chunkSize = pWaveInfo->totalSampleNum * pWaveInfo->fmtChunk.chNum * pWaveInfo->fmtChunk.bitsPerSample / ;
fseek(pWaveInfo->fp, , SEEK_SET);
#if 0
retSize = fwrite((char *)&pWaveInfo->riffChunk, sizeof(WAVE_RIFF), , pWaveInfo->fp);
retSize = fwrite((char *)&pWaveInfo->fmtChunk, sizeof(WAVE_FMT), , pWaveInfo->fp);
retSize = fwrite((char *)&pWaveInfo->dataChunk, sizeof(WAVE_DATA), , pWaveInfo->fp);
#endif
rwRiffChunk(pWaveInfo, );
rwFmtChunk(pWaveInfo, );
rwDataChunk(pWaveInfo, );
fclose(pWaveInfo->fp); printWaveHeader(pWaveInfo);
}
void *ppThread(void *arg)
{
char *fileName = (char *)arg;
WAVE_INFO waveInfo;
memset(&waveInfo, , sizeof(waveInfo));
strncpy(waveInfo.fileName, fileName, strlen(fileName));
printf("out file:%s\n", waveInfo.fileName);
waveInfo.fp = NULL;
while(!gPpBuf.fgInited)
{
usleep();
}
initWaveInfo(&waveInfo, , , );
unsigned char **readBuffer = (unsigned char **)malloc(gPpBuf.chNum * sizeof(unsigned char *));
unsigned short chIdx;
for(chIdx = ; chIdx < gPpBuf.chNum; chIdx++)
{
readBuffer[chIdx] = (unsigned char *)malloc(PP_SAMPLES * gPpBuf.bytesPerSample * sizeof(unsigned char));
}
while ()
{
if ( != recvData(readBuffer))
{
if (gPpBuf.fgEos)
break;
usleep();
}
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[], PP_SAMPLES * gPpBuf.bytesPerSample, &waveInfo);
}
}
updateWaveHeader(&waveInfo);
fgEnd = ;
} int main(int argc, char **argv)
{
#if 0
WAVE_INFO inputWaveInfo, outputWaveInfo;
readWaveHeader(argv[], &inputWaveInfo);
//initWaveInfo(&outputWaveInfo, 2, 48000, 16);
#endif #if 1
pthread_t readThreadId, ppThreadId;
memset(&gPpBuf, , sizeof(PP_BUF_T));
// initPpBuf(6, 3, PP_SAMPLES, 2);
#if 0
memset(&gFaderHandle, , sizeof(FADER_HANDLE_T));
float curVolumDb = ;
float attuationDb = -;
FADER_TYPE_E type = FADER_TYPE_CUBIC;
unsigned long timeMs = ;
unsigned long sampleRate = ;
faderInit(&gFaderHandle, attuationDb, type, timeMs, sampleRate, curVolumDb);
#endif
memset(&gDrcHandle, , sizeof(DRC_HANDLE_T));
#if 0
DRC_COMPRESSOR_PARAM_T compressorParams;
compressorParams.thresholdDb = -;
compressorParams.attackTimeMs = ;
compressorParams.releaseTimeMs = 20;
compressorParams.ratio = ;
drcInit(&gDrcHandle, &compressorParams, DRC_TYPE_COMPRESSOR);
#endif
DRC_LIMITER_PARAM_T limiterParams;
limiterParams.thresholdDb = -;
limiterParams.attackTimeMs = ;
limiterParams.releaseTimeMs = ;
drcInit(&gDrcHandle, &limiterParams, DRC_TYPE_LIMITER);
#if 0
DRC_EXPANDER_PARAM_T expanderParams;
expanderParams.thresholdDb = -;
expanderParams.attackTimeMs = ;
expanderParams.releaseTimeMs = ;
expanderParams.ratio = ;
expanderParams.holdTimeMs = ;
drcInit(&gDrcHandle, &expanderParams, DRC_TYPE_EXPANDER);
#endif
pthread_create(&readThreadId, NULL, readThread, argv[]);
pthread_create(&ppThreadId, NULL, ppThread, argv[]);
while(!fgEnd)
{
sleep();
}
#endif
return ;
}

drc实现的更多相关文章

  1. [转]or cad drc 错误

    本文转自 恋上姐的博客 http://blog.sina.com.cn/u/1750715103 用“取缔”一词,是源自<嘻哈四重奏>里面卢导的口头禅,哈哈借用一下!大多数DRC warn ...

  2. 571亿背后:DRC助阿里实现异地双活

    571亿背后:DRC助阿里实现异地双活 赶集网SQL自动上线

  3. Altium Designer 10 执行DRC发现有 Length Constraint 解决办法

    在PCB布局连线结束后,执行DRC,结果Length Constraint 报错,如图: 在Design Rules中找对应的规则约束,怎么也找不见. 其实是,在差分对进行等长蛇形绕线的步骤中,约束了 ...

  4. PCM EQ DRC 音频处理

    PCM Pulse-code modulation的缩写,中文译名是脉冲编码调制.(I2S仅仅是PCM的一个分支,接口定义都是一样的, I2S的采样频率一般为44.1KHZ和48KHZ做,PCM采样频 ...

  5. 谷歌开发的draco格式文件将obj文件压缩成drc文件后将大大减小文件大小(threejs加载有mtl文件的drc文件)

    问题描述:当前threejs是92版本 但是当前版本还没有能够直接加载带贴图文件的drc格式的loader: 解决办法:先加载mtl文件将obj文件分解(按照mtl文件内材质贴图信息进行分解)再将分解 ...

  6. ORCAD常见DRC错误

    一下就是网上整理的: https://blog.csdn.net/weixin_39671078/article/details/85344762 https://wenku.baidu.com/vi ...

  7. AAC DRC

    DRC feature 在AAC decoder是optional.DRC info是在编码在fill element. Program reference level是进行DRC的一个参考值.是原始 ...

  8. 转:进行vivado开发时,Generate Bitstream报错[DRC NSTD-1],详细解决步骤

    报错如下 [Drc 23-20] Rule violation (NSTD-1) Unspecified I/O Standard - 4 out of 142 logical ports use I ...

  9. AD进行行PCB DRC检查时,软件提示...report_drc.xsl不存在

    之前装过一次AD软件没有报过这样的错误,卸掉后重新装了之后,在对电气规则检查检查时“软件提示...report_drc.xsl不存在”. 原因:之前装的目录默认在C盘下,所以AD软件输出的报告也是默认 ...

随机推荐

  1. Selenium3+python自动化016-Selenium Grid

    一.Selenium Grid介绍 1.概念 Selenium Grid组件专门用于远程分布式测试或并发测试,通过并发执行测试用例的方式可以提高测试用例的执行速度和效率,解决界面自动化测试执行速度过慢 ...

  2. Qt多线程实现思路二

    建立一个继承于Qobject的类myThread 在类myThread中定义线程处理函数不必是思路一里的run(); 在窗口类中开辟一个自定义线程myThread的指针对象myT = new myTh ...

  3. Python标准库之re模块

    re模块用于正则表达式. 正则表达式在线测试:http://c.runoob.com/front-end/854 正则表达式元字符可以参考:https://www.w3cschool.cn/zheng ...

  4. 风变编程笔记(一)-Python基础语法

    第0关  print()函数与变量 1. print()函数print()函数:告诉计算机,把括号的内容显示在屏幕上 # 不带引号 print(1+1) # 让计算机读懂括号里的内容,打印最终的结果 ...

  5. (1)-Android学习笔记之:初识Android系统架构和项目结构

    Android系统架构 Android程序结构 创建一个Android项目,为初学便于理解,将程序项目结构切换为Project模式,项目结构如下 .gradle和.idea:这两个目录下放的都是And ...

  6. bookdown学习笔记

    主要参考大佬谢益辉的bookdown学习笔记 https://bookdown.org/yihui/bookdown/pandoc.html 灰常之详细 然后clone了他写好的小demo,准备自己试 ...

  7. [Python]find_all函数 2020.2.7

    .find_all(name,attrs,recursive,string,**kwargs) name:对标签名称的检索字符串attrs:对标签属性值的检索字符串,可标注属性检索recursive: ...

  8. Echart的使用legend遇到的问题小记

    Echart的图标真的很漂亮,使用也相对简单.但是官网的配置项的例子我不是很能快速的使用,得思考一会.哈哈,可能我比较笨吧. 在作柱状图的时候,我是通过Ajax动态获取的数据,但是图例legend就是 ...

  9. 执行python程序的方式

    1.交互器 程序不能永久保存 主要用于简单的语法测试相关 2.文件执行

  10. 在用vue-cli4创建的vue2.x项目中通过vue-fontawesome使用fontawesome5

    前言 本文写于2020年1月11日,仅提供最基本的引用方法,参考fontawesome5英文官方文档和vue-fontawesome英文官方文档. 正文 在vue项目中使用fontawesome5图标 ...