原理参考之前转载的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. web服务器的解析漏洞罗列

    前言 服务器相关中间件存在一些解析漏洞,攻击者可通过上传一定格式的文件,被服务器的中间件进行了解析,这样就对系统造成一定危害.常见的服务器解析漏洞涉及的中间件有IIS,apache.nginx等.可利 ...

  2. [Python]爬取首都之窗百姓信件网址id python 2020.2.13

    经人提醒忘记发网址id的爬取过程了, http://www.beijing.gov.cn/hudong/hdjl/com.web.consult.consultDetail.flow?original ...

  3. link(外部资源关系)

    规定了外部资源与当前文档的关系 常于链接样式表<link href="/media/examples/link-element-example.css" rel=" ...

  4. 【你不知道的javaScript 上卷 笔记7】javaScript中对象的[[Prototype]]机制

    [[Prototype]]机制 [[Prototype]]是对象内部的隐试属性,指向一个内部的链接,这个链接的作用是:如果在对象上没有找到需要的属性或者方法引用,引擎就 会继续在 [[Prototyp ...

  5. jmeter测试出现端口占用

    原文地址:https://www.cnblogs.com/deepSleeping/p/12067654.html Jmeter测试会出现端口占用情况 这边在这里做个记录,每次都要百度查询,刚好需要整 ...

  6. php安装xdebug扩展,PHPStorm+XDebug单步调试

    (一)php安装xdebug扩展,PHPStorm+XDebug单步调试 (二)PHPStorm配置XDebug (三)PHPStorm使用XDebug调试 (四)PhpStorm+Xdebug配置单 ...

  7. WebMethods开发入门

    webMethods  Integration Platform 由用于设计.执行和管理集成解决方案的 3 类组件构成. 设计时组件:这些组件提供了开发和测试集成解决方案的工具. 1.webMetho ...

  8. linux C++ 读取mysql结果保存

    c++读取mysql数据库结果保存 #include <fstream> #include <iomanip> #include <iostream> #inclu ...

  9. Mac 多版本 JDK 管理

    Mac 多版本 JDK 管理 1. 准备 ZSH Homebrew Oracle JDK 1.8 安装包(Homebrew 官方源和第三方源不再提供老版本的 Oracle JDK) 2. 安装 JDK ...

  10. R语言函数化学习笔记3

    R语言函数化学习笔记3 R语言常用的一些命令函数 1.getwd()查看当前R的工作目录 2.setwd()修改当前工作目录 3.str()可以输出指定对象的结构(类型,位置等),同理还有class( ...