Sorties de mixage multiples en Java


J'essaie de faire en sorte que Java joue un son stéréo différent dans deux sorties (prises audio avant et arrière).

Ma carte son est configurée pour traiter les deux sorties indépendamment, et dans le mélangeur Windows, je peux les faire émettre un son de test séparément, donc ce n'est pas un problème de carte.

J'ai essayé l'approche sur Changer le mélangeur pour produire du son en java en utilisant différentes sorties en obtenant deux clips avec des mélangeurs différents, avec AudioSystem.getClip(AudioSystem.getMixerInfo()[i]);. Cependant, cette ligne de code ne fonctionne qu'avec la Java Sound Audio Engine (AudioSystem.getMixerInfo()[0]), qui sort dans la sortie audio par défaut de Windows. Tout le reste jette

java.lang.IllegalArgumentException: Line unsupported: interface Clip supporting format PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian

L'exemple de code suivant génère un bruit blanc long de 5 secondes et le lit pendant 1 seconde, puis se termine. Il imprime les informations du mélangeur comme on le voit sur comment puis-je obtenir la disposition des canaux du mélangeur en java . Il sort actuellement sur le mélangeur" Java Sound Audio Engine", et essayer de passer à n'importe quel autre mélangeur lève l'exception ci-dessus.

import java.io.ByteArrayInputStream;
import java.security.SecureRandom;
import java.util.Random;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;

public class Main {
    static int SAMPLE_RATE = 44100;
    static AudioFormat format = new AudioFormat(
            AudioFormat.Encoding.PCM_SIGNED, // Encoding
            SAMPLE_RATE,    // sample rate
            8,              // sample size in bits
            2,              // channels
            4,              // frame size
            SAMPLE_RATE,    // frame rate
            true);          // is big endian

    static int DURATION = 5;
    Thread soundThread;

    // Noise audio
    static AudioInputStream inputStream = new AudioInputStream(new ByteArrayInputStream(generateNoise(DURATION*2*SAMPLE_RATE)), format, DURATION*SAMPLE_RATE);

    public static void main(String[] args) {
        try {

            // https://stackoverflow.com/questions/12863081/how-do-i-get-mixer-channels-layout-in-java
            Mixer.Info[] mi = AudioSystem.getMixerInfo();
            for (Mixer.Info info : mi) {
                System.out.println("info: " + info);
                Mixer m = AudioSystem.getMixer(info);
                System.out.println("mixer " + m);
                Line.Info[] sl = m.getSourceLineInfo();
                for (Line.Info info2 : sl) {
                    System.out.println("    info: " + info2);
                    Line line = AudioSystem.getLine(info2);
                    if (line instanceof SourceDataLine) {
                        SourceDataLine source = (SourceDataLine) line;

                        DataLine.Info i = (DataLine.Info) source.getLineInfo();
                        for (AudioFormat format : i.getFormats()) {
                            System.out.println("    format: " + format);
                        }
                    }
                }
                System.out.println("");
            }


            // Code only works for AudioSystem.getMixerInfo()[0] 
            final Clip clip = AudioSystem.getClip(AudioSystem.getMixerInfo()[0]);
            clip.open(inputStream);

            Thread soundThread = new Thread(new Runnable() {                
                @Override
                public void run() {
                    try {
                        clip.loop(Clip.LOOP_CONTINUOUSLY);
                        Thread.sleep(1000);
                        clip.close();
                        System.exit(0);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            soundThread.start();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static byte[] generateNoise(int size) {
        byte[] out = new byte[size];
        Random r = new SecureRandom();
        r.nextBytes(out);
        return out;
    }
}

Voici le mélangeur information. Ce code a fonctionné avec les deux prises de sortie connectées et Windows reconnaît comme deux périphériques de sortie différents (haut-parleurs et écouteurs). Il semble que seul le moteur audio de Java puisse lire des sons.

info: Java Sound Audio Engine, version 1.0
mixer com.sun.media.sound.HeadspaceMixer@22c84d9
    info: interface SourceDataLine supporting 8 audio formats
    format: PCM_SIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame, 
    format: PCM_UNSIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame, 
    format: PCM_SIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame, 
    format: PCM_UNSIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame, 
    format: PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, big-endian
    format: PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, little-endian
    format: PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian
    format: PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, little-endian
    info: interface Clip supporting 8 audio formats, and buffers of 0 to 4194304 bytes

info: Microsoft ?T?E???h, version Unknown Version
mixer com.sun.media.sound.SimpleInputDevice@7e0df503

info: Stereo Mixer (Realtek High Defi, version Unknown Version
mixer com.sun.media.sound.SimpleInputDevice@4650d89c

info: Port Realtek HD Audio 2nd output (Re, version 6.1
mixer com.sun.media.sound.PortMixer@65bd0dd4

info: Port Stereo Mixer (Realtek High Defi, version 6.1
mixer com.sun.media.sound.PortMixer@78b5f53a
    info: ?}?X? source port

info: Port Speakers (Realtek High Definiti, version 6.1
mixer com.sun.media.sound.PortMixer@b37c60d

J'utilise Java 6 à cause d'autres limitations. De plus, certains noms sont cassés probablement parce que je suis dans un environnement japonais et Eclipse ne récupérera pas les noms dans le codage correct (j'ai essayé de tout changer en UTF-8 et Shift_JIS mais rien n'a changé, mais je suppose que ce n'est pas le cas liées à ce problème).

En d'autres termes, Il semble que impossible de sortir dans les clips de différents mélangeurs car Java ne peut sortir que vers "Java Sound Audio Engine" qui va au périphérique audio par défaut de Windows. Y a - t-il un moyen de faire fonctionner les autres mélangeurs? Est-il une alternative à l'utilisation de plusieurs sorties audio?

Update : Il semble que ce problème a déjà été résolu mais je n'arrive toujours pas à le faire fonctionner. J'ai désactivé le périphérique d'enregistrement "Stereo Mix" et exécuté le exemple de code donné dans ce lien, et a obtenu cette sortie:

MIXER 0: Java Sound Audio Engine, version 1.0
OUTPUT LINE (SourceDataLine) 0: interface SourceDataLine supporting 8 audio formats
OUTPUT LINE (SourceDataLine) 1: interface Clip supporting 8 audio formats, and buffers of 0 to 4194304 bytes

MIXER 1: Port Realtek HD Audio 2nd output (Re, version 6.1
INPUT LINE (TargetDataLine) 0: HEADPHONE target port

MIXER 2: Port Speakers (Realtek High Definiti, version 6.1
INPUT LINE (TargetDataLine) 0: SPEAKER target port

Il semble donc que seul Java Sound Audio Engine puisse produire du son car les mélangeurs pour les prises audio avant et arrière sont traités comme des lignes d'entrée. Lecture audio via les sorties Clip ou SourceDataLine dans le périphérique de lecture par défaut de Windows.

De plus, il semble qu'ils aient résolu le problème en utilisant DirectAudio mais je n'ai toujours pas compris comment les utiliser.

Author: Community, 2016-01-22

1 answers

Lors des tests sur différents ordinateurs, j'ai résolu ce problème en passant à Java 1.6.0_17 (ce qui était toujours correct avec mes limitations d'environnement pour appeler Java à partir de Matlab) afin que les pilotes DirectAudio soient répertoriés (même s'il semble que cela devrait fonctionner à partir de Java 1.5). Chaque périphérique audio DirectAudio donne une SourceDataLine et un clip pour chaque périphérique.

 0
Author: walljam7, 2016-01-28 01:34:19