有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

javasound如何使用Java从just linein端口录制声音

我需要从线路输入端口捕捉声音,而不是麦克风

虽然我通过麦克风完成了录音,但我无法从线路输入端口或特定端口捕获声音。我如何处理这个问题


共 (4) 个答案

  1. # 1 楼答案

    import javax.sound.sampled.*;
    
    /**
     *
     * @author d07114915
     * 
     * Class to get a mixer with a specified recordable audio format from a specified port
     * For instance get a 44.1kHz 16bit record line for a "line in"  input
     */
    public class MixerMatcher {
    private static final String THE_INPUT_TYPE_I_WANT = "MICROPHONE";
    private static final String THE_NAME_OF_THE_MIXER_I_WANT_TO_GET_THE_INPUT_FROM = "Realtek HD Audio Input";
    private static final AudioFormat af = new AudioFormat(
            AudioFormat.Encoding.PCM_SIGNED,
            44100.0F,
            16,
            2,
            2 * 2,
            44100.0F,
            false);
    private static final DataLine.Info targetDataLineInfo = new DataLine.Info(TargetDataLine.class, af);
    private static final Port.Info myInputType = new Port.Info((Port.class), THE_INPUT_TYPE_I_WANT, true);
    private static TargetDataLine targetDataLine = null;
    
    public static void main(String[] args) {
        Mixer portMixer = null;
        Mixer targetMixer = null;
        try {
            for (Mixer.Info mi : AudioSystem.getMixerInfo()) {
                //               System.out.println("-" +mi.getName() + "-");
                if (mi.getName().equals(THE_NAME_OF_THE_MIXER_I_WANT_TO_GET_THE_INPUT_FROM)) {
                    System.out.println("Trying to get portMixer for :" + mi.getName());
                    portMixer = getPortMixerInfoFor(mi);
                    if (portMixer != null) {
                        System.out.println(portMixer.getMixerInfo().toString());
                        targetMixer = AudioSystem.getMixer(mi);
                        break;
                    }
                }
            }
            if (targetMixer != null) {
                targetMixer.open();
    
                targetDataLine = (TargetDataLine) targetMixer.getLine(targetDataLineInfo);
                System.out.println("Got TargetDataLine from :" + targetMixer.getMixerInfo().getName());
    
                portMixer.open();
    
                Port port = (Port) portMixer.getLine(myInputType);
                port.open();
    
                Control[] controls = port.getControls();
                System.out.println((controls.length > 0 ? "Controls for the "+ THE_INPUT_TYPE_I_WANT + " port:" : "The port has no controls."));
                for (Control c : controls) {
                    System.out.println(c.toString());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    
    }
    
    //return the portMixer that corresponds to TargetMixer 
    private static Mixer getPortMixerInfoFor(Mixer.Info mixerInfo) {
        //Check this out for interest
        //http://www.java-forum.org/spiele-multimedia-programmierung/94699-java-sound-api-zuordnung-port-mixer-input-mixer.html
        try {
            // get the requested mixer
            Mixer targetMixer = AudioSystem.getMixer(mixerInfo);
            targetMixer.open();
            //Check if it supports the desired format
            if (targetMixer.isLineSupported(targetDataLineInfo)) {
                System.out.println(mixerInfo.getName() + " supports recording @ " + af);
                //now go back and start again trying to match a mixer to a port
                //the only way I figured how is by matching name, because 
                //the port mixer name is the same as the actual mixer with "Port " in front of it
                // there MUST be a better way
                for (Mixer.Info portMixerInfo : AudioSystem.getMixerInfo()) {
                    String port_string = "Port ";
                    if ((port_string + mixerInfo.getName()).equals(portMixerInfo.getName())) {
                        System.out.println("Matched Port to Mixer:" + mixerInfo.getName());
                        Mixer portMixer = AudioSystem.getMixer(portMixerInfo);
                        portMixer.open();
                        //now check the mixer has the right input type eg LINE_IN
                        boolean lineTypeSupported = portMixer.isLineSupported((Line.Info) myInputType);
                        System.out.println(portMixerInfo.getName() +" does " + (lineTypeSupported? "" : "NOT") + " support " + myInputType.getName());
                        if (lineTypeSupported) {
                            portMixer.close();
                            targetMixer.close();
                            return portMixer;
                        }
                        portMixer.close();
                    }
                }
            }
            targetMixer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    }
    

    运行此命令,我得到:
    Trying to get portMixer for :Realtek HD Audio Input
    Realtek HD Audio Input supports recording @ PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian
    Matched Port to Mixer:Realtek HD Audio Input
    Port Realtek HD Audio Input does support MICROPHONE
    Port Realtek HD Audio Input, version 5.10
    Got TargetDataLine from :Realtek HD Audio Input
    Controls for the MICROPHONE port:
    Mic Volume Control containing Select, Microphone Boost, Volume, and Balance Controls.

    将混音器和输入类型首选项分别更改为“USB Sound Device”和“LINE_IN”,我得到以下结果:(注意,混音器名称中“Device”一词后面有8个空格,但它们不会显示在此网页上!)

    Trying to get portMixer for :USB Sound Device
    Trying to get portMixer for :USB Sound Device
    USB Sound Device supports recording @ PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian
    Matched Port to Mixer:USB Sound Device
    Port USB Sound Device does support LINE_IN
    Port USB Sound Device , version 0.16
    Got TargetDataLine from :USB Sound Device
    Controls for the LINE_IN port:
    Line Control containing Select, Mute, Volume, and Balance Controls.

    这里USB声卡显示一个输入端口和一个输出端口,因此其中一个不支持LINE_in,这可能是因为它是一个输出,因此可能允许录制“立体声混音”或其他输出类型

    希望这能起作用,帮助别人。。。。由于Java文档相当模糊。。。 在Windows上测试过,但我认为Linux不会识别端口名,比如LINE_IN,所以您需要检查操作系统端口是什么,可能还有一些其他的事情,比如需要一个子字符串作为混音器名称等等。。。 在我的Linux上,麦克风被称为“捕获”

    查看jsresources.org FAQ了解更多信息

    任何错误的改进等让我知道

    d07114915

  2. # 2 楼答案

    熟悉^{}类。另外,从它自己的Javadoc:

    The target data line can be obtained from a mixer by invoking the getLine method of Mixer with an appropriate DataLine.Info object.

    具体地说,我还要检查^{},并检查返回的输出,以选择与您正在寻找的端口中的行相匹配的行

  3. # 3 楼答案

    我也没想到,但你真的需要

    mixer.getSourceLineInfo()因为这是来自混音器的视图。。。真让人困惑

    targetDataLine是一条可记录的输入线,但要查看这些线可能来自何处,您需要查找混音器的端口(麦克风、线路输入、SPDIF),因此需要调用

    混合器。getSourceLineInfo()

    这只提供了端口。例如,它们可用于控制输入中的行_的录制音量,但不能直接从端口对象录制

    你需要使用 数据线。Info targetDataLineInfo=新数据线。信息(TargetDataLine.class,音频格式)

    其中AudioFormat是一些用户定义的格式,如

    audioFormat = new AudioFormat(
                    Encoding.PCM_SIGNED,
                    sampleRate,
                    bitRate,
                    monoOrStereo,
                    monoOrStereo * 2, // 
                    sampleRate,
                    false); 
    

    然后从首选混音器中获取该行:

    Mixer.getLine(audioFormat);
    

    这会给你一条可记录的线,就像你可能已经做过的那样

    我不知道的是,像你一样,如何选择一个端口,比如LINE_IN,并创建一个匹配的TargetDataLine,Port对象可以控制它,我已经搜索了又搜索

    ()

    任何有工作经验的人

  4. # 4 楼答案

    试试这个。如果它工作,让我知道,因为我不能完全自己测试我的笔记本电脑。 然后,您可以构造自己的函数来获取PortMixerActualMixer 以及具有指定输入类型和/或所需混频器的TargateDataLine

    private void testGettingInput() {
        //Check this out for interest
        //http://www.java-forum.org/spiele-multimedia-programmierung/94699-java-sound-api-zuordnung-port-mixer-input-mixer.html
        final String newLine = System.getProperty("line.separator");
        final String inputTypeString = "LINE_IN"; // or COMPACT_DISC or MICROPHONE etc ...
        final Port.Info myInputType = new Port.Info((Port.class), inputTypeString, true);
        final AudioFormat af = new AudioFormat(
                Encoding.PCM_SIGNED,
                44100.0F,
                16,
                2,
                2 * 2,
                44100.0F,
                false);
        final DataLine.Info targetDataLineInfo = new DataLine.Info(TargetDataLine.class, af);
        TargetDataLine targetDataLine;
    
        //Go through the System audio mixers
        for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
            try {
                Mixer targetMixer = AudioSystem.getMixer(mixerInfo);
                targetMixer.open();
                //Check if it supports the desired format
                if (targetMixer.isLineSupported(targetDataLineInfo)) {
                    System.out.println(mixerInfo.getName() + " supports recording @" + af);
                    //now go back and start again trying to match a mixer to a port
                    //the only way I figured how is by matching name, because 
                    //the port mixer name is the same as the actual mixer with "Port " in front of it
                    // there MUST be a better way
                    for (Mixer.Info mifo : AudioSystem.getMixerInfo()) {
                        String port_string = "Port ";
                        if ((port_string + mixerInfo.getName()).equals(mifo.getName())) {
                            System.out.println("Matched Port to Mixer:" + mixerInfo.getName());
                            Mixer portMixer = AudioSystem.getMixer(mifo);
                            portMixer.open();
                            portMixer.isLineSupported((Line.Info) myInputType);
                            //now check the mixer has the right input type eg LINE_IN
                            if (portMixer.isLineSupported((Line.Info) myInputType)) {
                                //OK we have a supported Port Type for the Mixer
                                //This has all matched (hopefully)
                                //now just get the record line
                                //There should be at least 1 line, usually 32 and possible unlimited
                                // which would be "AudioSystem.Unspecified" if we ask the mixer 
                                //but I haven't checked any of this
                                targetDataLine = (TargetDataLine) targetMixer.getLine(targetDataLineInfo);
                                System.out.println("Got TargetDataLine from :" + targetMixer.getMixerInfo().getName());
                                return;
                            }
                        }
                    }
                    System.out.println(newLine);
                }
                targetMixer.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }