我需要对麦克风捕获的声音执行数字信号处理。>>
由于这个原因,我制作了一个Java程序,使用AudioSystem.write
保存的声音效果与预期的一样,但是我需要执行实时处理声音。也就是说,没有将其存储在文件中,我想要获取麦克风捕获的字节(声音)并直接对其进行处理。编写应用程序后,我注意到我没有达到预期的行为,因此我选择将捕获的字节存储到磁盘,并与AudioSystem.write
存储的字节进行比较,然后发现字节(有效载荷,不带WAV头)在两个不同文件之间。
与BlockingQueue
相关的代码是因为我想使用它,而一些注释的代码是因为我正在测试是否犯了错误。我应该使用频率/ sampleRate 8192
实际上使用AudioSystem.write
不是选项
public class CatchingSoundBytes { public static void main(String[] args) { try { new CatchingSoundBytes().executor(); } catch (LineUnavailableException ex) { ex.printStackTrace(); } } public void executor() throws LineUnavailableException { int numChannels = 1; int numBytesPerSample = 2; int sampleRate = 8192; AudioFormat audioformat = new AudioFormat(sampleRate, 8 * numBytesPerSample, numChannels, true, true); DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioformat); TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo); try { targetDataLine.open(audioformat); targetDataLine.start(); } catch (LineUnavailableException ex) { System.out.println("ex:" + ex.getMessage()); } int bufferSize = (int) Math.pow(2.0, 11); final PipedOutputStream srcSavePOStream = new PipedOutputStream(); final PipedInputStream snkSavePIStream = new PipedInputStream(bufferSize); try { snkSavePIStream.connect(srcSavePOStream); } catch (IOException ex) { System.out.println("ex:" + ex.getMessage()); } String dateFilename = new SimpleDateFormat("yyyyMMdd-HHmm").format(new Date()); // INI Save File new Thread(() -> { AudioInputStream aisRecording = new AudioInputStream((InputStream) snkSavePIStream, audioformat, AudioSystem.NOT_SPECIFIED); File fileRecordedWav = new File("Rec_" + dateFilename + ".wav"); System.out.println("fileRecordedWav:" + fileRecordedWav.getAbsolutePath()); try { AudioSystem.write(aisRecording, AudioFileFormat.Type.WAVE, fileRecordedWav); } catch (IOException ex) { System.out.println("Save File -> ex:" + ex.getMessage()); } }).start(); // END Save File /* PipedOutputStream rafPOStream = new PipedOutputStream(); PipedInputStream rafPIStream = new PipedInputStream(bufferSize); try { rafPIStream.connect(rafPOStream); } catch (IOException ex) { System.out.println("ex:" + ex.getMessage()); } */ BlockingQueue<BytesSound> blockingQueue = new LinkedBlockingQueue<>(); Stopper stopper = new Stopper(); stopper.setRunning(true); // INI Capture Sound new Thread(() -> { long index = 0; byte[] buffer = new byte[bufferSize]; while (stopper.isRunning()) { try { int count = targetDataLine.read(buffer, 0, bufferSize); if (count > 0) { byte[] output = new byte[count]; System.arraycopy(buffer, 0, output, 0, count); srcSavePOStream.write(output); // Send to Save Using AudioSystem.write //rafPOStream.write(output); blockingQueue.put(new BytesSound(output, index)); // Send to Save Using RandomAccessFile } } catch (Exception ex) { System.out.println("Capture Sound -> ex:" + ex.getMessage()); } index++; } targetDataLine.stop(); try { targetDataLine.close(); } catch (SecurityException e) { } }).start(); // END Capture Sound // INI Save RandomAccessFile File new Thread(() -> { String filename = "Raf_" + dateFilename + ".wav"; System.out.println("raf:" + filename); long index = 0; byte[] buffer = new byte[bufferSize]; while (stopper.isRunning()) { try { BytesSound bytesSound = blockingQueue.take(); if (bytesSound instanceof Kill) { break; } /* rafPIStream.read(buffer); BytesSound bytesSound = new BytesSound(buffer, index); */ //REALLY I don't need to save bytes in this stage, //only in order to compare with payload of method using AudioSystem.write // I need the bytes and position for processing RandomAccessFile raf = new RandomAccessFile(filename, "rw"); addSample(raf, bytesSound); } catch (Exception ex) { System.out.println("Save RandomAccessFile File -> ex:" + ex.getMessage()); } index++; } } ).start(); // END Save RandomAccessFile File new Timer(true).schedule(new TimerTask() { @Override public void run() { stopper.setRunning(false); } }, 4000L); } private void addSample(RandomAccessFile raf, BytesSound bytesSound) { try { raf.seek(bytesSound.getIndex() * bytesSound.getChunk().length); raf.write(bytesSound.getChunk()); } catch (IOException ex) { System.out.println("ex:" + ex.getMessage()); } } private class BytesSound { private final byte[] chunk; private final long index; public BytesSound(byte[] chunk, long index) { this.chunk = chunk; this.index = index; } public byte[] getChunk() { return chunk; } public long getIndex() { return index; } } private class Kill extends BytesSound { public Kill(byte[] chunk, long index) { super(chunk, index); } } private class Stopper { private boolean running; public boolean isRunning() { return running; } public void setRunning(boolean running) { this.running = running; } } }
为了正确地直接从麦克风获取字节,我应该改变什么?
我需要对麦克风捕获的声音进行数字信号处理。因此,我制作了一个Java程序,使用AudioSystem.write保存的声音按预期工作,但是我需要...
使用二进制比较器详细查看...