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

jianggp101 2013-12-10 10:47:16
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文件 就可以正常播放
...全文
4741 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_17728305 2016-04-01
  • 打赏
  • 举报
回复
大神们解决了没有啊,麻烦把代码发我邮箱 2368336484@qq.com , 谢谢!!!
fansgq 2015-06-18
  • 打赏
  • 举报
回复
各位大神,到底有没有解决问题?能共享一下不???
ke13590955160 2014-08-06
  • 打赏
  • 举报
回复
题主 pCodecCtx->channels=1和 pCodecCtx->sample_fmt=8是不是有一个错了?矛盾了。 请看下面的资料: enum AVSampleFormat { -1 AV_SAMPLE_FMT_NONE = -1, 0 AV_SAMPLE_FMT_U8, ///< unsigned 8 bits 1 AV_SAMPLE_FMT_S16, ///< signed 16 bits 2 AV_SAMPLE_FMT_S32, ///< signed 32 bits 3 AV_SAMPLE_FMT_FLT, ///< float 4 AV_SAMPLE_FMT_DBL, ///< double 5 AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar 6 AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar 7 AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar 8 AV_SAMPLE_FMT_FLTP, ///< float, planar 9 AV_SAMPLE_FMT_DBLP, ///< double, planar AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically }; 音频的采样: PCM采样有单声道(mono)和立体声(stereo)之分,采用位数有8,16,24三类。 单声道采样常用的格式有: AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32 立体声采样常用的格式有: AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P 对于末尾有P后缀的格式表示是平面格式(planar format),没有P后缀的是压缩格式(packed format), 两者的存储方式不一样。 平面格式将不同的声道的数据分开存储,每种数据对应一个data[i];压缩格式是左右声道交替存储的, 它只占用了AVFrame结构体中的data[0]。
Steven-Xu 2014-06-28
  • 打赏
  • 举报
回复
支持下,看起来很复杂的样子。
qazmoon 2014-06-16
  • 打赏
  • 举报
回复
引用 3 楼 neustar1 的回复:
额,自己转一下不就OK了
怎么转的啊?
qazmoon 2014-06-13
  • 打赏
  • 举报
回复
最终怎么解决的啊?
__cc__ 2014-04-25
  • 打赏
  • 举报
回复
额,自己转一下不就OK了
Q214HW 2014-04-24
  • 打赏
  • 举报
回复
楼主你弄好没,我现在也在做这个,求助啊
逸萌 2013-12-11
  • 打赏
  • 举报
回复

2,543

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧