JAVA音频数据流0s

我一直在编写一个简短的程序,将音频从/ mic转换为扬声器。 我只是在学习大部分内容,但是我的工作已经产生了似乎几乎是我想要的工作模型。 但是,当我打印TargetDataLine缓冲区时,它会打印所有0,就像它已连接和流式传输一样,但无法听到我的输入。 在这一点上,我已经研究了大部分sampled包内容以及在论坛,教程和其他人的代码中可以在线获得的内容,并且由于缺乏已发布的音频代码,我认为我的学习资源几乎耗尽了。 因此,如果任何人有任何建议或资源,我们将不胜感激。 我认为您不需要任何其他代码,但如果您这样做,请问。 此代码使用Eclipse version: 4.3.0.v20130605在我的机器上编译时没有错误或警告Eclipse version: 4.3.0.v20130605

这是类的方法索引,可以保存大部分200行代码。

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

码:

 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. * 

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

* 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() { } }

输出:

 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 

让我们来看看:

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

如果一切顺利,这将读取数据,直到缓冲区已满,但在你的情况下一切都不好,实际上它没有读取任何内容,你可以通过检查read返回的值来判断:

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

numRead为0,并且没有在Stream.READ_BUFFER放入Stream.READ_BUFFER

要确保输出已读取的数据,您需要使用:

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

您没有阅读任何内容的原因是因为您尚未启动TargetDataLine ,您需要:

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