「javapcm音频」java 音频
今天给各位分享javapcm音频的知识,其中也会对java 音频进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、Android音视频系列(七):PCM音频单声道与双声道的相互转换
- 2、java音频处理问题
- 3、java 声音采集与播放 在Win7,8下AudioFormat应填写什么参数
- 4、Android音视频【十二】使用OpenSLES和AudioTrack进行播放PCM
- 5、JAVA 实现音频播放
Android音视频系列(七):PCM音频单声道与双声道的相互转换
上一篇我们已经学习了PCM音频的保存格式,这一篇我们通过掌握的知识,完成PCM音频的单声道和双声道的互相转换。
首先我们把上一篇的最核心部分贴出来:
我们首先完成单声道转双声道的操作。
单声道转双声道的基本原理:
首先我录制了一个音频保存到ArrayList中:
录制的是16位的数据,所以我们每一个采样的数据会占据两位,所以在拷贝的过程中,我们也要每两位拷贝一次:
单声道转声道的操作就完成了。
双声道转单声道的原理:
我们可以按照单声道双声道的做法,每四位取前两位或后两位的数据即可。但是这里我们换一种做法。
这里我们使用了ByteBuffer帮助我们把Byte转成Short。其中有一个很重要的坑,就是设置Byte转Short的规则:
所以我们一定要确保高低位的顺序,否则得到的Short一定是错的,经过测试,录制的音频是低位在前,所以我们修改ByteBuffer默认的高位在前的配置:
相同的原理,我们需要Byte转Int都可以借助对应的Buffer进行读取,非常的方便。
基本流程和第一种方法一样,如果是你用的Java,你还可以通过位运算进行Short和Byte的转换,但是kotlin的对应的运算符却无法正确转换,具体原因还不清楚,这也是为什么我使用了Buffer进行转换的原因。
只要我们掌握了PCM的保存格式,单声道和双声道的互相转换还是非常轻松的,下一篇我们来了解一下新的音频格式:WAV。
java音频处理问题
为什么audioFormat.getChannels(), 一次后还要再一个audioFormat.getChannels()*2
每声道每帧字节数2字节,再加上双声道所以用声道数(2)*字节数(2) = 每帧的总字节数
看来你的audioFormat不是从AudioInputStream中产生的啊?刚才回答你的问题我还没注意。原来audioFormat也可以new出来的啊,嘿嘿。
java 声音采集与播放 在Win7,8下AudioFormat应填写什么参数
1 AudioTrack应用实例
对于Android应用开发人员来讲,音频回放最熟悉的莫过于MediaPlayer,而AudioTrack相信用的人相对会少很多。这是因为MediaPlayer提供了更完整的封装和状态控制,使得我们用很少的代码就可以实现一个简单的音乐播放器。而相比MediaPlayer,AudioTrack更为精练、高效,实际上MediaPlayerService的内部实现就是使用了AudioTrack。
AudioTrack被用于PCM音频流的回放,在数据传送上它有两种方式:
Ø 调用write(byte[],int,int)或write(short[],int,int)把音频数据“push”到AudioTrack中。
Ø 与之相对的,当然就是“pull”形式的数据获取,即数据接收方主动索取的过程,如下图所示:
图 13‑20 “push”和“pull”两种数据传送模式
除此之外,AudioTrack还同时支持static和streaming两种模式:
§ static
静态的言下之意就是数据一次性交付给接收方。好处是简单高效,只需要进行一次操作就完成了数据的传递;缺点当然也很明显,对于数据量较大的音频回放,显然它是无法胜任的,因而通常只用于播放铃声、系统提醒等对内存小的操作
§ streaming
流模式和网络上播放视频是类似的,即数据是按照一定规律不断地传递给接收方的。理论上它可用于任何音频播放的场景,不过我们一般在以下情况下采用:
Ø 音频文件过大
Ø 音频属性要求高,比如采样率高、深度大的数据
Ø 音频数据是实时产生的,这种情况就只能用流模式了
下面我们选取AudioTrackTest.java为例来讲解,先从使用者的角度来了解下AudioTrack。
/*cts/tests/tests/media/src/android/media/cts*/
public voidtestSetStereoVolumeMax() throwsException {
final String TEST_NAME= "testSetStereoVolumeMax";
final int TEST_SR =22050;
final int TEST_CONF =AudioFormat.CHANNEL_CONFIGURATION_STEREO;
final int TEST_FORMAT= AudioFormat.ENCODING_PCM_16BIT;
final int TEST_MODE =AudioTrack.MODE_STREAM;
final intTEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
// --------initialization --------------
/*Step1.*/
int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
/*Step 2.*/
AudioTrack track = newAudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF,
TEST_FORMAT, 2 * minBuffSize,TEST_MODE);
byte data[] = newbyte[minBuffSize];
// -------- test--------------
track.write(data, OFFSET_DEFAULT, data.length);
track.write(data, OFFSET_DEFAULT, data.length);
track.play();
float maxVol =AudioTrack.getMaxVolume();
assertTrue(TEST_NAME, track.setStereoVolume(maxVol, maxVol) == AudioTrack.SUCCESS);
// -------- tear down--------------
track.release();
}
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还是蛮强大的。
JAVA 实现音频播放
这个程序只要写对了音乐文件的URL地址,例如:new URL("file:/C:/tmp/1/Windows Ding.wav");
就可以播放音乐,除了可以播放.wav格式的音乐,还可以播放.au格式的音乐。
另外,如果你不希望音乐循环播放,你可以去掉audio1.loop();这一语句。
import java.applet.AudioClip;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JFrame;
public class D extends JFrame{
D(){
setSize(200,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
URL codebase=null;
try {
codebase = new URL("file:/C:/tmp/1/Windows Ding.wav");
} catch (MalformedURLException e) {
e.printStackTrace();
}
AudioClip audio1=Applet.newAudioClip(codebase);
audio1.loop();
}
public static void main(String[] args) {
new D();
}
}
javapcm音频的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于java 音频、javapcm音频的信息别忘了在本站进行查找喔。
发布于:2022-12-08,除非注明,否则均为
原创文章,转载请注明出处。