Воспроизведение звука с микрофона в реальном времени

#java #audio

#ява #Аудио

Вопрос:

Хорошо, я искал, но не нашел решения. Мне удалось получить byte[] вывод с микрофона с AudioFormat(44100.0f, 32, 2, true, true); форматом. Хорошо, но теперь я хочу воспроизвести его через наушники, чтобы протестировать.

Я много чего прочитал, погуглил и посмотрел здесь, в StackOverflow, но я не могу найти способ просто воспроизвести мои уже сохраненные данные в наушниках (или на реальном устройстве вывода звука).

Я читал, что обычный способ — воспроизвести его из клипа (а клип считывает поток файлов аудиофайла) или альтернативно использовать SourceDataLine. Но я хочу вернуть byte[] в выходной поток или в буфер и воспроизвести его в реальном времени.

Мой код предназначен для вызова около 60 раз в секунду (поскольку он работает вложенным в 3D-приложение, возможно, я добавлю его позже) и выводит byte[] для графического представления.

Мой фактический (нерабочий) подход заключается в следующем (публикуя полный код ниже для завершения):

 /* DATA
AudioFormat format;      //Audio format (already initialiced)
TargetDataLine line;     //Microphone line (working)
DataLine.Info info;
byte soundArray[];       //The last retrieved data
*/

private void playOnRealtime() throws LineUnavailableException {

    Clip clip = AudioSystem.getClip();

    TargetDataLine d_line;
    AudioInputStream inputStream;
    DataLine.Info info = new DataLine.Info(SourceDataLine.class,
            format); // format is an AudioFormat object
    if (!AudioSystem.isLineSupported(info)) {
        System.err.print("Dataline OUT not supported!");
    }

    try {
        d_line = AudioSystem.getTargetDataLine(format);
        d_line.open();
        d_line.start();
        inputStream = AudioSystem.getAudioInputStream(format, new AudioInputStream(d_line));

        clip.open(inputStream);
        clip.start();
        d_line.stop();
        clip.stop();

    } catch (LineUnavailableException ex) {
        // Handle the error.
        // ...
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
  

Полный код здесь (если кто-то сочтет это уместным):

 package main;

import java.io.IOException;

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.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;

public class Monitor implements Runnable {

    AudioFormat format;
    TargetDataLine line;
    DataLine.Info info;
    byte soundArray[];

    public Monitor() {
        format = new AudioFormat(44100.0f, 32, 2, true, true);
        // format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
        // 44100.0F, 16, 2, 4, 44100.0F, false);

        try {
            line = AudioSystem.getTargetDataLine(format);
        } catch (LineUnavailableException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        DataLine.Info info = new DataLine.Info(TargetDataLine.class,
                format); // format is an AudioFormat object
        if (!AudioSystem.isLineSupported(info)) {
            // Handle the error ...
        }
        // Obtain and open the line.
        try {
            line = (TargetDataLine) AudioSystem.getLine(info);
            line.open(format);
        } catch (LineUnavailableException ex) {
            // Handle the error ...
        }

        soundArray = new byte[8000];

    }

    boolean started;

    @Override
    public void run() {
        try {
            line.open();
            line.start();
            line.read(soundArray, 0, 8000);
            System.out.println('A');
            printFloatArray(fragment(16, soundArray));
            line.stop();

        } catch (LineUnavailableException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            playOnRealtime();
        } catch (LineUnavailableException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private static byte[] fragment(int n, byte[] array) {

        int length = array.length;

        byte[] result = new byte[n];

        for (int k = 0; k < n; k  ) {
            result[k] = array[k * (length / n)];
        }

        return resu<

    }

    private static void printFloatArray(byte[] array) {

        for (byte var : array) {
            System.out.print(String.format("=", var)   "t");
        }
    }

    public byte[] getData(int n_div) {

        return fragment(n_div, soundArray);
    }

    private void playOnRealtime() throws LineUnavailableException {

        Clip clip = AudioSystem.getClip();

        TargetDataLine d_line;
        AudioInputStream inputStream;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class,
                format); // format is an AudioFormat object
        if (!AudioSystem.isLineSupported(info)) {
            System.err.print("Dataline OUT not supported!");
        }

        try {
            d_line = AudioSystem.getTargetDataLine(format);
            d_line.open();
            d_line.start();
            inputStream = AudioSystem.getAudioInputStream(format, new AudioInputStream(d_line));

            clip.open(inputStream);
            clip.start();
            d_line.stop();
            clip.stop();

        } catch (LineUnavailableException ex) {
            // Handle the error.
            // ...
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}