当前位置: 首页 > news >正文

网站建设行业 知乎广州市官方网站

网站建设行业 知乎,广州市官方网站,泰安华航网络有限公司,aspnet网站开发工具前言 产品一直有用户反馈音频截断问题。在机遇巧合下现学现卖音频知识处理相关问题。 问题描述 我们查看以下简化播放器代码#xff1a; class AACPlayer(private val filePath: String) {private val TAG AACPlayerprivate var extractor: MediaExtractor? …前言 产品一直有用户反馈音频截断问题。在机遇巧合下现学现卖音频知识处理相关问题。 问题描述 我们查看以下简化播放器代码 class AACPlayer(private val filePath: String) {private val TAG AACPlayerprivate var extractor: MediaExtractor? nullprivate var codec: MediaCodec? nullprivate var audioTrack: AudioTrack? nullfun play() {try {extractor MediaExtractor().apply {setDataSource(filePath)}var trackIndex -1for (i in 0 until extractor!!.trackCount) {val format extractor!!.getTrackFormat(i)val mime format.getString(MediaFormat.KEY_MIME)if (mime!!.startsWith(audio/)) {trackIndex ibreak}}if (trackIndex 0) {extractor!!.selectTrack(trackIndex)val format extractor!!.getTrackFormat(trackIndex)val mime format.getString(MediaFormat.KEY_MIME)codec MediaCodec.createDecoderByType(mime!!)codec!!.configure(format, null, null, 0)codec!!.start()val sampleRate format.getInteger(MediaFormat.KEY_SAMPLE_RATE)val channelConfig if (format.getInteger(MediaFormat.KEY_CHANNEL_COUNT) 1) AudioFormat.CHANNEL_OUT_MONO else AudioFormat.CHANNEL_OUT_STEREOval bufferSize AudioTrack.getMinBufferSize(sampleRate,channelConfig,AudioFormat.ENCODING_PCM_16BIT);val audioTrackAttributes AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()val audioFormat AudioFormat.Builder().setEncoding(AudioFormat.ENCODING_PCM_16BIT).setSampleRate(sampleRate).setChannelMask(channelConfig).build()audioTrack AudioTrack.Builder().setAudioAttributes(audioTrackAttributes).setAudioFormat(audioFormat).setTransferMode(AudioTrack.MODE_STREAM).setBufferSizeInBytes(bufferSize).build()if (Build.VERSION.SDK_INT Build.VERSION_CODES.S) {logD(bufferSizeInFrames [${audioTrack?.bufferSizeInFrames}] bufferCapacityInFrames [${audioTrack?.bufferCapacityInFrames}] bufferSize [${bufferSize}] startThresholdInFrames [${audioTrack!!.startThresholdInFrames}])}audioTrack!!.play()val inputBuffers codec!!.inputBuffersval outputBuffers codec!!.outputBuffersval bufferInfo MediaCodec.BufferInfo()var isEOS falsewhile (!isEOS) {val inIndex codec!!.dequeueInputBuffer(10000)if (inIndex 0) {val buffer inputBuffers[inIndex]val sampleSize extractor!!.readSampleData(buffer, 0)if (sampleSize 0) {codec!!.queueInputBuffer(inIndex,0,0,0,MediaCodec.BUFFER_FLAG_END_OF_STREAM)isEOS true} else {val presentationTimeUs extractor!!.sampleTimecodec!!.queueInputBuffer(inIndex, 0, sampleSize, presentationTimeUs, 0)extractor!!.advance()}}var outIndex codec!!.dequeueOutputBuffer(bufferInfo, 10000)while (outIndex 0) {val outBuffer outputBuffers[outIndex]val bufferBackup outBuffer.slice()if (outBuffer.remaining() 0) {continue}//仅仅为了打印无他用val array ByteArray(bufferBackup.remaining())bufferBackup.get(array, 0, array.size)logD(array.joinToString(transform { String.format(%02x, it) }))logD(写入数据大小${array.size} hashCode ${array.contentHashCode()})audioTrack!!.write(outBuffer,outBuffer.remaining(),AudioTrack.WRITE_BLOCKING)codec!!.releaseOutputBuffer(outIndex, false)outIndex codec!!.dequeueOutputBuffer(bufferInfo, 0)}}}} catch (e: Exception) {e.printStackTrace()} finally {extractor?.release()codec?.stop()codec?.release()audioTrack?.flush()audioTrack?.stop()audioTrack?.release()}}fun logD(msg:String) {Log.d(TAG, msg)} }这也是网上充斥最多的示例代码但是上面的代码丢失尾帧的音频的问题。 getStartThresholdInFrames文档 在Android中audiotrack有一个缓冲区调用则可以阻塞或阻塞式使用audiotrack.write向里面写入数据。播放器为提高效率在缓冲大于startThresholdInFrames时取出进行播放。startThresholdInFrames一般大于等于bufferSizeInFrames。 你播放音频时不敢保证所有音频数据都是对齐startThresholdInFrames所以你会以为调用audiotrack.flush可以解决问题了。但是我们阅读相关文档flush文档发现这个API只是丢弃之前的数据加速audiotrack.write。 解决方案 在音频流写入结束调用audiotrack.stop 这个函数会将未播放的数据进行加载播放在结束。audiotrack.stop文档 在上述的代码我们如下编写 class AACPlayer(...) {//...fun play() {try {while (outIndex 0) {//....略//结束调用stop刷出残余音频if (bufferInfo.size 0 (bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM) ! 0) {audioTrack!!.stop()break}//....略}}catch(...){//...}finally{} finally {extractor?.release()codec?.stop()codec?.release()audioTrack?.flush()//注释多余的stop//audioTrack?.stop()audioTrack?.release()}} } 当然你如果比较骚可以进行补帧操作 class AACPlayer(...) {//...fun play() {try {while (outIndex 0) {//....略if (bufferInfo.size 0 (bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM) ! 0) {var interpolationFrame (audioTrack!!.startThresholdInFrames / bufferSize) 1while (interpolationFrame 0) {interpolationFrame--;audioTrack!!.write(ByteArray(bufferSize), 0, bufferSize)}break}//....略}}catch(...){//...}finally{} finally {//略}} } 实践 我们有一个极短音频且有效音在末尾那么在部分手机上将无法听到这个音频 在某手机上相关输出参数如下 bufferSizeInFrames [11310] bufferCapacityInFrames [11310] bufferSize [45240] startThresholdInFrames [11310]这个文件对应的PCM数据40960(A000h)字节大小。 我们看下这个文件的末端可以看到很多有效数据。 我们在看看文件最前面PCM数据 全是空数据。 所以这个文件只有末尾才音频。 我们算一下Audiotrack刷新次数 文件PCM大小/Audiotrack刷新阈值 40960/11310 3.6假设如果我们有效音频在最后0.6将无法播放
http://www.pierceye.com/news/117063/

相关文章:

  • 总结网站推广策划思路的内容佛山做外贸网站哪家好
  • 阿里云服务器如何做两个网站网站建站对象
  • 做网站毕业实训报告网站架构企业收费标准
  • 高端品牌网站建设公司哪家好网页设计与制作个人总结
  • 自己电脑建设网站哈尔滨专业网站建设哪个好
  • 福建设计招标网站移动端网站和app开发
  • 山东网站制作团队门户网站内容管理建设方案
  • 新开传奇网站排行中国建设网官方网站app
  • 网站营运费广州网络公司建站
  • 小吃网站建设如何提高网站收录量
  • 全球网站域名做网站设计学那个专业好
  • 新手学网站建设解疑与技巧1200例北京网络行业协会
  • 医生工作室网站建设sae wordpress 主题
  • 防水网站怎么做义乌 外贸网站 开发
  • 中国做外贸的网站有哪些内容虚拟商品购物网站源码
  • 如何将数据写入wordpress文站房屋装修案例
  • 做网站的积木式编程网站开发中的qq登录
  • 官方网站作用咨询公司简介
  • 个人手机版网站建设电影网站模板html
  • 招聘网站开发源码广州服务类拓客软件
  • 婚庆策划公司加盟江门关键词优化价格
  • 百度网站入口ps网页设计实验报告
  • 做网站准备材料怎么做优化网站排名
  • asp技校网站手游网页版
  • 网站建设合同要交印花税吗烟台网站的建设
  • 可以做锚文本链接的网站广告公司创意广告语
  • 建设网站的题目旅游网页素材
  • 做网站很难吗新手学做网站 pdf
  • 建设电影推荐网站的项目背景网站开发的公司电话
  • 建设银行 福建分行招聘网站cctv5体育现场直播