2017-08-22 11 views
10

संपादित करने के लिए जावा में आउटपुट लाइन का चयन करें: अब मैं जैक (जैक ऑडियो कनेक्शन किट) का उपयोग कर रहा हूं। नीचे जवाब देखें।आठ चैनल साउंड कार्ड

मेरे पास 8 राउटबेरी पाई पर 8 साउंड चैनल (चार स्टीरियो चैनल), एक ऑक्टोसाउंड कार्ड के साथ एक साउंडकार्ड है। मैं जो करना चाहता हूं वह ध्वनि को रूट करने के लिए चैनलों में से एक का चयन करना है। इस कोड के साथ मैं साउंड कार्ड की जानकारी को मुद्रित:

mixers = AudioSystem.getMixerInfo(); 
    for (Mixer.Info mixerInfo : mixers) { 
     logger.debug("\n"); 
     logger.debug("Found Mixer: " + mixerInfo); 

     Mixer m = AudioSystem.getMixer(mixerInfo); 

     Line.Info[] sourceLines = m.getSourceLineInfo(); 
     for (Line.Info li : sourceLines) { 
      logger.debug("Found source line: " + li + " " + li.getClass()); 

      if (li instanceof Port.Info) { 
       Port.Info portInfo = (Port.Info) li; 
       logger.debug("port found " + portInfo.getName() + " is source " + portInfo.isSource()); 
       sourceDataLines.add(portInfo); 
      } 

     } 

     Line.Info[] targetLines = m.getTargetLineInfo(); 

     for (Line.Info li : targetLines) { 
      logger.debug("Found target line: " + li + " " + li.getClass()); 
      outputLines.add(li); 

      if (li instanceof Port.Info) { 
       Port.Info portInfo = (Port.Info) li; 
       logger.debug("port found " + portInfo.getName() + " is source " + portInfo.isSource()); 
       outputPorts.add(portInfo); 
      } 
     } 
    } 


private void lineClose(int soundPort) throws LineUnavailableException { 
    Port.Info lineInfo = outputPorts.get(soundPort); 
    Line line = (Port) AudioSystem.getLine(lineInfo); 
    line.close(); 
} 

private void lineOpen(int l) throws LineUnavailableException { 

    for (int i = 0; i < outputPorts.size(); i++) { 
     Port.Info lineInfo = outputPorts.get(i); 
     Line line = (Port) AudioSystem.getLine(lineInfo); 
     if (l == i) { 
      line.open(); 
     } else { 
      line.close(); 
     } 
    } 
} 

यह वह जगह है उत्पादन मैं:

Found Mixer: audioinjectoroc [default], version 4.9.41-v7+ 
Found source line: interface SourceDataLine supporting 84 audio formats, and buffers of at least 32 bytes class com.sun.media.sound.DirectAudioDevice$DirectDLI 
Found source line: interface Clip supporting 84 audio formats, and buffers of at least 32 bytes class com.sun.media.sound.DirectAudioDevice$DirectDLI 
Found target line: interface TargetDataLine supporting 84 audio formats, and buffers of at least 32 bytes class com.sun.media.sound.DirectAudioDevice$DirectDLI 

Found Mixer: audioinjectoroc [plughw:0,0], version 4.9.41-v7+ 
Found source line: interface SourceDataLine supporting 96 audio formats, and buffers of at least 32 bytes class com.sun.media.sound.DirectAudioDevice$DirectDLI 
Found source line: interface Clip supporting 96 audio formats, and buffers of at least 32 bytes class com.sun.media.sound.DirectAudioDevice$DirectDLI 
Found target line: interface TargetDataLine supporting 96 audio formats, and buffers of at least 32 bytes class com.sun.media.sound.DirectAudioDevice$DirectDLI 

Found Mixer: Port audioinjectoroc [hw:0], version 4.9.41-v7+ 
Found source line: ADC1 source port class com.sun.media.sound.PortMixer$PortInfo 
port found ADC1 is source true 
Found source line: ADC2 source port class com.sun.media.sound.PortMixer$PortInfo 
port found ADC2 is source true 
Found source line: ADC3 source port class com.sun.media.sound.PortMixer$PortInfo 
port found ADC3 is source true 
Found target line: DAC1 target port class com.sun.media.sound.PortMixer$PortInfo 
port found DAC1 is source false 
Found target line: DAC2 target port class com.sun.media.sound.PortMixer$PortInfo 
port found DAC2 is source false 
Found target line: DAC3 target port class com.sun.media.sound.PortMixer$PortInfo 
port found DAC3 is source false 
Found target line: DAC4 target port class com.sun.media.sound.PortMixer$PortInfo 
port found DAC4 is source false 

अब इस कोड मैं एक wav फ़ाइल से उत्पादन ध्वनि करने के लिए उपयोग करते हैं:

String path = soundDirectory + soundUrl; 
    InputStream is = new FileInputStream(path); 
    BufferedInputStream bis = new BufferedInputStream(is); 
    AudioInputStream inputStream = AudioSystem.getAudioInputStream(bis); 
    AudioFormat format = inputStream.getFormat(); 

    Mixer.Info mi = mixers[0]; 

    SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getSourceDataLine(format,mi); 
    sourceDataLine.open(format); 
    sourceDataLine.start(); 
    byte[] buf = new byte[1024]; 
    int bytesRead; 
    while ((bytesRead = inputStream.read(buf)) != -1){ 
     sourceDataLine.write(buf, 0, bytesRead); 
    } 
    inputStream.close(); 

    sourceDataLine.drain(); 
    sourceDataLine.stop(); 
    sourceDataLine.close(); 

    lineClose(soundPort); 

मैंने कई चीजों की कोशिश की है, लेकिन सभी मामलों में, आवाज सभी ouputs से बाहर आती है।

+1

तो आपने अभी तक क्या प्रयास किया है? – andy

+1

मेरे द्वारा पोस्ट किए गए कोड के अलावा, और इसमें कई बदलाव, मैं वर्तमान में जैक के साथ जेना जैक की कोशिश कर रहा हूं। – Christine

उत्तर

3

मुझे स्वयं समाधान मिला। मैं अब जैक (जैक ऑडियो कनेक्शन किट का उपयोग करें, here देखते हैं। यह जैक एक रास्पबेरी Pi पर चलाने के लिए एक परेशानी का एक सा है। वहाँ अच्छा जानकारी here है।

मैं साथ JnaJack का उपयोग जावा और जैक के बीच एक अंतरफलक प्रदान करता है।

आप बॉक्स के बाहर रास्पियन पर जैक नहीं चला सकते हैं। डेबियन व्हीजी के पास एक पैच था, लेकिन रास्पियन जेसी के पास ऐसा प्रतीत नहीं होता है। इसलिए आपको जैकड 2 का संस्करण बनाना होगा जो डीबीस का उपयोग नहीं करता है। Here यह समझाया गया है कि डीबीस के बिना जैकड 2 कैसे बनाया जाए। एक स्नैग है: आपको बस दो लाइनों को हटा देना है जो डीबीस को संदर्भित करते हैं। बाकी सब कुछ जिन्हें वे आपको पैच में बताते हैं, अब डिफ़ॉल्ट रूप से रास्पियन में पैच किए गए हैं, या ऐसा लगता है एसएस/नियमों को बदलने

waf-configure-options += $(if $(filter linux,$(DEB_HOST_ARCH_OS)),--alsa --dbus) 
became 
waf-configure-options += $(if $(filter linux,$(DEB_HOST_ARCH_OS)),--alsa) 

dh_install -pjackd2 debian/tmp/usr/share/dbus-1/* 
became 
#dh_install -pjackd2 debian/tmp/usr/share/dbus-1/* 

मैं SimpleAudioClient उदाहरण JnaJack स्रोत में पाया संशोधित आप स्रोत डाउनलोड करने के बाद डेबियन में, :

public class SimpleAudioClient { 

    private boolean autoconnect = true; 
    private JackClient client; 
    private Processor processor; 
    private Callback callback; 
    private ShutDownHook shutDownHook; 
    private JackPort[] inputPorts; 
    private JackPort[] outputPorts; 
    private FloatBuffer[] inputBuffers; 
    private FloatBuffer[] outputBuffers; 
    private float samplerate; 
    private int buffersize; 
    private volatile boolean active; 

    private Logger logger = Logger.getLogger(getClass().getSimpleName()); 
    private int channelNumber = 0; 

    public SimpleAudioClient() throws JackException { 

     Jack jack = Jack.getInstance(); 
     logger.debug("Jack instance " + jack.toString()); 
     EnumSet<JackOptions> options = EnumSet.of(JackOptions.JackNoStartServer); 
     EnumSet<JackStatus> status = EnumSet.noneOf(JackStatus.class); 
     try { 
      client = jack.openClient("jna_jack", options, status); 
     } catch (JackException ex) { 
      System.out.println("ERROR : Status : " + status); 
      throw ex; 
     } 

     String[] inputs = new String[0]; 
     inputPorts = new JackPort[inputs.length]; 
     EnumSet<JackPortFlags> flags = EnumSet.of(JackPortFlags.JackPortIsInput); 
     for (int i = 0; i < inputs.length; i++) { 
      //inputPorts[i] = client.registerPort(inputs[i], JackPortType.AUDIO, flags); 
     } 

     String[] outputs = new String[]{"playback_1", "playback_2", "playback_3", "playback_4", "playback_5", "playback_6", "playback_7", "playback_8"}; 
     outputPorts = new JackPort[outputs.length]; 
     flags = EnumSet.of(JackPortFlags.JackPortIsOutput); 
     for (int i = 0; i < outputs.length; i++) { 
      outputPorts[i] = client.registerPort(outputs[i], JackPortType.AUDIO, flags); 
     } 

     processor = new SineAudioSource(); 

     this.inputBuffers = new FloatBuffer[inputPorts.length]; 
     this.outputBuffers = new FloatBuffer[outputPorts.length]; 
     this.callback = new Callback(); 
     this.shutDownHook = new ShutDownHook(); 
     client.onShutdown(shutDownHook); 

     for (JackPort port : inputPorts) { 
      logger.debug("input port " + port.getType() + " " + port.getName()); 
     } 

     for (JackPort port : outputPorts) { 
      logger.debug("output port " + port.getType() + " " + port.getName()); 
     } 
    } 

    public void activate(int channelNr) throws JackException { 

     this.channelNumber = channelNr; 

     try { 
      samplerate = client.getSampleRate(); 
      System.out.println("Sample rate = " + samplerate); 
      buffersize = client.getBufferSize(); 
      System.out.println("Buffersize = " + buffersize); 
      processor.setup(samplerate, buffersize); 
      active = true; 
      client.setProcessCallback(callback); 
      client.activate(); 
      if (autoconnect) { 
       doAutoconnect(); 
      } 
     } catch (Exception ex) { 
      active = false; 
      throw new JackException("Could not activate Jack client"); 
     } 
    } 

    private void doAutoconnect() throws JackException { 
     Jack jack = Jack.getInstance(); 
     String[] physical = jack.getPorts(client, null, JackPortType.AUDIO, 
       EnumSet.of(JackPortFlags.JackPortIsInput, JackPortFlags.JackPortIsPhysical)); 
     int count = Math.min(outputPorts.length, physical.length); 
     for (int i = 0; i < count; i++) { 
      logger.debug("output port " + outputPorts[i].getName()); 
      jack.connect(client, outputPorts[i].getName(), physical[i]); 
     } 
     physical = jack.getPorts(client, null, JackPortType.AUDIO, 
       EnumSet.of(JackPortFlags.JackPortIsOutput, JackPortFlags.JackPortIsPhysical)); 
     count = Math.min(inputPorts.length, physical.length); 
     for (int i = 0; i < count; i++) { 
      logger.debug("input port " + inputPorts[i].getName()); 
      //jack.connect(client, physical[i], inputPorts[i].getName()); 
     } 
    } 

    public void shutdown() { 
     active = false; 
     client.deactivate(); 
     client.close(); 
    } 

    private void processBuffers(int nframes) { 
     for (int i = 0; i < inputPorts.length; i++) { 
      inputBuffers[i] = inputPorts[i].getFloatBuffer(); 
     } 
     for (int i = 0; i < outputPorts.length; i++) { 
      outputBuffers[i] = outputPorts[i].getFloatBuffer(); 
     } 
     processor.process(channelNumber, inputBuffers, outputBuffers); 
    } 

    private class Callback implements JackProcessCallback { 

     public boolean process(JackClient client,final int nframes) { 

      if (!active) { 
       return false; 
      } else { 
       try { 
        processBuffers(nframes); 
        return true; 
       } catch (Exception ex) { 
        System.out.println("ERROR : " + ex); 
        active = false; 
        return false; 
       } 

      } 
     } 
    } 

    private class ShutDownHook implements JackShutdownCallback { 

     public void clientShutdown(JackClient client) { 
      active = false; 
      processor.shutdown(); 
     } 
    } 

    public static interface Processor { 

     public void setup(float samplerate, int buffersize); 

     public void process(int channelNumber, FloatBuffer[] inputs, FloatBuffer[] outputs); 

     public void shutdown(); 
    } 

    /** 
    * Create a SimpleAudioClient. 
    * 
    * @return client 
    * @throws org.jaudiolibs.jnajack.JackException 
    */ 
    public static SimpleAudioClient create(
    ) throws JackException { 

     return new SimpleAudioClient(); 
    } 
} 

मैं से SineAudioClient संशोधित ई लाइनों आप को बदलने के लिए की जरूरत है इसमें नमूना कोड:

public class SineAudioSource implements SimpleAudioClient.Processor { 

    private final static int TABLE_SIZE = 200; 
    private int left_phase = 0; 
    private int right_phase = 0; 
    private float[] data; 

    public void setup(float samplerate, int buffersize) { 
     data = new float[TABLE_SIZE]; 
     for (int i = 0; i < TABLE_SIZE; i++) { 
      data[i] = (float) (0.2 * Math.sin(((double) i/(double) TABLE_SIZE) * Math.PI * 2.0)); 
     } 
    } 

    public void process(int channelNumber, FloatBuffer[] inputs, FloatBuffer[] outputs) { 

     FloatBuffer left = outputs[channelNumber]; 
     int size = left.capacity(); 
     for (int i = 0; i < size; i++) { 
      left.put(i, data[left_phase]); 
      left_phase += 2; 
      right_phase += 3; 
      if (left_phase >= TABLE_SIZE) { 
       left_phase -= TABLE_SIZE; 
      } 
     } 
    } 

    public void shutdown() { 
     System.out.println("Sine Audio Source shutdown"); 
    } 
} 

तो यह ध्वनि कार्ड के आठ चैनलों में से प्रत्येक में दो सेकंड के लिए साइन लहर चलाता है। मैंने इनपुट चैनलों (अभी तक) की कोशिश नहीं की है, मैंने पढ़ा है कि जैक को रास्पियन पर काम करना मुश्किल है जब इनपुट और आउटपुट दोनों सक्रिय होते हैं।

मैं जैक शुरू करने से पहले मैं अपने अनुप्रयोग चलाने, शुरू आदेश

/usr/bin/jackd -dalsa -dhw:audioinjectoroc -r48000 -p1024 -n2 -P & 

लॉग होता है जब आप शुरू जैक दिखाना चाहिए

creating alsa driver ... hw:audioinjectoroc|-|1024|2|48000|0|0|nomon|swmeter|-|32bit 

जहां "audioinjector" साउंड कार्ड का नाम है । यदि यह

...hw:audioinjectoroc|hw:audioinjectoroc|1024 ... 

दिखाता है तो आपको उससे कनेक्ट करने में समस्याएं होंगी।

आप जैक सेटिंग्स को QJackCtl के साथ देख सकते हैं, जिसे आप अपने रास्पबेरी पीआई पर चला सकते हैं और किसी अन्य कंप्यूटर से एक्स सर्वर के साथ एक्सेस कर सकते हैं। मैं पीआई पर एक्स विंडोज चलाने के लिए प्रबंधन नहीं किया था।

आप जैक के माध्यम से wav फ़ाइलें खेलने के लिए चाहते हैं, this कैसे एक wav फ़ाइल को पढ़ने और जैक करने के लिए इसे खिलाने के लिए का एक अच्छा उदाहरण है।

संपादित करें: उदाहरण एक अच्छा प्रारंभिक बिंदु है, लेकिन आपको कुछ बदलाव करने की आवश्यकता है। उन सभी बंदरगाहों को खोलना सबसे अच्छा है जिन्हें आप उपयोग करने की योजना बना रहे हैं, client.activate() पर कॉल करें, और जैककॉलबैक में अपने ऑडियो फ़ाइल के चैनलों को ध्वनि कार्ड में उपयुक्त चैनलों पर रूट करें। जैक में क्या हो रहा है यह देखने के लिए आप qjackctl का उपयोग कर सकते हैं।

संबंधित मुद्दे