当前位置:首页 » 安卓系统 » android音频系统

android音频系统

发布时间: 2022-11-22 11:10:34

❶ android2.3采用alsa作为音频系统,在asound.conf中的扬声器音量设置问题。

这个我也碰到过,是常规问题,原因在于音频系统不兼容,如果您的设置里面有“db分位噪比”选项,可以将其数值加大,一般到210即可。如果没有此选项,那您只好换个音频系统了,我就换了,以后再也没有出现类似的问题

❷ Android Audio System 之一:AudioTrack如何与AudioFlinger交换

引子Android Framework的音频子系统中,每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到 AudioFlinger中,由AudioFlinger把所有的AudioTrack进行混合(Mixer),然后输送到AudioHardware中 进行播放,目前Android的Froyo版本设定了同时最多可以创建32个音频流,也就是说,Mixer最多会同时处理32个AudioTrack的数 据流。如何使用AudioTrackAudioTrack的主要代码位于 frameworks/base/media/libmedia/audiotrack.cpp中。现在先通过一个例子来了解一下如何使用 AudioTrack,ToneGenerator是android中产生电话拨号音和其他音调波形的一个实现,我们就以它为例子:ToneGenerator的初始化函数:bool ToneGenerator::initAudioTrack() { // Open audio track in mono, PCM 16bit//, default sampling rate, default buffer size mpAudioTrack = new AudioTrack(); mpAudioTrack->set(mStreamType, 0, AudioSystem::PCM_16_BIT, AudioSystem::CHANNEL_OUT_MONO, 0, 0, audioCallback, this, 0, 0, mThreadCanCalljava); if (mpAudioTrack->initCheck() != NO_ERROR) { LOGE("AudioTrack->initCheck failed"); goto initAudioTrack_exit; } mpAudioTrack->setVolume(mVolume, mVolume); mState = TONE_INIT; ...... } 可见,创建步骤很简单,先new一个AudioTrack的实例,然后调用set成员函数完成参数的设置并注册到AudioFlinger中,然后可以调 用其他诸如设置音量等函数进一步设置音频参数。其中,一个重要的参数是audioCallback,audioCallback是一个回调函数,负责响应 AudioTrack的通知,例如填充数据、循环播放、播放位置触发等等。回调函数的写法通常像这样:void ToneGenerator::audioCallback(int event, void* user, void *info) { if (event != AudioTrack::EVENT_MORE_DATA) return; AudioTrack::Buffer *buffer = static_cast<AudioTrack::Buffer *>(info); ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user); short *lpOut = buffer->i16; unsigned int lNumSmp = buffer->size/sizeof(short); const ToneDescriptor *lpToneDesc = lpToneGen->mpToneDesc; if (buffer->size == 0) return; // Clear output buffer: WaveGenerator accumulates into lpOut buffer memset(lpOut, 0, buffer->size); ...... // 以下是产生音调数据的代码,略.... } 该函数首先判断事件的类型是否是EVENT_MORE_DATA,如果是,则后续的代码会填充相应的音频数据后返回,当然你可以处理其他事件,以下是可用的事件类型:enum event_type { EVENT_MORE_DATA = 0,// Request to write more data to PCM buffer. EVENT_UNDERRUN = 1,// PCM buffer underrun occured. EVENT_LOOP_END = 2,// Sample loop end was reached; playback restarted from loop start if loop count was not 0. EVENT_MARKER = 3,// Playback head is at the specified marker position (See setMarkerPosition()). EVENT_NEW_POS = 4,// Playback head is at a new position (See setPositionUpdatePeriod()). EVENT_BUFFER_END = 5// Playback head is at the end of the buffer. }; 开始播放:mpAudioTrack->start(); 停止播放:mpAudioTrack->stop(); 只要简单地调用成员函数start()和stop()即可。AudioTrack和AudioFlinger的通信机制通常,AudioTrack和AudioFlinger并不在同一个进程中,它们通过android中的binder机制建立联系。AudioFlinger是android中的一个service,在android启动时就已经被加载。下面这张图展示了他们两个的关系:图一AudioTrack和AudioFlinger的关系我们可以这样理解这张图的含义:audio_track_cblk_t实现了一个环形FIFO;AudioTrack是FIFO的数据生产者;AudioFlinger是FIFO的数据消费者。建立联系的过程下面的序列图展示了AudioTrack和AudioFlinger建立联系的过程:图二AudioTrack和AudioFlinger建立联系解释一下过程:Framework或者Java层通过JNI,new AudioTrack();根据StreamType等参数,通过一系列的调用getOutput();如有必要,AudioFlinger根据StreamType打开不同硬件设备;AudioFlinger为该输出设备创建混音线程: MixerThread(),并把该线程的id作为getOutput()的返回值返回给AudioTrack;AudioTrack通过binder机制调用AudioFlinger的createTrack();AudioFlinger注册该AudioTrack到MixerThread中;AudioFlinger创建一个用于控制的TrackHandle,并以IAudioTrack这一接口作为createTrack()的返回值;AudioTrack通过IAudioTrack接口,得到在AudioFlinger中创建的FIFO(audio_track_cblk_t);AudioTrack创建自己的监控线程:AudioTrackThread;自此,AudioTrack建立了和AudioFlinger的全部联系工作,接下来,AudioTrack可以:通过IAudioTrack接口控制该音轨的状态,例如start,stop,pause等等;通过对FIFO的写入,实现连续的音频播放;监控线程监控事件的发生,并通过audioCallback回调函数与用户程序进行交互;FIFO的管理 audio_track_cblk_taudio_track_cblk_t这个结构是FIFO实现的关键,该结构是在createTrack的时候,由AudioFlinger申请相 应的内存,然后通过IMemory接口返回AudioTrack的,这样AudioTrack和AudioFlinger管理着同一个 audio_track_cblk_t,通过它实现了环形FIFO,AudioTrack向FIFO中写入音频数据,AudioFlinger从FIFO 中读取音频数据,经Mixer后送给AudioHardware进行播放。audio_track_cblk_t的主要数据成员: user -- AudioTrack当前的写位置的偏移 userBase -- AudioTrack写偏移的基准位置,结合user的值方可确定真实的FIFO地址指针 server -- AudioFlinger当前的读位置的偏移 serverBase -- AudioFlinger读偏移的基准位置,结合server的值方可确定真实的FIFO地址指针 frameCount -- FIFO的大小,以音频数据的帧为单位,16bit的音频每帧的大小是2字节 buffers -- 指向FIFO的起始地址 out -- 音频流的方向,对于AudioTrack,out=1,对于AudioRecord,out=0audio_track_cblk_t的主要成员函数:framesAvailable_l()和framesAvailable()用于获取FIFO中可写的空闲空间的大小,只是加锁和不加锁的区别。uint32_t audio_track_cblk_t::framesAvailable_l() { uint32_t u = this->user; uint32_t s = this->server; if (out) { uint32_t limit = (s < loopStart) ? s : loopStart; return limit + frameCount - u; } else { return frameCount + u - s; } } framesReady()用于获取FIFO中可读取的空间大小。uint32_t audio_track_cblk_t::framesReady() { uint32_t u = this->user; uint32_t s = this->server; if (out) { if (u < loopEnd) { return u - s; } else { Mutex::Autolock _l(lock); if (loopCount >= 0) { return (loopEnd - loopStart)*loopCount + u - s; } else { return UINT_MAX; } } } else { return s - u; } } 我们看看下面的示意图: _____________________________________________ ^ ^ ^ ^ buffer_start server(s) user(u) buffer_end 很明显,frameReady = u - s,frameAvalible = frameCount - frameReady = frameCount - u + s 可能有人会问,应为这是一个环形的buffer,一旦user越过了buffer_end以后,应该会发生下面的情况: _____________________________________________ ^ ^ ^ ^ buffer_start user(u) server(s) buffer_end这时候u在s的前面,用上面的公式计算就会错误,但是android使用了一些技巧,保证了上述公式一直成立。我们先看完下面三个函数的代码再分析:uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) { uint32_t u = this->user; u += frameCount; ...... if (u >= userBase + this->frameCount) { userBase += this->frameCount; } this->user = u; ...... return u; } bool audio_track_cblk_t::stepServer(uint32_t frameCount) { // the code below simulates lock-with-timeout // we MUST do this to protect the AudioFlinger server // as this lock is shared with the client. status_t err; err = lock.tryLock(); if (err == -EBUSY) { // just wait a bit usleep(1000); err = lock.tryLock(); } if (err != NO_ERROR) { // probably, the client just died. return false; } uint32_t s = this->server; s += frameCount; // 省略部分代码 // ...... if (s >= serverBase + this->frameCount) { serverBase += this->frameCount; } this->server = s; cv.signal(); lock.unlock(); return true; } void* audio_track_cblk_t::buffer(uint32_t offset) const { return (int8_t *)this->buffers + (offset - userBase) * this->frameSize; } stepUser()和stepServer的作用是调整当前偏移的位置,可以看到,他们仅仅是把成员变量user或server的值加上需要移动 的数量,user和server的值并不考虑FIFO的边界问题,随着数据的不停写入和读出,user和server的值不断增加,只要处理得 当,user总是出现在server的后面,因此frameAvalible()和frameReady()中的算法才会一直成立。根据这种算 法,user和server的值都可能大于FIFO的大小:framCount,那么,如何确定真正的写指针的位置呢?这里需要用到userBase这一 成员变量,在stepUser()中,每当user的值越过(userBase+frameCount),userBase就会增加 frameCount,这样,映射到FIFO中的偏移总是可以通过(user-userBase)获得。因此,获得当前FIFO的写地址指针可以通过成员 函数buffer()返回:p = mClbk->buffer(mclbk->user);在AudioTrack中,封装了两个函数:obtainBuffer()和releaseBuffer()操作 FIFO,obtainBuffer()获得当前可写的数量和写指针的位置,releaseBuffer()则在写入数据后被调用,它其实就是简单地调用 stepUser()来调整偏移的位置。IMemory接口在createTrack的过程中,AudioFlinger会根据传入的frameCount参数,申请一块内存,AudioTrack可以通过 IAudioTrack接口的getCblk()函数获得指向该内存块的IMemory接口,然后AudioTrack通过该IMemory接口的 pointer()函数获得指向该内存块的指针,这块内存的开始部分就是audio_track_cblk_t结构,紧接着是大小为frameSize的 FIFO内存。IMemory->pointer() ---->|_______________________________________________________ |__audio_track_cblk_t__|_______buffer of FIFO(size==frameCount)____|看看AudioTrack的createTrack()的代码就明白了:sp<IAudioTrack> track = audioFlinger->createTrack(getpid(), streamType, sampleRate, format, channelCount, frameCount, ((uint16_t)flags) << 16, sharedBuffer, output, &status); // 得到IMemory接口 sp<IMemory> cblk = track->getCblk(); mAudioTrack.clear(); mAudioTrack = track; mCblkMemory.clear(); mCblkMemory = cblk; // 得到audio_track_cblk_t结构 mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); // 该FIFO用于输出 mCblk->out = 1; // Update buffer size in case it has been limited by AudioFlinger ring track creation mFrameCount = mCblk->frameCount; if (sharedBuffer == 0) { // 给FIFO的起始地址赋值 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); } else { .......... } (DroidPhone)

❸ Android音频底层调试-基于tinyalsa

因为Android中默认并没有使用标准alsa,而是使用的是tinyalsa。所以就算基于命令行的测试也要使用libtinyalsa。Android系统在上层Audio千变万化的时候,能够能这些个工具实时查看到,比方音频通道的切换等等。

编译完后会产生tinyplay、tinymix、tinycap等工具。

tinymix用法:

相应解释:

Playback Path:

例:将输出切换到扬声器

关于tinymix小结:

通过观察发现,Android系统的声音音量的调节并没有直接使用tinyalsa,而基于上层软件实现。由于不管上层音量怎么改变,这里看到的都是24(以我使用的设备为例)。

通道的切换是真正使用了tinyalsa,当通过不同通道播放音乐的时候能够实时观察到通道的切换。在某个站点上看到Android在没有声音播放的3秒后会关闭alsa,这里也得到了证实,我曾经觉得Android系统会永久占用音频设备。

当通过蓝牙播放音乐的时候,已经不经过alsa了,tinymix查看到都处理关闭状态。由于Android4.2的蓝牙协议所有在用户层实现了,直接走uart通道。

一般播放1khz 0db正弦波,然后在codec输出端示波器简单测量是否失真,杂音,然后再使用音频分析仪测试指标。

tinyalsa源码
原文: https://www.cnblogs.com/yxwkf/p/5344068.html

安卓系统为什么音质不好

Android 基于Linux,我们先来了解一下Linux的特点。Linux使用ALSA作为其音频架构,其全称Advanced Linux Sound Architecture,即高级Linux声音架构的意思,在2.6核心之后,ALSA成为了Linux系统默认的音频子架构。取代了之前的OSS[Open Sound System,开放式声音系统]。

ALSA并不太好理解,它首先是一个驱动库,包含了大量的声卡设备的开源驱动,并提供了核心层API与ALSA库通信,而ALSA库则是应用程序访问和操控音频硬件的中间层,这个中间层有标准接口,开发者可以无须考虑硬件差异性进行开发,它对提升开发效率是大有帮助的。ALSA可以向下兼容OSS,因为OSS已经被淘汰,其兼容的工作模式不再讨论。

这个体系被继承到了Android当中。在Android2.2[含2,2]之前,系统文件夹中能找到一个LibAudioALSA.so的文件,这就是ALSA库文件,其他应用程序调用它,与声卡设备进行指令和数据通信。Android音频架构与Linux的并无本质区别。

在桌面版本的Linux当中,为了兼容各类声卡,Linux也设置了一个SRC[Sample Rate Converter,采样频率转换]的环节,当当前采样率低于48kHz时强制SRC到48kHz输出。这个SRC环节位于ALSA的插件模块中的混音器部分。Android针对这个进行了改进。
什么是SRC?SRC即Sample Rate Converter,中文意思为采样频率转换。它被声卡爱好者所关注,大部分发烧友视SRC为音质杀手。

Android增加了一个AudioFinger,这个可以简单的理解为Android的ALSA音频子系统的标准化的插件模块,它包含了AudioMixer[混音器]、AudioResampler[重采样]等子模块,AudioResampler即我们理解的SRC,Android换了一个新名称而已。针对SRC,Android做了改进,但改进并不是以去除SRC为目的,而是修改了默认的输出频率,Android的SRC目标采样率为44.1kHz,非该值的采样率都将SRC处理。例如播放48kHz采样率的信号,输出的最终是44.1kHz,这对音质将产生负面影响。

ALSA是一个针对Linux 桌面版本设计的音频架构,它实际上是不适合智能终端设备的,起码里面大量的开源驱动代码是可以去除的,对与Android来说,这些都是废代码。从Android2.3起,启用了一个新的音频架构。它放弃了一直使用的ALSA架构,因此系统文件夹中,也不再有LibAudioALSA.so这个文件。

Android2.3起,架构已经做了修改,在针对内部代码进行了优化,去除了冗余代码,理论上让系统能变得更加高效,可以将新架构理解为一个精简的或者为智能终端设备定制的ALSA架构。遗憾的是,它同样存在SRC严重劣化的问题,通过测试可以证明。
Android 3.0专门为平板电脑设计,影音体验变得更加重要了,是不是新系统在音质方面会有新的的进步呢,测试结果依然是令人失望的。

Android系统将采样率同一为44.1kHz输出,这造成了诸多限制,它将无法实现96kHz、192kHz高清音频节目的良好回放,大量视频节目源自DVD或者蓝光盘,其采用率多为48kHz,Android设备在回放这些视频节目时,音质也将大打折扣。

理论上软件SRC可以通过更换算法来实现音质提升,但却不太现实,智能终端所采用的CPU多为ARM,ARM芯片的浮点运算力有限,而SRC需要大量的浮点运算的资源,即便有了高质量的SRC算法,其运算也是以牺牲设备性能和耗电量为代价的,实用性差。

从Android的音频架构及流程分析,可以认为,播放44.1kHz采样率的音乐节目时,不会引发SRC,音质因此可以获得保证,理论上确实如此。但它同样存在问题,不管是之前的ALSA架构还是Android2.3之后改良的架构,其驱动库都位于核心层,也就意味着音频设备厂商、用户无法象PC平台那样安装驱动来改善音质。实际测试也表明,Android设备音质普遍偏差,Soomal有大量测试可以证明。

我们再把目光投向iOS,iOS非常封闭,我们甚至无法获知其架构的具体构成,但iOS设备不存在硬件设备多样性的问题,因此要实现更好音质也会更加简单。iOS可以实现针对性的开发和改良,以实现更好的音质。实际情况也是如此,目前为止,还没有一款Android设备的音质可以媲美任意一款iOS设备,这种差距,我们认为不是来自硬件,而是操作系统。

Android音频架构的局限性也使得其难以成为优质的影音平台,如果你希望设计一款基于Android的高清影音播放器,那么首先需要做的不是设计硬件,而是去修改现有架构的不足,或者干脆设计一个专用的架构来取代Android的通用架构。从源代码分析,Android和原生的Linux底层能支持各种采样率,开源也使得其具有改造基础,因此,在技术实力强劲的公司手里,Android也可以乌鸡变凤凰。

❺ android5.0系统音频是否还有src的问题

一直以来,Android系统由于底层语言的问题,在音频播放上存在一个漏洞,即48khz采样率转换为44.1khz会被劣质SRC。这种被劣质SRC的问题,使得音频信号在安卓设备里受到了扭曲和损耗,产生大量噪波,立体声播放层次等这些指标全面受损。而用户需求较多的高品质音乐母生带、高清视频、游戏等的音频都是高于44.1khz的采样率;因此有很多用户不厌其烦抱怨安卓机器的音质失真和受损问题。
通过一段标准音频理论状态下的光谱图,我们可以发现正常安卓机型在播放48khz音频时,光谱图可谓惨不忍睹。主信号周围出现了巨量的噪波,主信号基本难以分辨,因此难免会出现声道串声,杂音,变调等问题。
近期智能手机厂商vivo发布了其自主研发的音频技术VRS。据了解,vivo的VRS技术声称完全解决了上述困扰安卓系统音频播放的梦魇,并得到了国家专利受理。
而应用了VRS音频技术的vivo V1智能手机在播放48khz音频时,完全不存在任何问题,其主信号的保真度接近于理论完美状态。虽然信号源质量并不完全代表最后的听感,但我们也知道,有了接近无损的信号源,是能够取得优秀播放效果的前提。可见,VRS技术的出现,表明vivo智能手机在致力于追求产品完美的音质享受探索又迈上了一个新的高度。

❻ smoothaction为什么有杂音

smoothaction为什么有杂音?APP

整个音频体系的最上层

Framework

MediaPlayer和MediaRecorder、AudioTrack和AudioRecorder,Android系统为控制音频系统提供了AudioManager、AudioService及AudioSystem类,这些都是framework为便利上层应用开发所设计的

Libraries

系统服务AudioFlinger和AudioPolicyService(比如:ServiceManager、LocationManagerService、ActivityManagerService等等),音频体系中另一个重要的系统服务是MediaPlayerService

HAL

硬件抽象层是AudioFlinger直接访问的对象,这说明了两个问题,一方面AudioFlinger并不直接调用底层的驱动程序;另一方面,AudioFlinger上层(包括和它同一层的MediaPlayerService)的模块只需要与它进行交互就可以实现音频相关的功能了。因而我们可以认为AudioFlinger是Android音频系统中真正的“隔离板”,无论下面如何变化,上层的实现都可以保持兼容。音频方面的硬件抽象层主要分为两部分,即AudioFlinger和AudioPolicyService。实际上后者并不是一个真实的设备,只是采用虚拟设备的方式来让厂商可以方便地定制出自己的策略,抽象层的任务是将AudioFlinger/AudioPolicyService真正地与硬件设备关联起来

以前Android系统中的Audio系统依赖于ALSA-lib,但后期就变为了tinyalsa,这样的转变不应该对上层造成破坏。因而Audio HAL提供了统一的接口来定义它与AudioFlinger/AudioPolicyService之间的通信方式,这就是audio_hw_device、audio_stream_in及audio_stream_out等等存在的目的,这些Struct数据类型内部大多只是函数指针的定义,是一些“壳”。当AudioFlinger/AudioPolicyService初始化时,它们会去寻找系统中最匹配的实现(这些实现驻留在以audio.primary.*,audio.a2dp.*为名的各种库中)来填充这些“壳”

理解Android音频系统的时候分为两条线索

以库为线索,比如:AudioPolicyService和AudioFlinger都是在libaudioflinger库中,而AudioTrack、AudioRecorder等一系列实现则在libmedia库中

以进程为线索,库并不代表一个进程,进程则依赖于库来运行。虽然有的类是在同一个库中实现的,但并不代表它们会在同一个进程中被调用。比如AudioFlinger和AudioPolicyService都驻留于名为mediaserver的系统进程中,而AudioTrack/AudioRecorder和MediaPlayer/MediaRecorder一样实际上只是应用进程的一部分,它们通过binder服务来与其它系统进程通信。

❼ Android音视频【十二】使用OpenSLES和AudioTrack进行播放PCM

本节我们学习下如何播放pcm数据,在Android中有两种方法:一种是使用java层的 AudioTrack 方法,一种是使用底层的 OpenSLES 直接在 jni 层调用系统的 OpenSLES的c方法 实现。

两种使用场景不一样:
AudioTrack 一般用于 比如本地播放一个pcm文件/流,又或者播放解码后的音频的pcm流,API较简单。
OpenSLES 一般用于一些播放器中开发中,比如音频/视频播放器,声音/音频的播放采用的OpenSLES,一是播放器一般是c/c++实现,便于直接在c层调用OpenSLES的API,二也是如果用AudioTrack进行播放,务必会带来java和jni层的反射调用的开销,API较复杂。

可以根据业务自行决定来进行选择。

AudioTrack的方式使用较简单,直接在java层。

指定采样率,采样位数,声道数进行创建。

其中44100是采样率, AudioFormat.CHANNEL_OUT_STEREO 为双声道,还有 CHANNEL_OUT_MONO 单声道。 AudioFormat.ENCODING_PCM_16BIT 为采样位数16位,还有 ENCODING_PCM_8BIT 8位。 minBufferSize 是播放器缓冲的大小,也是根据采样率和采样位数,声道数 进行获取,只有满足最小的buffer才去操作底层进程播放。

最后一个参数mode。可以指定的值有 AudioTrack.MODE_STREAM 和 AudioTrack.MODE_STATIC 。

MODE_STREAM 适用于大多数的场景,比如动态的处理audio buffer,或者播放很长的音频文件,它是将audio buffers从java层传递到native层。音频播放时音频数据从Java流式传输到native层的创建模式。

MODE_STATIC 适用场景,比如播放很短的音频,它是一次性将全部的音频资源从java传递到native层。音频数据在音频开始播放前仅从Java传输到native层的创建模式。

是的,就这么一个方法。注意此方法是同步方法,是个耗时方法,一般是开启一个线程循环调用 write 方法进行写入。
注意在调用 write 方法前需要调用 audioTrack.play() 方法开始播放。

因为是pcm裸数据,无法像mediaplayer一样提供了API。所以需要自己处理下。可以利用 getPlaybackHeadPosition 方法。

getPlaybackHeadPosition() 的意思是返回以帧为单位表示的播放头位置
getPlaybackRate() 的意思是返回以Hz为单位返回当前播放采样率。

所以当前播放时间可以通过如下方式获取

OpenSLES:(Open Sound Library for Embedded Systems).
OpenSLES是跨平台是针对嵌入式系统精心优化的硬件音频加速API。使用OpenSLES进行音频播放的好处是可以不依赖第三方。比如一些音频或者视频播放器中都是用OpenSLES进行播放解码后的pcm的,这样免去了和java层的交互。

在Android中使用OpenSLES首先需要把Android 系统提供的so链接到外面自己的so。在CMakeLists.txt脚本中添加链接库OpenSLES。库的名字可以在 类似如下目录中

需要去掉lib

然后导入头文件即可使用了OpenSLES提供的底层方法了。

创建&使用的步骤大致分为:

一个 SLObjectItf 里面可能包含了多个Interface,获取Interface通过 GetInterface 方法,而 GetInterface 方法的地2个参数 SLInterfaceID 参数来指定到的需要获取Object里面的那个Interface。比如通过指定 SL_IID_ENGINE 的类型来获取 SLEngineItf 。我们可以通过 SLEngineItf 去创建各种Object,例如播放器、录音器、混音器的Object,然后在用这些Object去获取各种Interface去实现各种功能。

如上所说,SLEngineItf可以创建混音器的Object。

在创建播放器前需要创建音频的配置信息(比如采样率,声道数,每个采样的位数等)

开始播放后会不断的回调这个 pcmBufferCallBack 函数将音频数据压入队列
(*pcmBufferQueue)->RegisterCallback(pcmBufferQueue, pcmBufferCallBack, this);

如果想要暂停播放参数直接设置为SL_PLAYSTATE_PAUSED,若暂停后继续播放设置参数为SL_PLAYSTATE_PLAYING即可。若想要停止播放参数设置为SL_PLAYSTATE_STOPPED即可。

首先获取播放器的用于控制音量的接口SLVolumeItf pcmVolumePlay

然后动态设置

首先也是获取播放器的用于控制音量的接口SLMuteSoloItf pcmMutePlay

然后动态设置

看起来控制还是蛮简单的哈。先熟悉这么多,OpenSLES还是蛮强大的。

https://github.com/ta893115871/PCMPlay

❽ android系统支持那些格式的音频文件

1、H.263:低码率视频编码标准,广泛应用于视频会议。

文件格式:

• 3GPP (.3gp)

• MPEG-4 (.mp4)

2、H.264 AVC:和MPEG2和MPEG4 ASP等压缩技术相比,在同等图像质量下,采用H.264技术压缩后的数据量只有MPEG2的1/8,MPEG4的1/3。提供了解决在不稳定网络环境下容易发生的丢包等错误的必要工具。从Android3.0+开始支持。在图像编码效率上,H.264算法最为领先,MPEG-4和H.263算法基本相同。

文件格式:

• 3GPP (.3gp)

• MPEG-4 (.mp4)

• MPEG-TS (.ts, AAC audio only, not seekable, Android 3.0+)

3、MPEG-4 SP:一种以矩形帧作为对象的编码形式,是从H.263、MPEG1和MPEG2继承而来的编码标准。

文件格式:3GPP (.3gp)

4、VP8:Google亲妈推出的,但压缩率比H.264差很多,Android2.3.3+。

文件格式:

• WebM(.webm)

• Matroska (.mkv, Android 4.0+) 注:开源,基于html5标准

❾ Android支持ogg格式的音频吗

安卓系统都支持ogg的音频,包括ogg的音频格式。

❿ SRC问题可解决 安卓手机音频分析与测试

【IT168评测】现在一台智能手机继承了非常多的功能,很多的人都会选择使用手机来听歌,手机的音乐播放功能足以取代了以前的MP3播放器的位置。实用手机来听歌当然是非常方便,但是往往会觉得手机的音质并不是太好,特别是安卓系统的智能手机。


▲智能手机SRC测试

其实安卓智能系统的音频架构导致了安卓手机的音乐播放质量差的问题,问题根源在于安卓系统在播放采样频率高于44.1KHz的音频是会强制音频的采样频率降低到44.1KHz,在这个过程中直接导致了出现SRC的问题,这是安卓系统的硬伤。关于安卓系统音频架构可参考《寻找音质变差元兇 聊聊Android音频架构》

什么是SRC?SRC即Sample Rate Converter,中文意思为采样频率转换。它被声卡爱好者所关注,大部分发烧友视SRC为音质杀手。


▲安卓手机普遍存在SRC问题

最近我们收到了一款智能手机针对这个问题提出了他们的解决方案,使得安卓手机在音乐播放音质方面可以领先与其他的安卓智能手机,事实是否如此?下面我们来测试一下。

如何测试?

这款智能手机能够解决安卓系统SRC问题在众多手机厂商中算是第一个,我们来对这款手机测试一下,首先是使用20Hz到20KHz的全频扫描进行测试,之后是进行主观听感的测试。


▲测试使用的44.1KHz音频和48KHz音频

全频扫描测试使用2个采样频率的wav文件,44.1KHz的音频和48KHz的音频,将文件放在手机中进行播放,使用cool edit pro录音,对录音进行频谱分析,入股出现SRC频频就会出现杂乱无章的线路。


▲正常没出SRC的图像


▲出现SRC时的图像

第二张图就是SRC的图像,现在很多安卓手机都会存在SRC问题,理论上测试结果和第二张图相似,而步步高vivo智能手机解决了SRC问题测试结果应该要接近第一张图。


▲测试使用E-MU 0404专业声卡

由于我们手上没有专业的测试设备,只能使用电脑进行测试,测试使用E-MU 0404 PC专业声卡作为输入声卡,采用cool edit pro来录音,由于测试环境并不是十分专业可能会有少量的噪音引入,而图像也不是十分完美,但也可以反映出问题。

SRC测试

这次测试不仅仅针对某品牌的智能手机,我们也找来了Nexus S和魅族M9进行对比,下面来看一下测试的结果。

44.1KHz采样频率音频扫描:


▲Nexus S测试图像(点击放大)


▲魅族M9测试图像(点击放大)


▲某品牌安卓测试图像(点击放大)

上面的测试图可以看到安卓系统在44.1KHz的采样频率下图像都是非常干净的,代表音质是没有受到任何影响,这是由于安卓音频架构规定的采样频率是44.1KHz,对于大部分的MP3音频都是在44.1KHz的采样频率,对于MP3音频安卓系统基本上问题不大。

48KHz采样频率音频扫描

48KHz采样频率音频扫描是这次测试的重点,因为安卓系统的音频架构限制了44.1KHz的采样频率,所以高于44.1KHz的采样频率就会转换成44.1KHz,直接导致音质变差,下面来看一下测试结果。


▲Nexus S测试图像(点击放大)


▲魅族M9测试图像(点击放大)

测试结果惨不忍睹,Nexus S采用安卓4.0系统SRC问题依然存在,图像出现了很多的交错的线条,而魅族M9采用安卓2.3系统测试的图像也说明SRC问题非常严重。


▲某品牌安卓智能手机测试图像(点击放大)

某品牌安卓智能手机进行48KHz采样频率音频扫描结果要比上面两款手机要好很多,只在扫描直线上面出现一条很浅色的直线,像对于其他的安卓系统已经是一个非常大的飞跃,对于播放高音质的音频这款安卓智能手机能更好还原原本音质。

主观听感:


▲测试使用的48KHz采样频率的MP3

说完理论的东西来点实际的听感,试用手机听音乐已经是相当普遍,测试使用2首48KHz采样频率的MP3进行测试,试听某品牌智能手机上和其他智能手机音质有什么区别。


▲测试使用UE TF10耳机

首先来听一下一般安卓手机播放48KHz采样频率的MP3,测试使用了UE TF10入耳耳机,听感觉得声音偏暖,有点朦胧的感觉,而音乐的细节有些地方无法很好的展现,这个问题在几台安卓手机上同样遇到,音色都是暖,细节表现不佳。而用耳机听回前面的20Hz-20KHz扫描是明显发现问题了,除了扫描信号的声音外还可以听到背后有一些跟着扫描信号一起响起的音频扫描声音,这就是图像上交错的线条,严重影响听感。

再来说一下某品牌智能手机上的听感,试听这2只48KHz采样频率的MP3时整体声音很清晰自然,细节表现非常清晰,没有过多的音染,音场也比较宽广,整体上表现非常好。再听音频扫描信号,并没有出现前面的情况,只会听到音频扫描信号,非常干净,没有任何干扰。

测试总结:


▲SRC问题解决究竟用了什么技术?

通过这个测试可以看到某品牌的安卓智能手机很好地解决了安卓手机SRC问题,提升了安卓手机音频播放的音质,虽然由于保密原因现在不方便公布这品牌,而且还不知道采用了什么技术来解决安卓系统的SRC问题,但是可以肯定的是这个品牌的安卓智能手机是第一个解决安卓系统SRC问题的手机。这个决绝SRC问题的技术也将会会公布,到时我们也会为大家公布这个手机品牌和型号。

热点内容
生鲜仓库视频拍摄脚本 发布:2024-05-11 00:23:40 浏览:700
成功人生教育密码是什么 发布:2024-05-11 00:19:18 浏览:276
安装了个分享云盘需要服务器地址 发布:2024-05-11 00:18:27 浏览:382
如何查看radmin密码 发布:2024-05-10 23:52:03 浏览:798
用云服务器搭建外网教学 发布:2024-05-10 23:31:10 浏览:386
edimax打印服务器设置ip 发布:2024-05-10 23:29:51 浏览:370
联通的网关初始密码是多少 发布:2024-05-10 23:16:57 浏览:719
哪个手机品牌综合配置好 发布:2024-05-10 22:54:45 浏览:884
怎么解绑手机号微信账号密码 发布:2024-05-10 22:49:42 浏览:720
龙芯机器可以cef编译吗 发布:2024-05-10 22:40:48 浏览:159