简体   繁体   English

JAVA音频数据流0s

[英]JAVA audio data streaming 0s

I've been writing a short program to redirect audio from the line in/mic to to speakers. 我一直在写一个简短的程序,将音频从线路输入/麦克风重定向到扬声器。 I'm just learning most of this, but my labors have yielded what seems to almost be a working model of what I want. 我只是在学习大部分,但是我的工作似乎已经成为我想要的工作模型。 However, when I print the TargetDataLine buffer, it prints all 0s as if it was connected and streaming, but can't hear my input. 但是,当我打印TargetDataLine缓冲区时,它会打印全0,就好像它已连接并正在流式传输一样,但是听不到我的输入。 At this point, I've studied most of the sampled package content and what was available online in forums, tutorials, and other people's code, and due to the disappointing lack of published audio code, I think my studying resources have all but run out. 在这一点上,我已经研究得最多的的sampled包内容和什么是可在网上论坛,教程和其他人的代码,并且由于令人失望的缺乏公布的音频编码,我认为我的学习资源几乎已经用完。 So, if anyone has any advice or resources whatsoever, it would be greatly appreciated. 因此,如果任何人有任何建议或资源,将不胜感激。 I don't think you'll need any of the other code, but if you do, just ask. 我认为您不需要其他任何代码,但是如果需要,请问一下。 This code compiles without errors or warnings on my machine using Eclipse version: 4.3.0.v20130605 . 这段代码使用Eclipse version: 4.3.0.v20130605在我的机器上编译时没有错误或警告。

Here's a method index of the class to save you most of 200 lines of code. 这是该类的方法索引,可为您节省200条代码中的大部分。

class Stream extends Thread {
    vars
    ...
    Stream()
    setProcessingBuffer()
    setRenderingBuffer()
    bytesToString()
    play()
    pause()
    run() (Override)
}

Code: 码:

package moshi;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;

/**
 * @author KN
 * @version 1.0 Build 1 October 26, 2013
 * 
 *          This concurrent process sets up and controls the streaming of audio
 *          data via input and output buffers.
 * 
 * @see {@link Thread}, {@link AudioSystem}, {@link TargetDataLine},
 *      {@link SourceDataLine}
 */

public class Stream extends Thread {

    /** The {@link AudioFormat} used in encoding/decoding streaming audio data */
    public final static AudioFormat audioFormat = new AudioFormat(48000, 16, 2, true, true);

    /**
     * {@link String} describing the name of the audio device to be used.
     * <p>
     * Example: "Line In", "Microphone"
     */
    private static String INPUT = "Mic";
    /**
     * {@link String} describing the name of the audio device to be used.
     * <p>
     * Example: "Speakers", "Line Out"
     */
    private static String OUTPUT = "Speakers";

    /**
     * {@link #PROCESSING_BUFFER} is a buffer used for receiving audio data
     * 
     * @see TargetDataLine
     */
    private static TargetDataLine PROCESSING_BUFFER;
    /**
     * {@link #RENDERING_BUFFER} is a buffer used for writing audio data
     * 
     * @see SourceDataLine
     */
    private static SourceDataLine RENDERING_BUFFER;
    /** {@link Integer} specifying the buffer sizes in bytes */
    private static int BUFFER_SIZE = 2048;
    /** {@link Byte[]} for holding raw audio data */
    private static byte[] READ_BUFFER = new byte[Stream.BUFFER_SIZE];

    /**
     * Initiates the audio hardware read/write buffers into
     * {@link TargetDataLine}s and {@link SourceDataLine}s respectively.
     * 
     * @see {@link TargetDataLine}, {@link SourceDataLine}
     */
    public Stream() {
        setProcessingBuffer();
        setRenderingBuffer();
    }

    /**
     * Queries input Lines and stores the {@link TargetDataLine} at
     * {@link #PROCESSING_BUFFER}
     * 
     * @see {@link AudioSystem}, {@link Line}, {@link TargetDataLine},
     *      {@link Mixer}
     */
    private void setProcessingBuffer() {
        final Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
        for (final Mixer.Info info : mixerInfos) {
            final Mixer mixer = AudioSystem.getMixer(info);
            final Line.Info[] targetLineInfos = mixer.getTargetLineInfo();
            for (final Line.Info targetLineInfo : targetLineInfos) {
                if (targetLineInfo.getLineClass() == javax.sound.sampled.TargetDataLine.class
                    && info.getName().startsWith(Stream.INPUT)) {
                    try {
                        Stream.PROCESSING_BUFFER = (TargetDataLine) mixer.getLine(targetLineInfo);
                        System.out.println(targetLineInfo.getLineClass() + ": " + info.getName() + " ["
                            + Stream.PROCESSING_BUFFER + "] ");
                    } catch (LineUnavailableException e) {
                        e.printStackTrace();
                    }
                } else {
                }
            }
        }
    }

    /**
     * Queries output Lines and stores the {@link SourceDataLine} at
     * {@link #RENDERING_BUFFER}
     * 
     * @see {@link AudioSystem}, {@link Line}, {@link SourceDataLine},
     *      {@link Mixer}
     */
    private void setRenderingBuffer() {
        final Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
        for (Mixer.Info info : mixerInfos) {
            final Mixer mixer = AudioSystem.getMixer(info);
            final Line.Info[] sourceLineInfos = mixer.getSourceLineInfo();
            for (final Line.Info sourceLineInfo : sourceLineInfos) {
                if (sourceLineInfo.getLineClass() == javax.sound.sampled.SourceDataLine.class
                    && info.getName().startsWith(Stream.OUTPUT)) {
                    try {
                        Stream.RENDERING_BUFFER = (SourceDataLine) mixer.getLine(sourceLineInfo);
                        System.out.println(sourceLineInfo.getLineClass() + ": " + info.getName() + " ["
                            + Stream.RENDERING_BUFFER + "]");
                    } catch (LineUnavailableException e) {
                        e.printStackTrace();
                    }
                } else {
                }
            }
        }
    }

    /**
     * Takes in an array of bytes and returns a String object representation of
     * the data
     * 
     * @param array
     *            The byte array to be converted
     * @return The string object representation of a byte array
     */
    private static String bytesToString(byte[] array) {
        String toString = "";
        for (byte currentByte : array) {
            toString += currentByte;
        }
        return toString;
    }

    /**
     * Opens buffers {@link #PROCESSING_BUFFER} and {@link #RENDERING_BUFFER}
     * for reading/writing
     */
    public static void play() {
        try {
            if (!Stream.PROCESSING_BUFFER.isOpen()) {
                Stream.PROCESSING_BUFFER.open(Stream.audioFormat, Stream.BUFFER_SIZE);
            }
            if (!Stream.RENDERING_BUFFER.isOpen()) {
                Stream.RENDERING_BUFFER.open(Stream.audioFormat, Stream.BUFFER_SIZE);
                Stream.RENDERING_BUFFER.start();
            }

            while (Stream.RENDERING_BUFFER.isOpen()) {
                Stream.PROCESSING_BUFFER.read(Stream.READ_BUFFER, 0, Stream.BUFFER_SIZE);
                System.out.println(Stream.bytesToString(Stream.READ_BUFFER));
                Stream.RENDERING_BUFFER.write(Stream.READ_BUFFER, 0, Stream.BUFFER_SIZE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Stops buffers {@link #PROCESSING_BUFFER} and {@link #RENDERING_BUFFER}
     * from reading/writing
     */
    public static void pause() {
        if (Stream.PROCESSING_BUFFER.isOpen()) {
            Stream.PROCESSING_BUFFER.close();
        }
        if (Stream.RENDERING_BUFFER.isOpen()) {
            Stream.RENDERING_BUFFER.stop();
            Stream.RENDERING_BUFFER.close();
        }
    }

    /** {@inheritDoc} */
    @Override
    public void run() {
    }
}

Output: 输出:

interface javax.sound.sampled.TargetDataLine: Microphone (Realtek High Defini [com.sun.media.sound.DirectAudioDevice$DirectTDL@2f57d162] 
interface javax.sound.sampled.SourceDataLine: Speakers (Realtek High Definition Audio) [com.sun.media.sound.DirectAudioDevice$DirectSDL@79b7d13e]
0000000000000000000000000000000000000000000000000000000000000...... And a lot more of that

Lets look at: 让我们看一下:

Stream.PROCESSING_BUFFER.read(Stream.READ_BUFFER, 0, Stream.BUFFER_SIZE);

if all is well this will read data until the buffer is full, but in your case all is not well and in fact it is reading nothing as you can tell by checking the value returned by read : 如果一切正常,它将读取数据,直到缓冲区已满为止,但是在您的情况下,一切都不好,实际上,它没有读取任何内容,通过检查read返回的值可以看出:

int numRead = Stream.PROCESSING_BUFFER.read(Stream.READ_BUFFER, 0, Stream.BUFFER_SIZE);

numRead is 0 and nothing has been put in Stream.READ_BUFFER . numRead为0,并且Stream.READ_BUFFER没有任何Stream.READ_BUFFER

To be sure you output the data that was read you need to use: 为了确保您输出已读取的数据,您需要使用:

Stream.RENDERING_BUFFER.write(Stream.READ_BUFFER, 0, numRead);

The reason you are reading nothing is because you have not started the TargetDataLine , you need: 您什么都没读的原因是因为尚未启动TargetDataLine ,因此需要:

if (!Stream.PROCESSING_BUFFER.isOpen()) {
    Stream.PROCESSING_BUFFER.open(Stream.audioFormat, Stream.BUFFER_SIZE);
    Stream.PROCESSING_BUFFER.start();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM