软录 · 2023年5月20日

安卓audiotrack|android audiotrack同时播放

① android audiotrack static怎么用

正确使用的方法如下:

…if(NULL==mAudioOut){…mAudioOut=newAudioTrack(AudioSystem::TTS,VP_WAVEFILE_SAMPLERATE,AudioSystem::PCM_16_BIT,AudioSystem::CHANNEL_OUT_MONO,minFrameCount>4096?minFrameCount:4096,0,0,0,0);if(NULL==mAudioOut){returnfalse;}mAudioOut->write(m_bWaveBuf,dataSize);mAudioOut->start();}if(mAudioOut->stopped()){mAudioOut->reload();mAudioOut->start();}elseif(!mAudioOut->stopped()){mAudioOut->stop();mAudioOut->reload();mAudioOut->start();}……..

② android webrtc 回音消除使用audiotrack 合适吗

android webrtc 回音消除使用audiotrack合适。推荐即构科技,产品可选:实时音视频、实时语音、互动直播、IM即时通讯。【点击免费试用,0成本启动】WebRTC的代码结构布局清晰,在“webrtc\moles\audio_processing\aee”目录下可以找到几个用于回声处理GIPS的AEC源文件。然后主要查找每个AEC源文件所关联的WebRTC代码,就可找出回声处理模块所需要WebRTC相关的源代码文件和头文件,这样就可以将AEC从WebRTC中提取出来单独使用。为方便使用,将需要这些代码分成2个模块,通用音频处理模块webRTC_AUDIO和GIPS-AEC模块。WebRTC—AUDIO模块中包含AEC源文件运行所依赖的WebRTC音频处理相关源文件及头文件,而GIPS—AEC模块则是WebRTC中专门用于回声处理GIPS的AEC源文件。GIPS-AEC模块以WebRTC_AUDIO模块为基础,对回声进行处理。想要了解更多关于这方面的相关信息,推荐咨询ZEGO即构科技。ZEGO即构科技是一家全球云通讯服务商,专注自研音视频引擎,服务覆盖全球,链接 5 亿终端用户。ZEGO即构科技覆盖212个国家/地区,全球用户体验毫秒级互动,日均通话时长达30亿分钟,跻身云通讯行业头部,全方位行业解决方案,满足百余个业务场景需要,服务客户4000家,70%泛娱乐/在线教育客户的选择。

③ 安卓2.2和2.3有什么区别

系统版本不一样,2.3比较2.2更加全面,操作性更强2.3版本的功能较之前版本新增内容:1. 新增android.net.sip包,名为SipManager类,可以轻松开发基于Sip的Voip应用。同时使用时必须至少包含这两个权限<uses-permission android:name="android.permission.INTERNET">and <uses-permission android:name="android.permission.USE_SIP">,如果需要在Market上过滤仅显示支持VoIP API的机型,可以在发布时androidmanifest.xml中加入<uses-feature android:name="android.software.sip"android:required="true"> 和<uses-feature android:name="android.software.sip.voip"> 这两个标志。2. Near FieldCommunications (NFC) 近距离通讯的支持,NFC可以在不接触的情况下实现数据交换通讯,可以很好的代替RFID SIM卡实现手机支付等扩展功能,当然Android123提示这需要硬件的支持,新增包在android.nfc包含NfcAdapter,NdefMessage,NdefRecord等类,类似蓝牙的处理方式,使用该API需要声明权限<uses-permissionandroid:name="android.permission.NFC"> ,同时在Market上过滤支持NFC的设备需要加入<uses-feature android:name="android.hardware.nfc"android:required="true">这句。3. 新增陀螺仪和其他的传感器支持Android 2.3加入了一些新的感应器,比如gyroscope陀螺仪, rotation vector旋转向量, linearacceleration线性加速器gravity和barometer气压计的支持。如果过滤这些功能,发布时加入类似<uses-featureandroid:name="android.hardware.sensor.gyroscope"android:required="true">到androidmanifest.xml中。4. 多摄像头支持新增Camera.CameraInfo 可以管理摄像头前置或后置新增getNumberOfCameras(), getCameraInfo() 和getNumberOfCameras() 获取摄像头数量。新增get() 方法,可以获取摄像头配置信息CamcorderProfile新增 () 获取jpeg编码质量参数可以在CameraPreview.java 文件从ApiDemos示例程序中查看。5. 新增拍照API比如获取焦距getFocusDistances()获取预览FPS getPreviewFpsRange(), 获取焦距范围getSupportedPreviewFpsRange() 和设置教育setPreviewFpsRange()6. 混响音效本次Android 2.3框架中加入了对混响音效的支持,比如低音,耳机和虚拟化等效果.新增android.media.audiofx 包新增AudioEffect 类提供音效控制新增音频会话ID,设置AudioTrack 和MediaPlayer.新AudioTrack 新增attachAuxEffect()、getAudioSessionId()和setAuxEffectSendLevel()。新attachAuxEffect() ,getAudioSessionId(),setAudioSessionId(int), 和setAuxEffectSendLevel() .相关音效在AudioFxDemo.java 的ApiDemos 示例。6. 照片EXIF信息改进新增 经纬度标签在JPG格式的EXIF中,同时可以使用getAltitude() 方法获取经纬度的EXIF信息新增setOrientationHint() 可以让程序获取视频录制的方向.7. 下载管理在Android 2.3中新增的下载管理支持长时间运行的Http下载服务支持。可以保证在手机重启后仍然重试下载等操作,整个过程在后台执行。通过DownloadManager 类使用getSystemService(DOWNLOAD_SERVICE) 来实例化,通过ACTION_NOTIFICATION_CLICKED 这个Intent来处理。8. 限制模式可以帮助开发者监控他的应用的性能,处理线程阻塞,避免ANR的发生。StrictMode.ThreadPolicy 和StrictMode.VmPolicy 获取VM相关信息.使用限制模式优化的Android应用程序可以查看android.os.StrictMode包的具体介绍。

④ android可以设定audiotrack的flag吗

你打印下Min_size看下是多少?这是我以前写的能用。packagegame.net.Speech;importjava.io.IOException;importjava.io.InputStream;importjava.net.Socket;importandroid.media.AudioFormat;importandroid.media.AudioManager;importandroid.media.AudioTrack;importandroid.util.Log;{@Overridepublicvoidplay(){//TODOAuto-generatedmethodstubthis.start();}@Overridepublicvoidend(){//TODOAuto-generatedmethodstubm_keep_running=false;try{Thread.sleep(200);}catch(Exceptione){}}privateInputStreammis;protectedAudioTrackm_out_trk;protectedintm_out_buf_size;protectedbyte[]m_out_bytes;publicbooleanm_keep_running=true;/***初始化设备信息*@throwsIOException*/publicAudioTypePlay(InputStreamis)throwsIOException{m_keep_running=true;m_out_buf_size=AudioTrack.getMinBufferSize(8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT);m_out_trk=newAudioTrack(AudioManager.STREAM_MUSIC,8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT,m_out_buf_size,AudioTrack.MODE_STREAM);m_out_bytes=newbyte[m_out_buf_size*3];//newThread(R1).start();mis=is;}publicvoidrun(){m_out_trk.play();while(m_keep_running){try{m_out_buf_size=mis.read(m_out_bytes);Log.d("播放声音",String.valueOf(m_out_buf_size));m_out_trk.write(m_out_bytes.clone(),0,m_out_buf_size);}catch(Exceptione){e.printStackTrace();}}m_out_trk.stop();m_out_trk.release();m_out_trk=null;if(endEvent!=null){endEvent.EndEvent();}};@OverridepublicvoidsetEndEvent(OnSpeechEndEventevent){//TODOAuto-generatedmethodstubendEvent=event;}}

⑤ android audiotrack同时播放

把他写到service里面,开启两次service就好了,mediaPlayer底层代码也是用service管理的

⑥ android audiotrack 可以播放什么格式

播放mp3的总是噪音,不知道原因,后来播放wav的倒是可以,wav是没有压缩的pcmJava代码package com.lp; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.content.Context; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.media.AudioTrack.; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private Button play; private Button stop; private AudioTrack at; private AudioManager am; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); am = (AudioManager)getSystemService(Context.AUDIO_SERVICE); play = (Button)findViewById(R.id.main_play); stop = (Button)findViewById(R.id.main_stop); play.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(am.isSpeakerphoneOn()){ am.setSpeakerphoneOn(false); } setVolumeControlStream(AudioManager.STREAM_VOICE_CALL); am.setMode(AudioManager.MODE_IN_CALL); System.out.println(am.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL)); System.out.println("&&&&&&&&&&&&&"); System.out.println(am.getStreamVolume(AudioManager.STREAM_VOICE_CALL)); int bufferSizeInBytes = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); if(at==null){ at = new AudioTrack(AudioManager.STREAM_VOICE_CALL, 44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes, AudioTrack.MODE_STREAM); System.out.println("22222"); new AudioTrackThread().start(); }else{ if(at.getPlayState()==AudioTrack.PLAYSTATE_PLAYING){ System.out.println("111111111"); }else{ System.out.println("33333"); at = new AudioTrack(AudioManager.STREAM_VOICE_CALL, 44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes, AudioTrack.MODE_STREAM); new AudioTrackThread().start(); } } } }); stop.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { at.stop(); at.release(); am.setMode(AudioManager.MODE_NORMAL); } }); } class AudioTrackThread extends Thread{ @Override public void run() { byte[] out_bytes = new byte[44100]; InputStream is = getResources().openRawResource(R.raw.start); int length ; at.play(); try { while((length = is.read(out_bytes))!=-1){ System.out.println(length); at.write(out_bytes, 0, length); } } catch (IOException e) { e.printStackTrace(); } if(at.getPlayState()==AudioTrack.PLAYSTATE_PLAYING){ at.stop(); at.release(); am.setMode(AudioManager.MODE_NORMAL); } } } }

⑦ 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 AudioTrack.play怎么判断播放完成

根据你的描述:audioTrack.getPlayState() == AudioTrack.PLAYSTATE_STOPPED; 希望能帮助到你。