Несколько выходов микшера в Java

Я пытаюсь заставить Java воспроизводить разные стереозвуки на двух выходах (передние и задние аудиоразъемы).

Моя звуковая карта настроена так, чтобы обрабатывать оба выхода независимо, и в микшере Windows я могу заставить их издавать тестовый звук отдельно, так что это не проблема карты.

Я попробовал подход Change Mixer для вывода звука в java используя разные выходы, получив два клипа с разными микшерами, с AudioSystem.getClip(AudioSystem.getMixerInfo()[i]);. Однако эта строка кода работает только с Java Sound Audio Engine (AudioSystem.getMixerInfo()[0]), который выводит звук по умолчанию в Windows. Что-нибудь еще бросает

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

В следующем примере кода создается 5-секундный белый шум, который воспроизводится в течение 1 секунды, а затем завершается. Он выводит информацию о микшере, как показано в разделе , как мне получить макет каналов микшера. в Java. В настоящее время он выводится на микшер «Java Sound Audio Engine», и попытка перейти на любой другой микшер вызывает указанное выше исключение.

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;
    }
}

Вот информация о микшере. Этот код работал с обоими подключенными выходными разъемами, и Windows распознает два разных устройства вывода (динамики и наушники). Похоже, что только звуковой движок Java может воспроизводить звуки.

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

Я использую Java 6 из-за других ограничений. Кроме того, некоторые имена не работают, вероятно, потому, что я нахожусь в японской среде, и Eclipse не будет получать имена в правильной кодировке (я пытался изменить все на UTF-8 и Shift_JIS, но ничего не изменилось, но я думаю, что это не связано к этой проблеме).

Другими словами, похоже, что он не может выводить клипы из разных микшеров, потому что Java может выводить только на «Java Sound Audio Engine», который идет на аудиоустройство Windows по умолчанию. Есть ли способ заставить другие микшеры работать? Есть ли альтернатива использованию нескольких аудиовыходов?

Обновление: кажется, что эта проблема уже решена но я все еще не могу заставить его работать. Я отключил записывающее устройство «Stereo Mix» и запустил пример кода, указанный в этой ссылке, и получил следующий результат:

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

Таким образом, похоже, что только Java Sound Audio Engine может выводить звук, поскольку микшеры для переднего и заднего аудиоразъемов обрабатываются как входные линии. Звук воспроизводится через выходы Clip или SourceDataLine на устройстве воспроизведения Windows по умолчанию.

Кроме того, похоже, что они решили проблему с помощью DirectAudio, но я так и не понял, как их использовать.


person walljam7    schedule 22.01.2016    source источник


Ответы (1)


Во время тестирования на разных компьютерах я решил эту проблему, обновив до Java 1.6.0_17 (что все еще было в порядке с ограничениями моей среды для вызова Java из Matlab), поэтому драйверы DirectAudio будут перечислены (хотя похоже, что он должен работать с Java 1.5). Каждое звуковое устройство DirectAudio предоставляет SourceDataLine и Clip для каждого устройства.

person walljam7    schedule 28.01.2016