问题描述
我已经写了一个简短的程序,从IN / MIC行重定向音频扬声器。我刚学极本,但我的劳动取得了什么似乎差不多是我想要的东西的工作模式。然而,当我打印 TargetDataLine的
缓冲,它打印全0,如果它是连接和数据流,但不能听我的意见。在这一点上,我已经研究得最多的采样
包内容的,什么是可以在网上论坛,教程和其他人的code和因失望缺乏公布的音频code,我觉得我的学习资源已经几乎用完。因此,如果任何人有任何意见或任何资源,这将大大AP preciated。我不认为你需要的任何其他code,但如果你做什么,只问。 。4.3.0.v20130605
Eclipse版本编译下面是类的方法指数为您节省大部分200线code的。
类流继承Thread {
瓦尔
...
流()
setProcessingBuffer()
setRenderingBuffer()
bytesToString()
玩()
暂停()
run()的(覆盖)
}
code:
包莫希;进口javax.sound.sampled.AudioFormat中;
进口javax.sound.sampled.AudioSystem;
进口javax.sound.sampled.Line中;
进口javax.sound.sampled.LineUnavailableException;
进口javax.sound.sampled.Mixer中;
进口javax.sound.sampled.SourceDataLine;
进口javax.sound.sampled.TargetDataLine;/ **
* @author KN
* @version 1.0建设100 2013年10月26日
*
*此并发进程设置和控制音频流
*经由输入和输出缓冲器的数据。
*
* @see {@link主题},{@link AudioSystem},{@link TargetDataLine的},
* {@link的SourceDataLine}
* /公共类流继承Thread { / **的{@link AudioFormat的}在编码/解码用于音频流数据* /
公众最终静态AudioFormat的AudioFormat的=新AudioFormat的(48000,16,2,真实,真实); / **
* {@link字符串}描述音频设备的名称被使用。
*所述p为H.;
*例:线路,麦克风
* /
私有静态字符串输入=麦克风;
/ **
* {@link字符串}描述音频设备的名称被使用。
*所述p为H.;
*例:扬声器,线路输出
* /
私有静态字符串输出=扬声器; / **
* {@link #PROCESSING_BUFFER}是用于接收音频数据的缓冲
*
* @see TargetDataLine的
* /
私有静态TargetDataLine的PROCESSING_BUFFER;
/ **
* {@link #RENDERING_BUFFER}是用于写音频数据的缓冲
*
* @see的SourceDataLine
* /
私有静态的SourceDataLine RENDERING_BUFFER;
/ ** {@link整数}指定缓冲区大小,以字节为单位* /
私有静态诠释BUFFER_SIZE = 2048;
/ ** {@link字节]}保持原始音频数据* /
私人静态的byte []的read_buffer =新的字节[Stream.BUFFER_SIZE] / **
*启动音频硬件读/写缓存成
* {@link TargetDataLine的} S和{@link的SourceDataLine}分别秒。
*
* @see {@link TargetDataLine的},{@link的SourceDataLine}
* /
公共流(){
setProcessingBuffer();
setRenderingBuffer();
} / **
*查询输入线和存储{@link TargetDataLine的}在
* {@link #PROCESSING_BUFFER}
*
* @see {@link AudioSystem},{@link线},{@link TargetDataLine的},
* {@link搅拌机}
* /
私人无效setProcessingBuffer(){
最后Mixer.Info [] = mixerInfos AudioSystem.getMixerInfo();
对于(最终Mixer.Info信息:mixerInfos){
最后的调音台调音台= AudioSystem.getMixer(信息);
最后Line.Info [] = targetLineInfos mixer.getTargetLineInfo();
对于(最终Line.Info targetLineInfo:targetLineInfos){
如果(targetLineInfo.getLineClass()== javax.sound.sampled.TargetDataLine.class
&功放;&安培; info.getName()。startsWith(Stream.INPUT)){
尝试{
Stream.PROCESSING_BUFFER =(TargetDataLine的)mixer.getLine(targetLineInfo);
的System.out.println(targetLineInfo.getLineClass()+:+ info.getName()+[
+ Stream.PROCESSING_BUFFER +]);
}赶上(LineUnavailableException E){
e.printStackTrace();
}
}其他{
}
}
}
} / **
*查询输出线和存储{@link的SourceDataLine}在
* {@link #RENDERING_BUFFER}
*
* @see {@link AudioSystem},{@link线},{@link的SourceDataLine},
* {@link搅拌机}
* /
私人无效setRenderingBuffer(){
最后Mixer.Info [] = mixerInfos AudioSystem.getMixerInfo();
对于(Mixer.Info信息:mixerInfos){
最后的调音台调音台= AudioSystem.getMixer(信息);
最后Line.Info [] = sourceLineInfos mixer.getSourceLineInfo();
对于(最终Line.Info sourceLineInfo:sourceLineInfos){
如果(sourceLineInfo.getLineClass()== javax.sound.sampled.SourceDataLine.class
&功放;&安培; info.getName()。startsWith(Stream.OUTPUT)){
尝试{
Stream.RENDERING_BUFFER =(SourceDataLine的)mixer.getLine(sourceLineInfo);
的System.out.println(sourceLineInfo.getLineClass()+:+ info.getName()+[
+ Stream.RENDERING_BUFFER +]);
}赶上(LineUnavailableException E){
e.printStackTrace();
}
}其他{
}
}
}
} / **
*在字节数组注意到并返回一个String对象的重新presentation
* 数据
*
* @参数数组
*字节数组转换
返回:String对象重新字节数组presentation
* /
私人静态字符串bytesToString(byte []数组){
字符串的ToString =;
对于(字节currentByte:数组){
的toString + = currentByte;
}
返回的toString;
} / **
*打开缓冲器{@link #PROCESSING_BUFFER}和{@link #RENDERING_BUFFER}
*为读/写
* /
公共静态无效播放(){
尝试{
如果(!Stream.PROCESSING_BUFFER.isOpen()){
Stream.PROCESSING_BUFFER.open(Stream.audioFormat,Stream.BUFFER_SIZE);
}
如果(!Stream.RENDERING_BUFFER.isOpen()){
Stream.RENDERING_BUFFER.open(Stream.audioFormat,Stream.BUFFER_SIZE);
Stream.RENDERING_BUFFER.start();
} 而(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);
}
}赶上(例外五){
e.printStackTrace();
}
} / **
*停止缓冲区{@link #PROCESSING_BUFFER}和{@link #RENDERING_BUFFER}
*从读/写
* /
公共静态无效暂停(){
如果(Stream.PROCESSING_BUFFER.isOpen()){
Stream.PROCESSING_BUFFER.close();
}
如果(Stream.RENDERING_BUFFER.isOpen()){
Stream.RENDERING_BUFFER.stop();
Stream.RENDERING_BUFFER.close();
}
} / ** {} @inheritDoc * /
@覆盖
公共无效的run(){
}
}
输出:
接口javax.sound.sampled.TargetDataLine:麦克风(Realtek高Defini [com.sun.media.sound.DirectAudioDevice$DirectTDL@2f57d162]
接口javax.sound.sampled.SourceDataLine:喇叭(Realtek高保真音频)com.sun.media.sound.DirectAudioDevice$DirectSDL@79b7d13e]
0000000000000000000000000000000000000000000000000000000000000 ......而那多很多
解决方案 让我们看看:
Stream.PROCESSING_BUFFER.read(Stream.READ_BUFFER,0,Stream.BUFFER_SIZE);
如果一切正常,直到缓冲区满,这将读取数据,但在你的情况下,一切都不好,其实这是读什么,你可以通过检查的返回值读取告诉
:
INT numRead = Stream.PROCESSING_BUFFER.read(Stream.READ_BUFFER,0,Stream.BUFFER_SIZE);
numRead
0,没有什么已经放在 Stream.READ_BUFFER
。
要确保你输出读取数据,你需要使用:
Stream.RENDERING_BUFFER.write(Stream.READ_BUFFER,0,numRead);
您正在阅读什么的原因是因为你还没有开始的 TargetDataLine的
,您需要:
如果(!Stream.PROCESSING_BUFFER.isOpen()){
Stream.PROCESSING_BUFFER.open(Stream.audioFormat,Stream.BUFFER_SIZE);
Stream.PROCESSING_BUFFER.start();
}
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. 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. 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
.
Here's a method index of the class to save you most of 200 lines of code.
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
:
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
.
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:
if (!Stream.PROCESSING_BUFFER.isOpen()) {
Stream.PROCESSING_BUFFER.open(Stream.audioFormat, Stream.BUFFER_SIZE);
Stream.PROCESSING_BUFFER.start();
}
这篇关于JAVA音频数据流0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!