快上网专注成都网站设计 成都网站制作 成都网站建设
成都网站建设公司服务热线:028-86922220

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

android混音,android混音增益

Mate10手机投屏时,手机视频声音与大屏微信语音信息混音

问题现象:

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:国际域名空间、雅安服务器托管、营销软件、网站建设、尼勒克网站维护、网站推广。

手机投屏时,大屏播放视频的同时,手机播放微信或某些媒体流时,声音也会从大屏上输出,造成混音现象。

问题原因:

大屏播放视频和手机播放媒体流,使用同一种媒体流,同一种流的输出策略是一样的,Android 目前无法做分流处理,同时输出到同一个设备,则会出现混音。

解决方案:

为了更好的视听体验,建议您暂时关闭其中一个正在播放音频的应用。

android 播放音乐时为什么用不到混音线程mixerthread

MixerThread是按照音频输出的核心部分,所有Android的音频都需要经过MixerThread进行混音后再输出到音频设备。 MixerThread的继承关系如下: MixerThread---PlaybackThread---ThreadBase---Thread 在PlaybackThread中,重写了Thread的threadLandroid 播放音乐时为什么用不到混音线程mixerthread

Android AudioTrack详解

我们知道播放声音能够用MediaPlayer和AudioTrack,MediaPlayer会在framework层创建相应的音频解码器。而AudioTrack仅仅能播放已经解码的PCM流,MediaPlayer在framework层还是会创建AudioTrack,把解码后的PCM数流传递给AudioTrack。AudioTrack再传递给AudioFlinger进行混音,然后才传递给硬件播放,所以是MediaPlayer包括了AudioTrack

每个音频流相应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到 AudioFlinger中。由AudioFlinger把全部的AudioTrack进行混合(Mixer)。然后输送到AudioHardware中进行播放。眼下Android同一时候最多能够创建32个音频流,也就是说。Mixer最多会同一时候处理32个AudioTrack的数据流。

在4000到48000之间

AudioTrack有两种数据载入模式:

1.MODE_STREAM

在这样的模式下,应用程序持续地write音频数据流到AudioTrack中,而且write动作将堵塞直到数据流从Java层传输到native层,同一时候增加到播放队列中。这样的模式适用于播放大音频数据,但该模式也造成了一定的延时;

2.MODE_STATIC

在播放之前,先把全部数据一次性write到AudioTrack的内部缓冲区中。适用于播放内存占用小、延时要求较高的音频数据。

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还是蛮强大的。

android开发中怎样实现混音

音频混音的原理: 量化的语音信号的叠加等价于空气中声波的叠加。

下面是代码,可以参照来学习:

public void mixAudios(File[] rawAudioFiles){

final int fileSize = rawAudioFiles.length;

FileInputStream[] audioFileStreams = new FileInputStream[fileSize];

File audioFile = null;

FileInputStream inputStream; byte[][] allAudioBytes = new byte[fileSize][]; boolean[] streamDoneArray = new boolean[fileSize]; byte[] buffer = new byte[512]; int offset;

try {

for (int fileIndex = 0; fileIndex  fileSize; ++fileIndex) {

audioFile = rawAudioFiles[fileIndex];

audioFileStreams[fileIndex] = new FileInputStream(audioFile);

} while(true){

for(int streamIndex = 0 ; streamIndex  fileSize ; ++streamIndex){

inputStream = audioFileStreams[streamIndex]; if(!streamDoneArray[streamIndex]  (offset = inputStream.read(buffer)) != -1){

allAudioBytes[streamIndex] = Arrays.copyOf(buffer,buffer.length);

}else{

streamDoneArray[streamIndex] = true;

allAudioBytes[streamIndex] = new byte[512];

}

}

byte[] mixBytes = mixRawAudioBytes(allAudioBytes);

//mixBytes 就是混合后的数据

boolean done = true; for(boolean streamEnd : streamDoneArray){ if(!streamEnd){

done = false;

}

}

if(done){ break;

}

}

} catch (IOException e) {

e.printStackTrace(); if(mOnAudioMixListener != null)

mOnAudioMixListener.onMixError(1);

}finally{ try { for(FileInputStream in : audioFileStreams){ if(in != null)

in.close();

}

} catch (IOException e) {

e.printStackTrace();

}

}

}/**

* 每一行是一个音频的数据

*/byte[] averageMix(byte[][] bMulRoadAudioes) {

if (bMulRoadAudioes == null || bMulRoadAudioes.length == 0) return null; byte[] realMixAudio = bMulRoadAudioes[0];

if(bMulRoadAudioes.length == 1) return realMixAudio;

for(int rw = 0 ; rw  bMulRoadAudioes.length ; ++rw){ if(bMulRoadAudioes[rw].length != realMixAudio.length){

Log.e("app", "column of the road of audio + " + rw +" is diffrent."); return null;

}

}

int row = bMulRoadAudioes.length; int coloum = realMixAudio.length / 2; short[][] sMulRoadAudioes = new short[row][coloum]; for (int r = 0; r  row; ++r) { for (int c = 0; c  coloum; ++c) {

sMulRoadAudioes[r][c] = (short) ((bMulRoadAudioes[r][c * 2]  0xff) | (bMulRoadAudioes[r][c * 2 + 1]  0xff)  8);

}

} short[] sMixAudio = new short[coloum]; int mixVal; int sr = 0; for (int sc = 0; sc  coloum; ++sc) {

mixVal = 0;

sr = 0; for (; sr  row; ++sr) {

mixVal += sMulRoadAudioes[sr][sc];

}

sMixAudio[sc] = (short) (mixVal / row);

} for (sr = 0; sr  coloum; ++sr) {

realMixAudio[sr * 2] = (byte) (sMixAudio[sr]  0x00FF);

realMixAudio[sr * 2 + 1] = (byte) ((sMixAudio[sr]  0xFF00)  8);

} return realMixAudio;

}


网站标题:android混音,android混音增益
本文地址:http://6mz.cn/article/dseiiej.html

其他资讯