Java - 从混音器录音

发布于 2024-11-07 05:38:45 字数 13797 浏览 0 评论 0原文

我有一个与我之前的问题相关的问题。我想从混音器(扬声器)录制音频,我正在使用 javax.sound。我必须设置audioFormat,但我不知道在那里输入什么:/使用类ListMixer(我在这里找到的-> http://forums.oracle.com/forums/thread.jspa?threadID=2198477&tstart=2),我写的是这样的:< a href="http://forums.oracle.com/forums/thread.jspa?threadID=2198477&tstart=2" rel="noreferrer">http://forums.oracle.com/forums/thread.jspa? threadID=2198477&tstart=2 但我没有任何有关采样率的信息(未知采样率)。程序抛出此异常:

java.lang.IllegalArgumentException:线路不受支持:接口 TargetDataLine 支持格式 PCM_UNSIGNED 44100.0 Hz,8 位,单声道,4 字节/帧,

代码:

package sound;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;

public class AudioCapture02 extends JFrame{

  boolean stopCapture = false;
  ByteArrayOutputStream byteArrayOutputStream;
  AudioFormat audioFormat;
  TargetDataLine targetDataLine;
  AudioInputStream audioInputStream;
  SourceDataLine sourceDataLine;

  public AudioCapture02(){//constructor
    final JButton captureBtn =
                          new JButton("Capture");
    final JButton stopBtn = new JButton("Stop");
    final JButton playBtn =
                         new JButton("Playback");

    captureBtn.setEnabled(true);
    stopBtn.setEnabled(false);
    playBtn.setEnabled(false);

    //Register anonymous listeners
    captureBtn.addActionListener(
      new ActionListener(){
        public void actionPerformed(
                                 ActionEvent e){
          captureBtn.setEnabled(false);
          stopBtn.setEnabled(true);
          playBtn.setEnabled(false);
          //Capture input data from the
          // microphone until the Stop button is
          // clicked.
          captureAudio();
        }//end actionPerformed
      }//end ActionListener
    );//end addActionListener()
    getContentPane().add(captureBtn);

    stopBtn.addActionListener(
      new ActionListener(){
        public void actionPerformed(
                                 ActionEvent e){
          captureBtn.setEnabled(true);
          stopBtn.setEnabled(false);
          playBtn.setEnabled(true);
          //Terminate the capturing of input data
          // from the microphone.
          stopCapture = true;
        }//end actionPerformed
      }//end ActionListener
    );//end addActionListener()
    getContentPane().add(stopBtn);

    playBtn.addActionListener(
      new ActionListener(){
        public void actionPerformed(
                                 ActionEvent e){
          //Play back all of the data that was
          // saved during capture.
          playAudio();
        }//end actionPerformed
      }//end ActionListener
    );//end addActionListener()
    getContentPane().add(playBtn);

    getContentPane().setLayout(new FlowLayout());
    setTitle("Capture/Playback Demo");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(250,70);
    setVisible(true);
  }//end constructor

  //This method captures audio input from a
  // microphone and saves it in a
  // ByteArrayOutputStream object.
  private void captureAudio(){
    try{
      //Get and display a list of
      // available mixers.
      Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
      System.out.println("Available mixers:");
      for(int cnt = 0; cnt < mixerInfo.length;
                                          cnt++){
        System.out.println(mixerInfo[cnt].
                                      getName());
      }//end for loop

      //Get everything set up for capture
      audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED, 44100.0F, 8, 1, 4, 44100.0F,
                        false);


      DataLine.Info dataLineInfo =
                            new DataLine.Info(
                            TargetDataLine.class,
                            audioFormat);
      ListMixers lm = new ListMixers();
      lm.listAll(new PrintWriter(System.out));

      System.out.println(" AKTUALNY => "+mixerInfo[0].getName());
      Mixer mixer = AudioSystem.getMixer(mixerInfo[0]);

      //Get a TargetDataLine on the selected
      // mixer.
      targetDataLine = (TargetDataLine)
                     mixer.getLine(dataLineInfo);
      //Prepare the line for use.
      targetDataLine.open(audioFormat);
      targetDataLine.start();

      //Create a thread to capture the microphone
      // data and start it running.  It will run
      // until the Stop button is clicked.
      Thread captureThread = new CaptureThread();
      captureThread.start();
    } catch (Exception e) {
      System.out.println(e);
      System.exit(0);
    }//end catch
  }//end captureAudio method

  //This method plays back the audio data that
  // has been saved in the ByteArrayOutputStream
  private void playAudio() {
    try{
      //Get everything set up for playback.
      //Get the previously-saved data into a byte
      // array object.
      byte audioData[] = byteArrayOutputStream.
                                   toByteArray();
      //Get an input stream on the byte array
      // containing the data
      InputStream byteArrayInputStream =
             new ByteArrayInputStream(audioData);
      AudioFormat audioFormat = getAudioFormat();
      audioInputStream = new AudioInputStream(
                    byteArrayInputStream,
                    audioFormat,
                    audioData.length/audioFormat.
                                 getFrameSize());
      DataLine.Info dataLineInfo =
                            new DataLine.Info(
                            SourceDataLine.class,
                            audioFormat);
      sourceDataLine = (SourceDataLine)
               AudioSystem.getLine(dataLineInfo);
      sourceDataLine.open(audioFormat);
      sourceDataLine.start();

      //Create a thread to play back the data and
      // start it  running.  It will run until
      // all the data has been played back.
      Thread playThread = new PlayThread();
      playThread.start();
    } catch (Exception e) {
      System.out.println(e);
      System.exit(0);
    }//end catch
  }//end playAudio

  //This method creates and returns an
  // AudioFormat object for a given set of format
  // parameters.  If these parameters don't work
  // well for you, try some of the other
  // allowable parameter values, which are shown
  // in comments following the declartions.
  private AudioFormat getAudioFormat(){
    float sampleRate = 8000.0F;
    //8000,11025,16000,22050,44100
    int sampleSizeInBits = 16;
    //8,16
    int channels = 1;
    //1,2
    boolean signed = true;
    //true,false
    boolean bigEndian = false;
    //true,false
    return new AudioFormat(
                      sampleRate,
                      sampleSizeInBits,
                      channels,
                      signed,
                      bigEndian);
  }//end getAudioFormat
//=============================================//

//Inner class to capture data from microphone
class CaptureThread extends Thread{
  //An arbitrary-size temporary holding buffer
  byte tempBuffer[] = new byte[10000];
  public void run(){
    byteArrayOutputStream =
                     new ByteArrayOutputStream();
    stopCapture = false;
    try{//Loop until stopCapture is set by
        // another thread that services the Stop
        // button.
      while(!stopCapture){
        //Read data from the internal buffer of
        // the data line.
        int cnt = targetDataLine.read(tempBuffer,
                              0,
                              tempBuffer.length);
        if(cnt > 0){
          //Save data in output stream object.
          byteArrayOutputStream.write(tempBuffer,
                                      0,
                                      cnt);
        }//end if
      }//end while
      byteArrayOutputStream.close();
    }catch (Exception e) {
      System.out.println(e);
      System.exit(0);
    }//end catch
  }//end run
}//end inner class CaptureThread
//===================================//
//Inner class to play back the data
// that was saved.
class PlayThread extends Thread{
  byte tempBuffer[] = new byte[10000];

  public void run(){
    try{
      int cnt;
      //Keep looping until the input read method
      // returns -1 for empty stream.
      while((cnt = audioInputStream.read(
                      tempBuffer, 0,
                      tempBuffer.length)) != -1){
        if(cnt > 0){
          //Write data to the internal buffer of
          // the data line where it will be
          // delivered to the speaker.
          sourceDataLine.write(tempBuffer,0,cnt);
        }//end if
      }//end while
      //Block and wait for internal buffer of the
      // data line to empty.
      sourceDataLine.drain();
      sourceDataLine.close();
    }catch (Exception e) {
      System.out.println(e);
      System.exit(0);
    }//end catch
  }//end run
}//end inner class PlayThread
//=============================================//
class ListMixers {
    PrintWriter out;

     void listAll(final PrintWriter out) {
        this.out = out;
        Mixer.Info[] aInfos = AudioSystem.getMixerInfo();
        for (int i = 0; i < aInfos.length; i++) {
            try {
                Mixer mixer = AudioSystem.getMixer(aInfos[i]);
                out.println(""+i+": "+aInfos[i].getName()+", "
                        +aInfos[i].getVendor()+", "
                        +aInfos[i].getVersion()+", "
                        +aInfos[i].getDescription());

                printLines(mixer, mixer.getSourceLineInfo());
                printLines(mixer, mixer.getTargetLineInfo());
            } catch (Exception e) {
                out.println("Exception: "+e);
            }
            out.println();
        }
        if (aInfos.length == 0) {
            out.println("[No mixers available]");
        }
    }

    void printLines(Mixer mixer, Line.Info[] infos) {
        for (int i = 0; i < infos.length; i++) {
            try {
                if (infos[i] instanceof Port.Info) {
                    Port.Info info = (Port.Info) infos[i];

                    out.println("  Port " + info);
                }
                if (infos[i] instanceof DataLine.Info) {
                    DataLine.Info info = (DataLine.Info) infos[i];

                    out.println("  Line " + info + " (max. " +
                                mixer.getMaxLines(info) + " simultaneously): ");
                    printFormats(info);
                }
                Line line = mixer.getLine(infos[i]);

                if (!(line instanceof Clip)) {
                    try {
                        line.open();
                    }
                    catch (LineUnavailableException e) {
                        out.println("LineUnavailableException when trying to open this line");
                    }
                }
                try {
                    printControls(line.getControls());
                }
                finally {
                    if (!(line instanceof Clip)) {
                        line.close();
                    }
                }
            }
            catch (Exception e) {
                out.println("Exception: " + e);
            }
            out.println();
        }
    }

    void printFormats(DataLine.Info info) {
        AudioFormat[] formats = info.getFormats();
        for (int i = 0; i < formats.length; i++) {
            out.println("  "+i+": "+formats[i]
                    +" ("+formats[i].getChannels()+" channels, "
                    +"frameSize="+formats[i].getFrameSize()+", "
                    +(formats[i].isBigEndian()?"big endian":"little endian")
                    +")");
        }
        if (formats.length == 0) {
            out.println("  [no formats]");
        }
        out.println();
    }

    void printControls(Control[] controls) {
        for (int i = 0; i<controls.length; i++) {
            printControl("    ", "Controls["+i+"]: ", controls[i]);
        }
        if (controls.length == 0) {
            out.println("    [no controls]");
        }
        out.println();
    }

    void printControl(String indent, String id, Control control) {
        if (control instanceof BooleanControl) {
            BooleanControl ctrl = (BooleanControl) control;
            out.println(indent+id+"BooleanControl: "+ctrl);
        } else if (control instanceof CompoundControl) {
            CompoundControl ctrl = (CompoundControl) control;
            Control[] ctrls = ctrl.getMemberControls();
            out.println(indent+id+"CompoundControl: "+control);
            for (int i=0; i<ctrls.length; i++) {
                printControl(indent+"  ", "MemberControls["+i+"]: ", ctrls[i]);
            }
        } else if (control instanceof EnumControl) {
            EnumControl ctrl = (EnumControl) control;
            Object[] values = ctrl.getValues();
            Object value = ctrl.getValue();
            out.println(indent+id+"EnumControl: "+control);
            for (int i=0; i<values.length; i++) {
                if (values[i] instanceof Control) {
                    printControl(indent+"  ", "Values["+i+"]: "+((values[i]==value)?"*":""), (Control) values[i]);
                } else {
                    out.println(indent+"  Values["+i+"]: "+((values[i]==value)?"*":"")+values[i]);
                }
            }
        } else if (control instanceof FloatControl) {
            FloatControl ctrl = (FloatControl) control;
            out.println(indent+id+"FloatControl: "+ctrl);
        } else {
            out.println(indent+id+"Control: "+control);
        }
    }
}
}//end outer class AudioCapture02.java

I have a problem connected with my previous question. I want to record audio from mixer (speakers), I'm using javax.sound. I have to set up audioFormat and I don't know what to type there :/ Using class ListMixer (which I found here -> http://forums.oracle.com/forums/thread.jspa?threadID=2198477&tstart=2), I write something like this: http://forums.oracle.com/forums/thread.jspa?threadID=2198477&tstart=2 but I don't have any info about sample rate (unknown sample rate). Program is throwing this exception:

java.lang.IllegalArgumentException: Line unsupported: interface TargetDataLine supporting format PCM_UNSIGNED 44100.0 Hz, 8 bit, mono, 4 bytes/frame,

Code:

package sound;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;

public class AudioCapture02 extends JFrame{

  boolean stopCapture = false;
  ByteArrayOutputStream byteArrayOutputStream;
  AudioFormat audioFormat;
  TargetDataLine targetDataLine;
  AudioInputStream audioInputStream;
  SourceDataLine sourceDataLine;

  public AudioCapture02(){//constructor
    final JButton captureBtn =
                          new JButton("Capture");
    final JButton stopBtn = new JButton("Stop");
    final JButton playBtn =
                         new JButton("Playback");

    captureBtn.setEnabled(true);
    stopBtn.setEnabled(false);
    playBtn.setEnabled(false);

    //Register anonymous listeners
    captureBtn.addActionListener(
      new ActionListener(){
        public void actionPerformed(
                                 ActionEvent e){
          captureBtn.setEnabled(false);
          stopBtn.setEnabled(true);
          playBtn.setEnabled(false);
          //Capture input data from the
          // microphone until the Stop button is
          // clicked.
          captureAudio();
        }//end actionPerformed
      }//end ActionListener
    );//end addActionListener()
    getContentPane().add(captureBtn);

    stopBtn.addActionListener(
      new ActionListener(){
        public void actionPerformed(
                                 ActionEvent e){
          captureBtn.setEnabled(true);
          stopBtn.setEnabled(false);
          playBtn.setEnabled(true);
          //Terminate the capturing of input data
          // from the microphone.
          stopCapture = true;
        }//end actionPerformed
      }//end ActionListener
    );//end addActionListener()
    getContentPane().add(stopBtn);

    playBtn.addActionListener(
      new ActionListener(){
        public void actionPerformed(
                                 ActionEvent e){
          //Play back all of the data that was
          // saved during capture.
          playAudio();
        }//end actionPerformed
      }//end ActionListener
    );//end addActionListener()
    getContentPane().add(playBtn);

    getContentPane().setLayout(new FlowLayout());
    setTitle("Capture/Playback Demo");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(250,70);
    setVisible(true);
  }//end constructor

  //This method captures audio input from a
  // microphone and saves it in a
  // ByteArrayOutputStream object.
  private void captureAudio(){
    try{
      //Get and display a list of
      // available mixers.
      Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
      System.out.println("Available mixers:");
      for(int cnt = 0; cnt < mixerInfo.length;
                                          cnt++){
        System.out.println(mixerInfo[cnt].
                                      getName());
      }//end for loop

      //Get everything set up for capture
      audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED, 44100.0F, 8, 1, 4, 44100.0F,
                        false);


      DataLine.Info dataLineInfo =
                            new DataLine.Info(
                            TargetDataLine.class,
                            audioFormat);
      ListMixers lm = new ListMixers();
      lm.listAll(new PrintWriter(System.out));

      System.out.println(" AKTUALNY => "+mixerInfo[0].getName());
      Mixer mixer = AudioSystem.getMixer(mixerInfo[0]);

      //Get a TargetDataLine on the selected
      // mixer.
      targetDataLine = (TargetDataLine)
                     mixer.getLine(dataLineInfo);
      //Prepare the line for use.
      targetDataLine.open(audioFormat);
      targetDataLine.start();

      //Create a thread to capture the microphone
      // data and start it running.  It will run
      // until the Stop button is clicked.
      Thread captureThread = new CaptureThread();
      captureThread.start();
    } catch (Exception e) {
      System.out.println(e);
      System.exit(0);
    }//end catch
  }//end captureAudio method

  //This method plays back the audio data that
  // has been saved in the ByteArrayOutputStream
  private void playAudio() {
    try{
      //Get everything set up for playback.
      //Get the previously-saved data into a byte
      // array object.
      byte audioData[] = byteArrayOutputStream.
                                   toByteArray();
      //Get an input stream on the byte array
      // containing the data
      InputStream byteArrayInputStream =
             new ByteArrayInputStream(audioData);
      AudioFormat audioFormat = getAudioFormat();
      audioInputStream = new AudioInputStream(
                    byteArrayInputStream,
                    audioFormat,
                    audioData.length/audioFormat.
                                 getFrameSize());
      DataLine.Info dataLineInfo =
                            new DataLine.Info(
                            SourceDataLine.class,
                            audioFormat);
      sourceDataLine = (SourceDataLine)
               AudioSystem.getLine(dataLineInfo);
      sourceDataLine.open(audioFormat);
      sourceDataLine.start();

      //Create a thread to play back the data and
      // start it  running.  It will run until
      // all the data has been played back.
      Thread playThread = new PlayThread();
      playThread.start();
    } catch (Exception e) {
      System.out.println(e);
      System.exit(0);
    }//end catch
  }//end playAudio

  //This method creates and returns an
  // AudioFormat object for a given set of format
  // parameters.  If these parameters don't work
  // well for you, try some of the other
  // allowable parameter values, which are shown
  // in comments following the declartions.
  private AudioFormat getAudioFormat(){
    float sampleRate = 8000.0F;
    //8000,11025,16000,22050,44100
    int sampleSizeInBits = 16;
    //8,16
    int channels = 1;
    //1,2
    boolean signed = true;
    //true,false
    boolean bigEndian = false;
    //true,false
    return new AudioFormat(
                      sampleRate,
                      sampleSizeInBits,
                      channels,
                      signed,
                      bigEndian);
  }//end getAudioFormat
//=============================================//

//Inner class to capture data from microphone
class CaptureThread extends Thread{
  //An arbitrary-size temporary holding buffer
  byte tempBuffer[] = new byte[10000];
  public void run(){
    byteArrayOutputStream =
                     new ByteArrayOutputStream();
    stopCapture = false;
    try{//Loop until stopCapture is set by
        // another thread that services the Stop
        // button.
      while(!stopCapture){
        //Read data from the internal buffer of
        // the data line.
        int cnt = targetDataLine.read(tempBuffer,
                              0,
                              tempBuffer.length);
        if(cnt > 0){
          //Save data in output stream object.
          byteArrayOutputStream.write(tempBuffer,
                                      0,
                                      cnt);
        }//end if
      }//end while
      byteArrayOutputStream.close();
    }catch (Exception e) {
      System.out.println(e);
      System.exit(0);
    }//end catch
  }//end run
}//end inner class CaptureThread
//===================================//
//Inner class to play back the data
// that was saved.
class PlayThread extends Thread{
  byte tempBuffer[] = new byte[10000];

  public void run(){
    try{
      int cnt;
      //Keep looping until the input read method
      // returns -1 for empty stream.
      while((cnt = audioInputStream.read(
                      tempBuffer, 0,
                      tempBuffer.length)) != -1){
        if(cnt > 0){
          //Write data to the internal buffer of
          // the data line where it will be
          // delivered to the speaker.
          sourceDataLine.write(tempBuffer,0,cnt);
        }//end if
      }//end while
      //Block and wait for internal buffer of the
      // data line to empty.
      sourceDataLine.drain();
      sourceDataLine.close();
    }catch (Exception e) {
      System.out.println(e);
      System.exit(0);
    }//end catch
  }//end run
}//end inner class PlayThread
//=============================================//
class ListMixers {
    PrintWriter out;

     void listAll(final PrintWriter out) {
        this.out = out;
        Mixer.Info[] aInfos = AudioSystem.getMixerInfo();
        for (int i = 0; i < aInfos.length; i++) {
            try {
                Mixer mixer = AudioSystem.getMixer(aInfos[i]);
                out.println(""+i+": "+aInfos[i].getName()+", "
                        +aInfos[i].getVendor()+", "
                        +aInfos[i].getVersion()+", "
                        +aInfos[i].getDescription());

                printLines(mixer, mixer.getSourceLineInfo());
                printLines(mixer, mixer.getTargetLineInfo());
            } catch (Exception e) {
                out.println("Exception: "+e);
            }
            out.println();
        }
        if (aInfos.length == 0) {
            out.println("[No mixers available]");
        }
    }

    void printLines(Mixer mixer, Line.Info[] infos) {
        for (int i = 0; i < infos.length; i++) {
            try {
                if (infos[i] instanceof Port.Info) {
                    Port.Info info = (Port.Info) infos[i];

                    out.println("  Port " + info);
                }
                if (infos[i] instanceof DataLine.Info) {
                    DataLine.Info info = (DataLine.Info) infos[i];

                    out.println("  Line " + info + " (max. " +
                                mixer.getMaxLines(info) + " simultaneously): ");
                    printFormats(info);
                }
                Line line = mixer.getLine(infos[i]);

                if (!(line instanceof Clip)) {
                    try {
                        line.open();
                    }
                    catch (LineUnavailableException e) {
                        out.println("LineUnavailableException when trying to open this line");
                    }
                }
                try {
                    printControls(line.getControls());
                }
                finally {
                    if (!(line instanceof Clip)) {
                        line.close();
                    }
                }
            }
            catch (Exception e) {
                out.println("Exception: " + e);
            }
            out.println();
        }
    }

    void printFormats(DataLine.Info info) {
        AudioFormat[] formats = info.getFormats();
        for (int i = 0; i < formats.length; i++) {
            out.println("  "+i+": "+formats[i]
                    +" ("+formats[i].getChannels()+" channels, "
                    +"frameSize="+formats[i].getFrameSize()+", "
                    +(formats[i].isBigEndian()?"big endian":"little endian")
                    +")");
        }
        if (formats.length == 0) {
            out.println("  [no formats]");
        }
        out.println();
    }

    void printControls(Control[] controls) {
        for (int i = 0; i<controls.length; i++) {
            printControl("    ", "Controls["+i+"]: ", controls[i]);
        }
        if (controls.length == 0) {
            out.println("    [no controls]");
        }
        out.println();
    }

    void printControl(String indent, String id, Control control) {
        if (control instanceof BooleanControl) {
            BooleanControl ctrl = (BooleanControl) control;
            out.println(indent+id+"BooleanControl: "+ctrl);
        } else if (control instanceof CompoundControl) {
            CompoundControl ctrl = (CompoundControl) control;
            Control[] ctrls = ctrl.getMemberControls();
            out.println(indent+id+"CompoundControl: "+control);
            for (int i=0; i<ctrls.length; i++) {
                printControl(indent+"  ", "MemberControls["+i+"]: ", ctrls[i]);
            }
        } else if (control instanceof EnumControl) {
            EnumControl ctrl = (EnumControl) control;
            Object[] values = ctrl.getValues();
            Object value = ctrl.getValue();
            out.println(indent+id+"EnumControl: "+control);
            for (int i=0; i<values.length; i++) {
                if (values[i] instanceof Control) {
                    printControl(indent+"  ", "Values["+i+"]: "+((values[i]==value)?"*":""), (Control) values[i]);
                } else {
                    out.println(indent+"  Values["+i+"]: "+((values[i]==value)?"*":"")+values[i]);
                }
            }
        } else if (control instanceof FloatControl) {
            FloatControl ctrl = (FloatControl) control;
            out.println(indent+id+"FloatControl: "+ctrl);
        } else {
            out.println(indent+id+"Control: "+control);
        }
    }
}
}//end outer class AudioCapture02.java

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

久隐师 2024-11-14 05:38:45

您将使用您创建的 AudioFormat 获取 TargetDataLine。这不能保证有效。您必须首先使用 AudioSystem.isLineSupported(Info info) 方法查询 Mixer 以检查它是否支持您所需的 AudioFormat。

就我个人而言,我觉得这相当麻烦。您需要查询系统上的混音器以确定它们是否支持您想要的音频格式。

下面的函数将获取数据线类支持的格式的向量。 调用

Vector<AudioFormat> formats = getSupportedFormats(TargetDataLine.class);

使用or

Vector<AudioFormat> formats = getSupportedFormats(SourceDataLine.class);

它此代码可能需要一些调试;我必须删除一些特定于应用程序的内容以使其自包含......

public Vector<AudioFormat> getSupportedFormats(Class<?> dataLineClass) {
    /*
     * These define our criteria when searching for formats supported
     * by Mixers on the system.
     */
    float sampleRates[] = { (float) 8000.0, (float) 16000.0, (float) 44100.0 };
    int channels[] = { 1, 2 };
    int bytesPerSample[] = { 2 };

    AudioFormat format;
    DataLine.Info lineInfo;

    SystemAudioProfile profile = new SystemAudioProfile(); // Used for allocating MixerDetails below.
    Vector<AudioFormat> formats = new Vector<AudioFormat>();

    for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
        for (int a = 0; a < sampleRates.length; a++) {
            for (int b = 0; b < channels.length; b++) {
                for (int c = 0; c < bytesPerSample.length; c++) {
                    format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
                            sampleRates[a], 8 * bytesPerSample[c], channels[b], bytesPerSample[c],
                            sampleRates[a], false);
                    lineInfo = new DataLine.Info(dataLineClass, format);
                    if (AudioSystem.isLineSupported(lineInfo)) {
                        /*
                         * TODO: To perform an exhaustive search on supported lines, we should open
                         * TODO: each Mixer and get the supported lines. Do this if this approach
                         * TODO: doesn't give decent results. For the moment, we just work with whatever
                         * TODO: the unopened mixers tell us.
                         */
                        if (AudioSystem.getMixer(mixerInfo).isLineSupported(lineInfo)) {
                            formats.add(format);
                        }
                    }
                }
            }
        }
    }
    return formats;
}

You're getting a TargetDataLine using an AudioFormat you've created. This isn't guaranteed to work. You must first query the Mixer to check if it supports your desired AudioFormat using the AudioSystem.isLineSupported(Info info) method.

Personally, I find this quite cumbersome. You need to query the Mixers on the system to determine if they support the AudioFormat you want.

The function below will get a Vector of supported formats for a data line class. Call it using

Vector<AudioFormat> formats = getSupportedFormats(TargetDataLine.class);

or

Vector<AudioFormat> formats = getSupportedFormats(SourceDataLine.class);

This code might need a bit of debugging; I had to remove some of my app-specific stuff to make it self contained...

public Vector<AudioFormat> getSupportedFormats(Class<?> dataLineClass) {
    /*
     * These define our criteria when searching for formats supported
     * by Mixers on the system.
     */
    float sampleRates[] = { (float) 8000.0, (float) 16000.0, (float) 44100.0 };
    int channels[] = { 1, 2 };
    int bytesPerSample[] = { 2 };

    AudioFormat format;
    DataLine.Info lineInfo;

    SystemAudioProfile profile = new SystemAudioProfile(); // Used for allocating MixerDetails below.
    Vector<AudioFormat> formats = new Vector<AudioFormat>();

    for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
        for (int a = 0; a < sampleRates.length; a++) {
            for (int b = 0; b < channels.length; b++) {
                for (int c = 0; c < bytesPerSample.length; c++) {
                    format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
                            sampleRates[a], 8 * bytesPerSample[c], channels[b], bytesPerSample[c],
                            sampleRates[a], false);
                    lineInfo = new DataLine.Info(dataLineClass, format);
                    if (AudioSystem.isLineSupported(lineInfo)) {
                        /*
                         * TODO: To perform an exhaustive search on supported lines, we should open
                         * TODO: each Mixer and get the supported lines. Do this if this approach
                         * TODO: doesn't give decent results. For the moment, we just work with whatever
                         * TODO: the unopened mixers tell us.
                         */
                        if (AudioSystem.getMixer(mixerInfo).isLineSupported(lineInfo)) {
                            formats.add(format);
                        }
                    }
                }
            }
        }
    }
    return formats;
}
爱给你人给你 2024-11-14 05:38:45

可以直接获取所有支持的Lines及其AudioFormats。我对系统上默认 MixerSourceDataLines 执行了此操作,您可以轻松编辑代码以获得任何类型的 Lines 和 <任何 Mixer 支持的 code>AudioFormats。

Mixer mixer = AudioSystem.getMixer(null); // default mixer
mixer.open();

System.out.printf("Supported SourceDataLines of default mixer (%s):\n\n", mixer.getMixerInfo().getName());
for(Line.Info info : mixer.getSourceLineInfo()) {
    if(SourceDataLine.class.isAssignableFrom(info.getLineClass())) {
        SourceDataLine.Info info2 = (SourceDataLine.Info) info;
        System.out.println(info2);
        System.out.printf("  max buffer size: \t%d\n", info2.getMaxBufferSize());
        System.out.printf("  min buffer size: \t%d\n", info2.getMinBufferSize());
        AudioFormat[] formats = info2.getFormats();
        System.out.println("  Supported Audio formats: ");
        for(AudioFormat format : formats) {
            System.out.println("    "+format);
//          System.out.printf("      encoding:           %s\n", format.getEncoding());
//          System.out.printf("      channels:           %d\n", format.getChannels());
//          System.out.printf(format.getFrameRate()==-1?"":"      frame rate [1/s]:   %s\n", format.getFrameRate());
//          System.out.printf("      frame size [bytes]: %d\n", format.getFrameSize());
//          System.out.printf(format.getSampleRate()==-1?"":"      sample rate [1/s]:  %s\n", format.getSampleRate());
//          System.out.printf("      sample size [bit]:  %d\n", format.getSampleSizeInBits());
//          System.out.printf("      big endian:         %b\n", format.isBigEndian());
//          
//          Map<String,Object> prop = format.properties();
//          if(!prop.isEmpty()) {
//              System.out.println("      Properties: ");
//              for(Map.Entry<String, Object> entry : prop.entrySet()) {
//                  System.out.printf("      %s: \t%s\n", entry.getKey(), entry.getValue());
//              }
//          }
        }
        System.out.println();
    } else {
        System.out.println(info.toString());
    }
    System.out.println();
}

mixer.close();

我得到这样的输出:

interface SourceDataLine supporting 8 audio formats, and buffers of at least 32 bytes
  max buffer size:  -1
  min buffer size:  32
  Supported Audio formats: 
    PCM_UNSIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame, 
    PCM_SIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame, 
    PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, little-endian
    PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, big-endian
    PCM_UNSIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame, 
    PCM_SIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame, 
    PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, little-endian
    PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian


interface Clip supporting 8 audio formats, and buffers of at least 32 bytes

It is possible to obtain all supported Lines and their AudioFormats directly. I did this for the SourceDataLines of the default Mixer on the system, and you can easily edit the code to get any type of Lines and AudioFormats supported by any Mixer.

Mixer mixer = AudioSystem.getMixer(null); // default mixer
mixer.open();

System.out.printf("Supported SourceDataLines of default mixer (%s):\n\n", mixer.getMixerInfo().getName());
for(Line.Info info : mixer.getSourceLineInfo()) {
    if(SourceDataLine.class.isAssignableFrom(info.getLineClass())) {
        SourceDataLine.Info info2 = (SourceDataLine.Info) info;
        System.out.println(info2);
        System.out.printf("  max buffer size: \t%d\n", info2.getMaxBufferSize());
        System.out.printf("  min buffer size: \t%d\n", info2.getMinBufferSize());
        AudioFormat[] formats = info2.getFormats();
        System.out.println("  Supported Audio formats: ");
        for(AudioFormat format : formats) {
            System.out.println("    "+format);
//          System.out.printf("      encoding:           %s\n", format.getEncoding());
//          System.out.printf("      channels:           %d\n", format.getChannels());
//          System.out.printf(format.getFrameRate()==-1?"":"      frame rate [1/s]:   %s\n", format.getFrameRate());
//          System.out.printf("      frame size [bytes]: %d\n", format.getFrameSize());
//          System.out.printf(format.getSampleRate()==-1?"":"      sample rate [1/s]:  %s\n", format.getSampleRate());
//          System.out.printf("      sample size [bit]:  %d\n", format.getSampleSizeInBits());
//          System.out.printf("      big endian:         %b\n", format.isBigEndian());
//          
//          Map<String,Object> prop = format.properties();
//          if(!prop.isEmpty()) {
//              System.out.println("      Properties: ");
//              for(Map.Entry<String, Object> entry : prop.entrySet()) {
//                  System.out.printf("      %s: \t%s\n", entry.getKey(), entry.getValue());
//              }
//          }
        }
        System.out.println();
    } else {
        System.out.println(info.toString());
    }
    System.out.println();
}

mixer.close();

I get an output like this:

interface SourceDataLine supporting 8 audio formats, and buffers of at least 32 bytes
  max buffer size:  -1
  min buffer size:  32
  Supported Audio formats: 
    PCM_UNSIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame, 
    PCM_SIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame, 
    PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, little-endian
    PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, big-endian
    PCM_UNSIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame, 
    PCM_SIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame, 
    PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, little-endian
    PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian


interface Clip supporting 8 audio formats, and buffers of at least 32 bytes
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文