之前音频采集使用16位双声道(都快过去10年了)。利用faac编码没什么问题,现在心血来潮,想用更高级的32位,float进行采样,本以为依葫芦画瓢就行,没想到完全不行。这里看了源码,才知道怎么用,
避免之后的同胞入坑
demo见https://gitcode.net/bener2008zj/MediaDemo/-/tree/master/faacdemo
源码main.c中所有的采样都转化为float格式,跟WAV中读取的无关
myFormat->inputFormat = FAAC_INPUT_FLOAT;
读取函数可看input.c中,不管WAV原来是什么读取都为float,关键WAV是本身就是float还是要重新处理下
size_t wav_read_float32(pcmfile_t *sndf, float *buf, size_t num, int *map)
......
if (sndf->isfloat)
{
switch (sndf->samplebytes) {
case 4:
buf[cnt] *= 32768.0;
break;
default:
return 0;
}
continue;
}
修改方案
判断采样类型
if(waveFormat.wFormatTag==3){
pFaacConf->inputFormat=FAAC_INPUT_FLOAT;
}else{
if(waveFormat.wBitsPerSample==16){
pFaacConf->inputFormat=FAAC_INPUT_16BIT;
}else{
pFaacConf->inputFormat=FAAC_INPUT_32BIT;
}
}
处理采样数据
inputSamples=RealInputBytes/(waveFormat.wBitsPerSample/8);
if(waveFormat.wFormatTag==1&&waveFormat.wBitsPerSample==32){
int i=0;
int32_t*in=(int32_t*)inputbuffer;
for(i=0;i<inputSamples;i++){
in[i]/=256;
//库函数还会/256,最后等价于16位
}
}
if(waveFormat.wFormatTag==3){
int i=0;
float *buf=(float*)inputbuffer;
for(i=0;i<inputSamples;i++){
buf[i]*=32768.0;
}
}
各版本可能会有不同,当前看的版本为faac-1.29.9.2
主要看frame.c文件就行
在函数faacEncSetConfiguration中有这样的判断
switch( hEncoder->config.inputFormat )
{
case FAAC_INPUT_16BIT:
//case FAAC_INPUT_24BIT:
case FAAC_INPUT_32BIT:
case FAAC_INPUT_FLOAT:
break;
default:
return 0;
break;
}
if (hEncoder->config.aacObjectType != LOW)
return 0;
意味着只支持3种输入格式,24位的不支持
并且aacObjectType只能用LOW(以前用的旧版本没有这个限制)
输入格式FAAC_INPUT_16BIT是支持的,不用二次处理
输入格式FAAC_INPUT_FLOAT需要二次处理
输入格式FAAC_INPUT_32BIT也需要二次处理
faacEncEncode中有如下代码
switch( hEncoder->config.inputFormat )
{
case FAAC_INPUT_16BIT:
{
short *input_channel = (short*)inputBuffer + hEncoder->config.channel_map[channel];
for (i = 0; i < samples_per_channel; i++)
{
hEncoder->next3SampleBuff[channel][i] = (double)*input_channel;
input_channel += numChannels;
}
}
break;
case FAAC_INPUT_32BIT:
{
int32_t *input_channel = (int32_t*)inputBuffer + hEncoder->config.channel_map[channel];
for (i = 0; i < samples_per_channel; i++)
{
hEncoder->next3SampleBuff[channel][i] = (1.0/256) * (double)*input_channel;
input_channel += numChannels;
}
}
break;
case FAAC_INPUT_FLOAT:
{
float *input_channel = (float*)inputBuffer + hEncoder->config.channel_map[channel];
for (i = 0; i < samples_per_channel; i++)
{
hEncoder->next3SampleBuff[channel][i] = (double)*input_channel;
input_channel += numChannels;
}
}
break;
default:
return -1; /* invalid input format */
break;
}
int32之前已经除以了一次256(不这样得到的声音不对),库自身又除以256,相当于将32位减少到16位(源码不索性直接除65536得了,float也完全可以内部处理,不需要我们预处理,毕竟开源,只能睁只眼闭只眼)
总结:
float肯定是要二次处理的,
int32也需要二次处理,内部还要再处理,相当于就是使用int16
直接使用int16效率是最高的,其它2个最终也等价于int16,并不会有实质性的效果提升
真的需要高标准就都有专业的设备采集,自带接口支持硬编码,如果再用软编码这效率效果就低了