【发布时间】:2014-09-27 13:44:30
【问题描述】:
我正在尝试混合两个音频流以获得单个输出流,在 android 中是否可能?就我而言,我有一个来自麦克风的输入流,即我正在使用 AudioRecord 录制用户的语音。我想将这段录音与一个简短的声音剪辑混合,然后创建一个新的流,它是两个流的混合,然后通过数据报套接字发送它。 我研究了很多,这就是我所知道的。
首先,SoundPool 可以帮助我实现目标,但我认为我无法提供麦克风作为输入源。
目前我正在将 MIC 的录音保存在缓冲区中,然后通过数据报套接字将其流式传输。我想我可以将声音剪辑保存在另一个缓冲区中,然后添加两个缓冲区(我知道这是一个愚蠢的想法,因为我必须管理声音的各种属性)。
我也可以将麦克风的录音保存到一个文件中,并将声音剪辑的录音保存到另一个文件中并混合它们,但是我认为我不能这样做,因为我正在尝试通过数据报套接字流式传输录音.
我认为使用 Java 的声音 API 可以实现我想要实现的目标。但安卓不支持。
总而言之,我的最终目标是在基于 VoIP (SIP) 的呼叫中注入音效(像蟋蟀一样的音效和我的声音一起发出声音)。
我希望我对我的问题给出了明确的解释。
问题 1:我怎样才能做到这一点? 问题 2:我可以使用 Java 的 Sound API 创建一个 JAR 文件并在我的项目中使用它吗? (关于这个,我觉得不可能)
这是我的录音和音频播放的一些代码。
这是我的录音代码:
public void run() {
// TODO Auto-generated method stub
try{
int minbuffer = AudioRecord.getMinBufferSize(sample, config, format);
DatagramSocket socket = new DatagramSocket();
Log.d(TAG, "Socket Created");
socket.setBroadcast(true);
byte[] ubuff = new byte[minbuffer];
DatagramPacket packet;
Log.d(TAG, "Packet Created");
InetAddress dest = InetAddress.getByName("10.10.1.126");
//InetAddress dest = InetAddress.
//InetSocketAddress dest= new InetSocketAddress(host, port);
Log.d(TAG, "Address"+dest);
rec = new AudioRecord(MediaRecorder.AudioSource.MIC,sample,
config,format,minbuffer);
rec.startRecording();
while(status == true){
minbuffer = rec.read(ubuff, 0,ubuff.length);
Log.d(TAG, "Reading While");
packet = new DatagramPacket(ubuff, ubuff.length,dest,port);
socket.send(packet);
}
}catch(Exception e){
Log.d(TAG, "Bad Datagram");
}
}
});
stream.start();
这是我的音频播放代码:
@Override
public void run() {
// TODO Auto-generated method stub
try{
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
AudioManager mm = (AudioManager)getSystemService(AUDIO_SERVICE);
DatagramSocket rSocket = new DatagramSocket(8080);
Log.d(TAG, "Recive Socket");
int m_buf = AudioRecord.getMinBufferSize(sample, config, format);
byte[] _buff = new byte[m_buf];
AudioTrack rSpeaker = new AudioTrack(mm.STREAM_MUSIC,sample,config,
format,m_buf,AudioTrack.MODE_STREAM);
mm.setSpeakerphoneOn(false);
mm.setStreamVolume(AudioManager.STREAM_MUSIC, 100, AudioManager.MODE_IN_COMMUNICATION);
Log.d(TAG, "zzRecorder");
rSpeaker.setPlaybackRate(sample);
rSpeaker.play();
while(true){
try{
DatagramPacket rPacket = new DatagramPacket(_buff, _buff.length);
rSocket.receive(rPacket);
_buff = rPacket.getData();
rSpeaker.write(_buff, 0, m_buf);
Log.d(TAG, "Yo Start Write");
}catch(Exception e){
}
}
}catch(Exception e){
}
}
});
rvStrm.start();
【问题讨论】:
-
如果采样率相同,您可以将它们线性相加,如果瞬时总和超过满量程,则可能进行缩放。
-
“我怎样才能做到这一点?” --我不知道,对不起,因为我在音频混音方面的经验为零。 “我可以使用 Java 的 Sound API 创建一个 JAR 文件并在我的项目中使用它吗?” -- 我比较怀疑。
-
@ChrisStratton:感谢您抽出宝贵时间,我尝试过这样做,将我从麦克风获得的字节与短声音剪辑的字节相加,然后除以 2。这真的很糟糕,我对声音的各种属性一无所知。
-
@CommonsWare:感谢您抽出宝贵的时间,我也不知道,我正在尝试寻找资源来学习如何做到这一点,但找不到任何可靠的东西。您是否知道 iOS 上可用的音频工具箱(它采用两个不同的音频流并输出一个混合流)?我在Android上没有找到任何东西。 Android中是否有类似的东西?我知道 AudioRecord/AudioTrack 、 MediaRecord/MediaPlayer 和 SoundPool ,据我所知,它们不能将麦克风与声音剪辑混合。谢谢
-
如果您希望通过这个项目去任何地方,您将不得不了解声源的属性 - 采样率、采样格式等。
标签: java android sockets audio