效果图

源码

源码下载,请先移步Android左右声道的控制

我这里主要是用到了AudioTrack实现的左右声道的控制,手机一般都只有两个声道,即左声道和右声道,我们在输出的时候可以选择单声道,也可以选择双声道(立体声)。

查看了AudioTrack的API,提供了play()、pause()、stop()、write()等一系列的方法。

通过write()方法,可以实现将音频数据发送出去(播放出来)。

AudioTrack对象的构造

有三个构造方法

AudioTrack (int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)

AudioTrack (int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode, int sessionId)

AudioTrack (AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes, int mode, int sessionId)

主要参数有如下几个

streamType:以什么形式播放

STREAM_VOICE_CALL

STREAM_SYSTEM

STREAM_RING

STREAM_MUSIC

STREAM_ALARM

STREAM_NOTIFICATION

sampleRateInHz:采样率

channelConfig:声道

AudioFormat.CHANNEL_OUT_MONO:输出单声道音频数据

AudioFormat.CHANNEL_OUT_STEREO:输出双声道音频数据(立体声)

audioFormat:音频数据格式

mode:缓冲模式

MODE_STATIC:一次性将音频载入以后再播放

MODE_STREAM:以流的形式,加载一点就播放一点

把channelConfig的相关参数都看了一遍,没发现有可以指定向某声道发送数据的,只能通过AudioFormat.CHANNEL_OUT_MONO和AudioFormat.CHANNEL_OUT_STEREO选择是输出单声道的音频数据还是双声道的音频数据。

左右声道控制

构造的时候不能选择指定声道输出音频,但是有这样一个方法

setStereoVolume(float leftGain, float rightGain)

可以通过把某一个声道的音量设置到最小,达到只想某个声道输出音频的效果。

我自己也有点”呵呵“,但是也没有发现还有别的方法可以实现这样的效果。

这个方法还有一点小问题,在个别手机上,即使将某个声道的声音设置到了最小,也还是会有一点声音,这个我也还没有搞清楚为什么,个人猜测可能和手机硬件有关系。

封装

我这里的缓冲模式使用的MODE_STREAM的形式,以流的形式播放,因为这个逻辑要稍微复杂一点,尤其是暂停以后再继续播放的位置。

package kong.qingwei.androidsoundmanagerdemo;

import android.app.Activity;

import android.media.AudioFormat;

import android.media.AudioManager;

import android.media.AudioTrack;

import android.util.Log;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.InputStream;

/**

* Created by kqw on 2016/8/26.

* 播放音乐的线程

*/

public class PlayThread extends Thread {

// 采样率

private int mSampleRateInHz = 16000;

// 单声道

private int mChannelConfig = AudioFormat.CHANNEL_OUT_MONO;

// 双声道(立体声)

// private int mChannelConfig = AudioFormat.CHANNEL_OUT_STEREO;

private static final String TAG = "PlayThread";

private Activity mActivity;

private AudioTrack mAudioTrack;

private byte[] data;

private String mFileName;

public PlayThread(Activity activity, String fileName) {

mActivity = activity;

mFileName = fileName;

int bufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz, mChannelConfig, AudioFormat.ENCODING_PCM_16BIT);

mAudioTrack = new AudioTrack(

AudioManager.STREAM_MUSIC,

mSampleRateInHz,

mChannelConfig,

AudioFormat.ENCODING_PCM_16BIT,

bufferSize,

AudioTrack.MODE_STREAM);

}

@Override

public void run() {

super.run();

try {

if (null != mAudioTrack)

mAudioTrack.play();

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

InputStream inputStream = mActivity.getResources().getAssets().open(mFileName);

// 缓冲区

byte[] buffer = new byte[1024];

// 播放进度

int playIndex = 0;

// 是否缓冲完成

boolean isLoaded = false;

// 缓冲 + 播放

while (null != mAudioTrack && AudioTrack.PLAYSTATE_STOPPED != mAudioTrack.getPlayState()) {

// 字符长度

int len;

if (-1 != (len = inputStream.read(buffer))) {

byteArrayOutputStream.write(buffer, 0, len);

data = byteArrayOutputStream.toByteArray();

Log.i(TAG, "run: 已缓冲 : " + data.length);

} else {

// 缓冲完成

isLoaded = true;

}

if (AudioTrack.PLAYSTATE_PAUSED == mAudioTrack.getPlayState()) {

// TODO 已经暂停

}

if (AudioTrack.PLAYSTATE_PLAYING == mAudioTrack.getPlayState()) {

Log.i(TAG, "run: 开始从 " + playIndex + " 播放");

playIndex += mAudioTrack.write(data, playIndex, data.length - playIndex);

Log.i(TAG, "run: 播放到了 : " + playIndex);

if (isLoaded && playIndex == data.length) {

Log.i(TAG, "run: 播放完了");

mAudioTrack.stop();

}

if (playIndex < 0) {

Log.i(TAG, "run: 播放出错");

mAudioTrack.stop();

break;

}

}

}

Log.i(TAG, "run: play end");

} catch (IOException e) {

e.printStackTrace();

}

}

/**

* 设置左右声道平衡

*

*@param max 最大值

*@param balance 当前值

*/

public void setBalance(int max, int balance) {

float b = (float) balance / (float) max;

Log.i(TAG, "setBalance: b = " + b);

if (null != mAudioTrack)

mAudioTrack.setStereoVolume(1 - b, b);

}

/**

* 设置左右声道是否可用

*

*@param left 左声道

*@param right 右声道

*/

public void setChannel(boolean left, boolean right) {

if (null != mAudioTrack) {

mAudioTrack.setStereoVolume(left ? 1 : 0, right ? 1 : 0);

mAudioTrack.play();

}

}

public void pause() {

if (null != mAudioTrack)

mAudioTrack.pause();

}

public void play() {

if (null != mAudioTrack)

mAudioTrack.play();

}

public void stopp() {

releaseAudioTrack();

}

private void releaseAudioTrack() {

if (null != mAudioTrack) {

mAudioTrack.stop();

mAudioTrack.release();

mAudioTrack = null;

}

}

}

使用

从头开始播放

mPlayThread = new PlayThread(this, "tts1.pcm");

mPlayThread.start();

暂停

mPlayThread.pause();

暂停后继续播放

mPlayThread.play();

停止播放

mPlayThread.stopp();

mPlayThread = null;

左右声道控制

// 禁用左声道(右声道同理)

mPlayThread.setChannel(false, true);

向左右声道单独输出不同的音频数据

也是一个很”呵呵“的做法,但是依然还没有找到更好的方法。

构造两个AudioTrack对象,分别输出两个音频,一个禁用左声道,一个禁用右声道,达到预期效果。

mChannelLeftPlayer = new PlayThread(this, "tts1.pcm");

mChannelRightPlayer = new PlayThread(this, "tts2.pcm");

mChannelLeftPlayer.setChannel(true, false);

mChannelRightPlayer.setChannel(false, true);

mChannelLeftPlayer.start();

mChannelRightPlayer.start();

Android左右声道控制软件,Android左右声道的控制相关推荐

  1. android 左右声道,Android立体声pcm的数据结构,左右声道拆分、左右声道反转

    立体声pcm数据结构 Android录音默认录制生成的是pcm文件,假设我们设置采样率为16K,录音类型为AudioFormat.CHANNEL_IN_STEREO(立体声录音),数据类型为Audio ...

  2. Android立体声pcm的数据结构,左右声道拆分、左右声道反转

    立体声pcm数据结构 Android录音默认录制生成的是pcm文件,假设我们设置采样率为16K,录音类型为AudioFormat.CHANNEL_IN_STEREO(立体声录音),数据类型为Audio ...

  3. arxiv android app,为效率而生:好用的投屏控制软件(Android)

    为效率而生:好用的投屏控制软件(Android) 2019-04-09 11:55:20 228点赞 2795收藏 289评论 看到这个标题点进来的ios值友那绝对是真爱. 看到这个标题进来的Andr ...

  4. android 动态录音权限,Android如何判断手机是否有录音权限的工具类

    作用 判断手机是否有录音权限的工具类,兼容6.0以上以及以下android系统 测试环境 这篇文章是评论中的网友提出质疑后,经过重写修改与重写测试后编写的,我的调试环境是小米note3,Android ...

  5. android播放系统音效,Android用SoundPool播放音效

    SoundPool可以用来播放一些较短的音效,如一些信息提醒之类的 先来说下会用到的参数 SoundPool(int maxStreams, int streamType, int srcQualit ...

  6. android离线语音开发,Android应用开发之Android 云之声离线语音合成

    本文将带你了解Android应用开发之Android 云之声离线语音合成,希望本文对大家学Android有所帮助. 离线语音解析 public class SpeechUtilOffline impl ...

  7. 视频格式转换器android,佳佳Android视频格式转换器(Android视频转换软件)V12.0.1.0 免费版...

    佳佳Android视频格式转换器(Android视频转换软件)是一款功能强大的Android安卓手机视频格式转换工具.佳佳Android视频格式转换器(Android视频转换软件)可以轻松快捷的将原本 ...

  8. android蓝牙耳机录音播放,android蓝牙耳机录音并播放(二)

    Github下载 package com.example.superb.yy4; import android.content.Context; import android.media.AudioF ...

  9. 【Android FFMPEG 开发】Android 中使用 FFMPEG 将 PCM 音频采样转为 MP3 格式

    文章目录 一.前置操作 ( 移植 FFMPEG ) 二.FFMPEG 将 PCM 采样转为 MP3 格式的命令 三.Android FFMPEG 混音源代码完整示例 四.博客源码 一.前置操作 ( 移 ...

最新文章

  1. python3 类字符串名实例化对象
  2. 中交叉的线_表现力一绝!用交叉线构图拍出来的照片,竟然可以这么吸睛!
  3. linux vim下删除一行和多行
  4. 华为杯数学建模优秀论文_【优秀论文】2019数维杯国际大学生数学建模竞赛B题优秀论文...
  5. html本地载入缓存文件,Flutter中如何加载并预览本地的html文件的方法
  6. 微型计算机的分类有,微型计算机的种类很多,主要分为台式机,笔记本,还有什么...
  7. 范例ppt_经营计划与执行管理PPT,全内容商业计划书,完整课件快速套用
  8. 201521123083《Java程序设计》第11周学习总结
  9. 计算机作业有相似度,抄袭检测系统对计算机类电子作业的影响分析
  10. 检测代码运行时间(微秒级)
  11. [LeetCode] 350. 两个数组的交集 II intersection-of-two-arrays-ii(排序)
  12. 'Data_Label_Tools - 开源数据标注工具大列表
  13. java todo fixme_Java中注释TODO和FIXME的作用
  14. 在市场买一个小鸡都要20多块,为什么加工好的童子鸡才19块?
  15. Git回退和取消回退
  16. DISCUZ的数据字典3
  17. 软考程序员大纲2004
  18. JavaSwing_3.2: JScrollPane(滚动面板)
  19. 【字符转换】——全角和半角转换
  20. 百度超级链开放网络治理监督藏品火爆售罄!

热门文章

  1. 算法与数据结构(part1)--算法简介及大O表示法
  2. 第三次学JAVA再学不好就吃翔(part56)--StringBuffer的替换反转和截取功能
  3. 有道云笔记导入到CSDN博客
  4. SAP UI5 初学者教程之二十 - SAP UI5 的表达式绑定用法讲解
  5. SAP HANA Schemas 和 HDI Containers
  6. SAP Spartacus Customizing Meta Tags
  7. SAP Spartacus scss里的--cx-color-primary
  8. SAP UI5 OData, annotation这些设计的意义
  9. SAP Spartacus在没有修改用户名和密码的前提下,出现登录错误的原因
  10. 如何找到Angular应用的某个directive是属于哪一个Angular module