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

问题描述 投票:0回答:1

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

由于这个原因,我制作了一个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保存的声音按预期工作,但是我需要...

java audio microphone randomaccessfile
1个回答
0
投票

使用二进制比较器详细查看...

© www.soinside.com 2019 - 2024. All rights reserved.