Java,TargetDataLine读取的字节,将字节保存到文件的错误代码

Java,TargetDataLine读取的字节,将字节保存到文件的错误代码,java,audio,microphone,randomaccessfile,Java,Audio,Microphone,Randomaccessfile,我需要对麦克风捕获的声音执行数字信号处理 因此,我制作了一个Java程序,使用AudioSystem.write保存的声音效果与预期的一样,但我需要执行 在飞行中处理声音。也就是说,不需要将其存储在文件中,为此,我希望获取麦克风捕获的(声音)字节并直接处理它们。 在编写我的应用程序后,我注意到我没有得到预期的行为,所以我选择将捕获的字节存储到磁盘,并将其作为AudioSystem.write存储,我注意到两个不同文件之间的字节(有效负载,没有WAV头) 与BlockingQueue相关的代码是因

我需要对麦克风捕获的声音执行数字信号处理

因此,我制作了一个Java程序,使用
AudioSystem.write
保存的声音效果与预期的一样,但我需要执行 在飞行中处理声音。也就是说,不需要将其存储在文件中,为此,我希望获取麦克风捕获的(声音)字节并直接处理它们。 在编写我的应用程序后,我注意到我没有得到预期的行为,所以我选择将捕获的字节存储到磁盘,并将其作为
AudioSystem.write
存储,我注意到两个不同文件之间的字节(有效负载,没有WAV头)

BlockingQueue
相关的代码是因为我想使用它,而一些注释代码是因为我正在测试是否犯了错误。 频率/采样器是我应该使用的

实际上使用
音响系统。写入
不是一个选项,因为我会花费大量时间写入和重读光盘。我用它来证实我正在使用的字节

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;
    }

  }

}
公共类CatchingSoundBytes{
公共静态void main(字符串[]args){
试一试{
新的CatchingSoundBytes().executor();
}捕获(LineUnavailableException ex){
例如printStackTrace();
}
}
public void executor()引发LineUnavailableException{
int numChannels=1;
int numBytesPerSample=2;
int-sampleRate=8192;
AudioFormat AudioFormat=新的AudioFormat(sampleRate,8*numBytesPerSample,NumChannel,true,true);
DataLine.Info dataLineInfo=新的DataLine.Info(TargetDataLine.class,audioformat);
TargetDataLine TargetDataLine=(TargetDataLine)AudioSystem.getLine(dataLineInfo);
试一试{
targetDataLine.open(音频格式);
targetDataLine.start();
}捕获(LineUnavailableException ex){
System.out.println(“ex:+ex.getMessage());
}
int bufferSize=(int)Math.pow(2.0,11);
final PipedOutputStream srcSavePOStream=新的PipedOutputStream();
最终PipedInputStream snkSavePIStream=新的PipedInputStream(bufferSize);
试一试{
snkSavePIStream.connect(srcSavePOStream);
}捕获(IOEX异常){
System.out.println(“ex:+ex.getMessage());
}
字符串dateFilename=new SimpleDateFormat(“yyyyMMdd HHmm”).format(new Date());
//INI保存文件
新线程(()->{
AudioInputStream=新的AudioInputStream((InputStream)snkSavePIStream,audioformat,AudioSystem.未指定);
File fileRecordedWav=新文件(“Rec_”+dateFilename+”.wav);
System.out.println(“fileRecordedWav:+fileRecordedWav.getAbsolutePath());
试一试{
AudioSystem.write(AIS录制,AudioFileFormat.Type.WAVE,fileRecordedWav);
}捕获(IOEX异常){
System.out.println(“保存文件->ex:+ex.getMessage());
}
}).start();
//结束保存文件
/*
PipedOutputStream rafPOStream=新的PipedOutputStream();
PipedInputStream rafPIStream=新的PipedInputStream(缓冲区大小);
试一试{
rafPIStream.connect(rafPOStream);
}捕获(IOEX异常){
System.out.println(“ex:+ex.getMessage());
}
*/
BlockingQueue BlockingQueue=新建LinkedBlockingQueue();
塞子=新塞子();
stopper.setRunning(真);
//捕捉声音
新线程(()->{
长指数=0;
字节[]缓冲区=新字节[bufferSize];
while(stopper.isRunning()){
试一试{
int count=targetDataLine.read(缓冲区,0,缓冲区大小);
如果(计数>0){
字节[]输出=新字节[计数];
System.arraycopy(缓冲区,0,输出,0,计数);
srcSavePOStream.write(输出);//使用AudioSystem.write发送以保存
//rafPOStream.write(输出);
blockingQueue.put(newbytesound(output,index));//使用RandomAccessFile发送以保存
}
}捕获(例外情况除外){
System.out.println(“捕获声音->例如:+ex.getMessage());
}
索引++;
}
targetDataLine.stop();
试一试{
targetDataLine.close();
}捕获(安全异常e){
}
}).start();
//末端捕捉声音
//INI保存随机访问文件
新线程(()->{
String filename=“Raf_”+dateFilename+”.wav”;
System.out.println(“raf:+filename”);
长指数=0;
字节[]缓冲区=新字节[bufferSize];
while(stopper.isRunning()){
试一试{
BytesSound BytesSound=blockingQueue.take();
如果(通过终止的声音实例){
打破
}
/*
rafPIStream.read(缓冲区);
BytesSound BytesSound=新的BytesSound(缓冲区、索引);
*/
//我真的不需要在这个阶段保存字节,
//仅为了与使用AudioSystem.write的方法的有效负载进行比较
//我需要处理的字节和位置
RandomAccessFile raf=新的RandomAccessFile(文件名,“rw”);
添加样本(raf、bytesSound);
}捕获(例外情况除外){
System.out.println(“保存随机访问文件->ex:+ex.getMessage());
}
索引++;
}
}
).start();
//结束保存随机访问文件
新计时器(true).计划(新计时器任务(){
@凌驾
公开募捐{
stopper.setRunning(假);
}
},4000升);
}
私有void addSample(随机访问文件raf,BytesSound BytesSound){
试一试{
seek(bytesSound.getIndex()*bytesSound.getChunk().length);
write(bytesSound.getChunk());
}捕获(IOEX异常){
System.out.println(“ex:+ex.getMessage());
}
}
私家班{
私有最终字节[]块;
私人最终长期指数;
公共字节(字节)[
boolean endianness = false;
AudioFormat audioformat = new AudioFormat(sampleRate, 8 * numBytesPerSample,
    numChannels, true, endianness);
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;
    boolean endianness = false;
    AudioFormat audioformat = new AudioFormat(sampleRate, 8 * numBytesPerSample, numChannels, true, endianness);
    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 = (endianness ? "Big" : "Lit") + 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("AIS_" + 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

    BlockingQueue<BytesSound> blockingQueue = new LinkedBlockingQueue<>();
    Stopper stopper = new Stopper();
    stopper.setRunning(true);

    // INI Capture Sound
    new Thread(() -> {
      try {
        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
              blockingQueue.put(new BytesSound(endiannessReorderedBytes(output, audioformat), index)); // Send to Save Using RandomAccessFile
            }
          } catch (Exception ex) {
            System.out.println("Capture Sound -> ex:" + ex.getMessage());
          }
          index++;
          if (index > 1) {
            break;
          }
        }
        targetDataLine.stop();
      } catch (Exception ex) {
        System.out.println("Capture Sound -> ex:" + ex.getMessage());
      } finally {
        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;
      while (stopper.isRunning()) {
        try {
          BytesSound bytesSound = blockingQueue.take();
          if (bytesSound instanceof Kill) {
            break;
          }
          //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);
          raf.close();
        } catch (Exception ex) {
          System.out.println("Save RandomAccessFile File -> ex:" + ex.getMessage());
        }
        index++;
        if (index > 1) {
          break;
        }
      }
      System.out.println("Expected Size:" + index * bufferSize);
    }
    ).start();
    // END Save RandomAccessFile File

    new Timer(true).schedule(new TimerTask() {
      @Override
      public void run() {
        stopper.setRunning(false);
      }
    }, 4000L);
  }

  private byte[] endiannessReorderedBytes(byte[] incomingBytes, AudioFormat audioformat) {
    if (!(incomingBytes != null && audioformat != null)) {
      throw new IllegalArgumentException("Some arguments are null.");
    }
    byte[] outgoingBytes = new byte[incomingBytes.length];
    if (audioformat.getSampleSizeInBits() == 16) {
      if (incomingBytes.length % 2 != 0) {
        throw new IllegalArgumentException("The size of the byte array does not match the audio format.");
      }
      int count = incomingBytes.length / 2;
      if (audioformat.isBigEndian()) {
        for (int i = 0; i < count; i++) {
          outgoingBytes[i * 2] = incomingBytes[i * 2 + 1];
          outgoingBytes[i * 2 + 1] = incomingBytes[i * 2];
        }
      } else {
        System.arraycopy(incomingBytes, 0, outgoingBytes, 0, incomingBytes.length);
      }
    } else {
      if (audioformat.getEncoding() == Encoding.PCM_SIGNED) {
        for (int i = 0; i < incomingBytes.length; i++) {
          outgoingBytes[i] = (byte) (0x80 ^ incomingBytes[i]);
        }
      } else {
        System.arraycopy(incomingBytes, 0, outgoingBytes, 0, incomingBytes.length);
      }
    }
    return outgoingBytes;
  }


  private void addSample(RandomAccessFile raf, BytesSound bytesSound) {
    try {
      raf.seek(44 /*Header Length*/ + 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;
    }

  }
}