fader
发布时间:2020-12-14 03:47:02 所属栏目:大数据 来源:网络整理
导读:? fader在音频处理中是比较基础的处理。通常用于平滑的调节音量,或是音频的渐入和渐出效果。 比较常见的fader有line和cubic线型的fader。 line fader即fader的渐变过程是线性的。cubic的渐变过程是三次曲线。 line fader: 5s内衰减5db 5s时间fader in ? ?
? fader在音频处理中是比较基础的处理。通常用于平滑的调节音量,或是音频的渐入和渐出效果。 比较常见的fader有line和cubic线型的fader。 line fader即fader的渐变过程是线性的。cubic的渐变过程是三次曲线。 line fader: 5s内衰减5db 5s时间fader in ? ? ? ? ?实现代码如下: #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("faderInitn"); } void faderCalGain(FADER_HANDLE_T *pFaderHandle) { printf("faderCalcGainn"); 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:%ldn",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:%sn",pWaveInfo->fileName); printf("riff chunk:n"); printf("chunkId:%c%c%c%cn",pWaveInfo->riffChunk.chunkId[0],pWaveInfo->riffChunk.chunkId[1],pWaveInfo->riffChunk.chunkId[2],pWaveInfo->riffChunk.chunkId[3]); printf("chunkSize:%ldn",pWaveInfo->riffChunk.chunkSize); printf("format:%c%c%c%cn",pWaveInfo->riffChunk.format[0],pWaveInfo->riffChunk.format[1],pWaveInfo->riffChunk.format[2],pWaveInfo->riffChunk.format[3]); printf("fmt chunk:n"); printf("chunkId:%c%c%cn",pWaveInfo->fmtChunk.chunkId[0],pWaveInfo->fmtChunk.chunkId[1],pWaveInfo->fmtChunk.chunkId[2]); printf("chunkSize:%ldn",pWaveInfo->fmtChunk.chunkSize); printf("audioFormat:%dn",pWaveInfo->fmtChunk.audioFormat); printf("chNum:%dn",pWaveInfo->fmtChunk.chNum); printf("sampleRate:%ldn",pWaveInfo->fmtChunk.sampleRate); printf("byteRate:%ldn",pWaveInfo->fmtChunk.byteRate); printf("blockAlign:%dn",pWaveInfo->fmtChunk.blockAlign); printf("bitsPerSample:%dn",pWaveInfo->fmtChunk.bitsPerSample); printf("data chunk:n"); printf("chunkId:%c%c%c%cn",pWaveInfo->dataChunk.chunkId[0],pWaveInfo->dataChunk.chunkId[1],pWaveInfo->dataChunk.chunkId[2],pWaveInfo->dataChunk.chunkId[3]); printf("chunkSize:%ldn",pWaveInfo->dataChunk.chunkSize); } void initWaveInfo(WAVE_INFO *pWaveInfo,unsigned short chNum,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,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,2,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:%dn",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,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:%dn",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,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:%ldn",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:%ldn",(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,pWaveInfo->fp); retSize = fwrite((char *)&pWaveInfo->fmtChunk,pWaveInfo->fp); retSize = fwrite((char *)&pWaveInfo->dataChunk,pWaveInfo->fp); #endif rwRiffChunk(pWaveInfo,0); rwFmtChunk(pWaveInfo,0); rwDataChunk(pWaveInfo,0); } retSize = fwrite(pData,size,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,pWaveInfo->fp); retSize = fwrite((char *)&pWaveInfo->fmtChunk,pWaveInfo->fp); retSize = fwrite((char *)&pWaveInfo->dataChunk,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,sizeof(waveInfo)); strncpy(waveInfo.fileName,strlen(fileName)); printf("out file:%sn",waveInfo.fileName); waveInfo.fp = NULL; initWaveInfo(&waveInfo,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,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,ppThread,argv[2]); while(!fgEnd) { sleep(1); } #endif return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |