我创建了一个字节数组WebSocket,它从客户端的麦克风(navigator.getUserMedia)实时接收音频块。我已经将此流记录到服务器中的WAV文件,一段时间后,WebSocket停止接收新的字节数组。下面的代码表示当前的情况。
WebSocket
@OnMessage
public void message(byte[] b) throws IOException{
if(byteOutputStream == null) {
byteOutputStream = new ByteArrayOutputStream();
byteOutputStream.write(b);
} else {
byteOutputStream.write(b);
}
}
存储WAV文件的线程
public void store(){
byte b[] = byteOutputStream.toByteArray();
try {
AudioFormat audioFormat = new AudioFormat(44100, 16, 1, true, true);
ByteArrayInputStream byteStream = new ByteArrayInputStream(b);
AudioInputStream audioStream = new AudioInputStream(byteStream, audioFormat, b.length);
DateTime date = new DateTime();
File file = new File("/tmp/"+date.getMillis()+ ".wav");
AudioSystem.write(audioStream, AudioFileFormat.Type.WAVE, file);
audioStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
但不是记录WAV文件,我的目标是使用在TarsosDSP库上实现的YIN音调检测算法实时处理音频。换句话说,这基本上是执行pitchdetectoreexample,但是使用来自WebSocket而不是默认音频设备(OS mic)的数据。以下代码表示pitchdetectoreexample当前如何使用操作系统提供的麦克风线初始化实时音频处理。
private void setNewMixer(Mixer mixer) throws LineUnavailableException, UnsupportedAudioFileException {
if(dispatcher!= null){
dispatcher.stop();
}
currentMixer = mixer;
float sampleRate = 44100;
int bufferSize = 1024;
int overlap = 0;
final AudioFormat format = new AudioFormat(sampleRate, 16, 1, true, true);
final DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, format);
TargetDataLine line;
line = (TargetDataLine) mixer.getLine(dataLineInfo);
final int numberOfSamples = bufferSize;
line.open(format, numberOfSamples);
line.start();
final AudioInputStream stream = new AudioInputStream(line);
JVMAudioInputStream audioStream = new JVMAudioInputStream(stream);
// create a new dispatcher
dispatcher = new AudioDispatcher(audioStream, bufferSize, overlap);
// add a processor
dispatcher.addAudioProcessor(new PitchProcessor(algo, sampleRate, bufferSize, this));
new Thread(dispatcher,"Audio dispatching").start();
}
有一种方法来处理WebSocket数据作为TargetDataLine,所以它将有可能与AudioDispatcher和PitchProcessor挂钩?不知何故,我需要将从WebSocket接收到的字节数组发送到音频处理线程。
关于如何达到这个目标的其他想法是受欢迎的。谢谢!
我不确定您是否需要audioDispatcher。如果你知道字节是如何编码的(PCM, 16位单声道?),那么你可以将它们实时转换为浮点数并将它们提供给音调检测器算法,在你的websocket中你可以这样做(忘记输入流和audiodispatcher):
int index;
byte[] buffer = new byte[2048];
float[] floatBuffer = new float[1024];
FastYin detector = new FastYin(44100,1024);
public void message(byte[] b){
for(int i = 0 ; i < b.length; i++){
buffer[index] = b[i];
index++
if(index==2048){
AudioFloatConverter converter = AudioFloatConverter.getConverter(new Format(16bits, little endian, mono,...));
//converts the byte buffer to float
converter.toFloatArray(buffer,floatBuffer);
float pitch = detector.getPitch(floatBuffer);
//here you have your pitch info that you can use
index = 0;
}
}
您确实需要观察已传递的字节数:由于两个字节表示一个浮点数(如果使用16位pcm编码),您需要从偶数字节开始。端序和采样也很重要。
对
Joren