ffmpeg音频播放 (AudioTrack)杂音如何解决

jianggp101 jianggp101 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
ffmpeg2.1.1解码一个MP4文件的音频
我将结果保存为pcm文件,将解码的pcm内容发给Java层AudioTrack播放
解码出的 pCodecCtx->channels=1
pCodecCtx->sample_fmt=8
pCodecCtx->sample_rate=44100

JNI解码主要代码
// 函数名为 decodeLoop() 
if (packet.stream_index == audioStream)
{
int len = avcodec_decode_audio4(pCodecCtx, pFrame, &frameFinished, &packet);
if (len > 0 && frameFinished)
{
int data_size = av_samples_get_buffer_size(pFrame->linesize,
pCodecCtx->channels, pFrame->nb_samples,
pCodecCtx->sample_fmt, 1);
// 保存到pcm文件
if (outFile != NULL)
{
fwrite(pFrame->linesize[0], 1, outlen, data_size);
audioFileSize += outlen;
fflush(outFile);
}
// 传递到java层
jbyteArray nativePixels = (*env)->NewByteArray(env, data_size);
(*env)->SetByteArrayRegion(env, nativePixels, 0, data_size, pFrame->linesize[0]);
return nativePixels;
}
}


JAVA层代码
自定义MyAudioTrack类如下
int m_frequency;// 采样率
int m_channel; // 声道
int m_sampBit; // 采样精度
AudioTrack mAudioTrack;

//构造
//此时 frequency=44100, channel=1,
//自行设置的sampbit=SL_PCMSAMPLEFORMAT_FIXED_16即16 因为没有32
public MyAudioTrack(int frequency, int channel, int sampbit) {
m_frequency = frequency;
switch(channel)
{
case 0:
m_channel = AudioFormat.CHANNEL_CONFIGURATION_INVALID;
break;
case 1:
m_channel = AudioFormat.CHANNEL_CONFIGURATION_MONO;
break;
case 2:
m_channel = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
m_frequency = m_frequency /2; //保证播放速度
break;
default:
m_channel = AudioFormat.CHANNEL_CONFIGURATION_DEFAULT;
break;
}

switch(sampbit)
{
case 0:
m_sampBit = AudioFormat.ENCODING_INVALID ;
break;
case 8:
m_sampBit = AudioFormat.ENCODING_PCM_8BIT;
break;
case 16:
m_sampBit = AudioFormat.ENCODING_PCM_16BIT;
break;
default:
m_sampBit = AudioFormat.ENCODING_DEFAULT;
break;
}
}
public void init() {
// 获得构建对象的最小缓冲区大小
int minBufSize = AudioTrack.getMinBufferSize(m_sampleRate, m_channel,m_sampBit);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, m_frequency ,
m_channel, m_sampBit, minBufSize, AudioTrack.MODE_STREAM);
mAudioTrack.play();
}


MainActivity中播放声音
//循环调用ff_thread.decodeLoop() 返回解码的结果 给一个byte[]nativePixels
while((nativePixels = ff_thread.decodeLoop())!=null)
{
myAudioTrack.playAudioTrack(nativePixels, 0, nativePixels.length);
}



现在问题是 用AudaCity 播放pcm文件 需要设置 编码格式为32位 float 采样率为44100 放出来的声音正常
如果设置编码格式为 16bit PCM或者 8bit PCM 则几乎全是杂音
此时AudioTrack播放的声音全是杂音。。。
看了半天,应该是AudioTrack采样格式设置的问题 但是AudioTrack 只支持16和8位 不支持32位。
应该怎么办呢? 我用audio_resample重采样 也是杂音 而且audio_resample也只只能处理16位。

//out_channels=1 out_sample_rate=44100
reSampleCtx = av_audio_resample_init(out_channels, pCodecCtx->channels,
out_sample_rate, pCodecCtx->sample_rate, AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_S16, 16, 10, 0, 1);
///////////////////////////////////////////////////////
short* outBuffer;
outBuffer = (short *) malloc(sizeof(short) * data_size);
int outlen = audio_resample(reSampleCtx, outBuffer,
(short *) pFrame->data[0], data_size);
jbyteArray nativePixels = (*env)->NewByteArray(env, outlen);
(*env)->SetByteArrayRegion(env, nativePixels, 0, outlen,outBuffer);
free(outBuffer);
outBuffer = NULL;
return nativePixels;

最主要问题是 怎么能把解码出来的音频数据(貌似是32位)给AudioTrack 还能播放
同样这个代码 解码mp3文件 就可以正常播放
...全文

相关推荐

评论 9
收藏 已收藏
分享
返回顶部