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[];//"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 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 = ;
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)
{
printf("faderCalcGain\n");
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\n", pFaderHandle->curGain, pFaderHandle->curSample, pFaderHandle->timeInSample);
} 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 = 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));
}
}
} 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);
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);
} 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;
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;
initPpBuf(, , PP_SAMPLES, );
memset(&gFaderHandle, , sizeof(FADER_HANDLE_T));
float curVolumDb = -;
float attuationDb = ;
FADER_TYPE_E type = FADER_TYPE_LINE;
unsigned long timeMs = ;
unsigned long sampleRate = ;
faderInit(&gFaderHandle, attuationDb, type, timeMs, sampleRate, curVolumDb);
pthread_create(&readThreadId, NULL, readThread, argv[]);
pthread_create(&ppThreadId, NULL, ppThread, argv[]);
while(!fgEnd)
{
sleep();
}
#endif
return ;
}

fader的更多相关文章

  1. 关于 CSS 反射倒影的研究思考

    原文地址:https://css-tricks.com/state-css-reflections 译者:nzbin 友情提示:由于演示 demo 的兼容性,推荐火狐浏览.该文章篇幅较长,内容庞杂,有 ...

  2. jQuery动画高级用法——详解animation中的.queue()函数

    http://www.cnblogs.com/zhwl/p/4328279.html $('#object').hide('slow').queue(function(next){     $(thi ...

  3. Audio 的一些小笔记

    1.在做项目的过程中,对于volume 我们有一个volume curve,就是 0~63 step,每个step对应一个dB值,例如0step对应-90dB, 63 step对应0dB.关于这个0d ...

  4. Stealth视频教程学习笔记(第一章)

    Stealth视频教程学习笔记(第一章) 本文是对Unity官方视频教程Stealth的学习笔记.在此之前,本人整理了Stealth视频的英文字幕,并放到了优酷上.本文将分别对各个视频进行学习总结,提 ...

  5. Android Animation学习(三) ApiDemos解析:XML动画文件的使用

    Android Animation学习(三) ApiDemos解析:XML动画文件的使用 可以用XML文件来定义Animation. 文件必须有一个唯一的根节点: <set>, <o ...

  6. FadeTop – 定时休息提醒工具

    FadeTop 是款定时休息提醒工具,其特色是当设定时间到达时,将桌面渐变为指定的颜色,强制提醒但不影响桌面的任何操作 FadeTop is a visual break reminder for W ...

  7. 【JQuery NoviceToNinja系列】01 开篇 Html页面设计和布局

    01 开篇 Html页面设计和布局 index.html <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml ...

  8. Flex “跑马灯”效果(自定义“跑马灯”控件)

    自定义类(BroadCastMarquee.as): package marquee { import flash.events.MouseEvent; import flash.events.Tim ...

  9. jQuery动画高级用法(上)——详解animation中的.queue()动画队列插队函数

    决定对animate方面做一些总结,希望能给大家一些启发和帮助 从一个实际应用谈起 今天不谈animate().fadeIn().fadeOut().slideUp().show().hide()诸如 ...

随机推荐

  1. 《操作系统真象还原》ELF文件

    下面是第五章部分内容的收获. 用C语言编写内核 一直以来我们都是用汇编语言编写程序的,但接下来我们或许很少用汇编语言编写代码了,大多数都是使用C语言.为什么要这样呢?书上的解释我看的不是很懂,只能结合 ...

  2. Scala之Option: Some None

    Option类型本身没有实现,而是依赖两个子类型提供具体实习那:Some和None.Some是iyge类型参数化的单元素集合,None是一个空集合. ----<scala学习手册>P119

  3. C# NanUI WinFormium监听页面加载开始\结束

    个人博客 地址:https://www.wenhaofan.com/article/20190501213608 因为NanUI文档中仅介绍了Formium窗口的监听,但是没有WinFormium相关 ...

  4. Leetcode Week4 Find Minimum in Rotated Sorted Array II

    Question Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforeha ...

  5. Struts2-057远程代码执行漏洞(s2-057/CVE-2018-11776)复现

    参考了大佬的链接:https://github.com/jas502n/St2-057 00x01前言 Apache Struts是美国阿帕奇(Apache)软件基金会负责维护的一个开源项目,是一套用 ...

  6. 【你不知道的javaScript 上卷 笔记3】javaScript中的声明提升表现

    console.log( a ); var a = 2; 执行输出undefined a = 2; var a; console.log( a ); 执行输出2 说明:javaScript 运行时在编 ...

  7. vlan划分、本征vlan配置、中继

    命令部分: vlan划分(全局模式) vlan name v10 no shu no shu switchport access vlan vlan name v20 inter vlan no sh ...

  8. SDOI2010 粟粟的书架 lg2468(可持久化,前缀和)

    题面见https://www.luogu.org/problemnew/show/P2468 然后这道题属于合二为一题,看一眼数据范围就能发现 首先我们先考虑50分,二维前缀和维护一下(反正我不记得公 ...

  9. Java-杨辉三角(YangHuiTriangle)

    杨辉三角,是二项式系数在三角形中的一种几何排列. 杨辉三角概述 ☃ 每行端点与结尾的数为1 ☃ 每个数等于它上方两数之和 ☃ 每行数字左右对称,由1开始逐渐变大 ☃ 第n行的数字有n项 ☃ 前n行共[ ...

  10. 转行小白成长路--java基础

    每天都会发一篇,一点一滴,记录在这条路上的足迹.立个flag 2019年3月份至今已近一年,对信息技术有个大概的了解,个人认为对于这门技术更应该从最底层的原理入手,了解计算机演化的历史,从计算机语言到 ...