如何解决我无法在 java
我知道这个问题与 StackOverflow 上的另一个问题重复,我尽我所能理解捕获混音器音频背后的概念,但直到现在我才能录制我的电脑系统音频。
>我访问过的网站以了解该概念:
1-https://docs.oracle.com/javase/tutorial/sound/capturing.html
3-https://www.youtube.com/watch?v=GVtl19L9GxU
我访问过的 StackOverFlow 问题:
1-Recording speakers Ouput using Java
2-How to get TargetDataLine from Speakers?
3-Recording System Audio via Java
4-Capture audio going to speakers
我已尽力理解使用 API 的概念,但在遇到这个问题之前我仍然无法捕获任何音频:
Java: Processing audio in real time from speakers
此人试图迭代混音器并找到合适的混音器“扬声器”并将其用于他的代码。他的代码如下所示:
package audio;
import javax.sound.sampled.*;
public class App1 {
public static String getWord(String arr) {
int i = 0;
for(; i < arr.length(); i++) {
if (arr.charat(i) == ' ')
break;
}
return arr.substring(0,i);
}
public static void wait(int ms) {
try{
Thread.sleep(ms);
}
catch(InterruptedException ex){
Thread.currentThread().interrupt();
}
}
public static AudioFormat getAudioFormat(){
float sampleRate = 44100;
//8000,11025,16000,22050,44100
int sampleSizeInBits = 16;
//8,16
int channels = 1;
//1,2
boolean signed = true;
//true,false
boolean bigEndian = false;
//true,false
//return new AudioFormat(Encoding.PCM_SIGNED,sampleRate,16,1,2,false);
return new AudioFormat(sampleRate,sampleSizeInBits,channels,signed,bigEndian);
}
public static void main(String [] args) {
try {
//-----DECLaraTIONS-----
TargetDataLine targetDataLine = null;
mixer.Info[] mixers = AudioSystem.getmixerInfo();
mixer.Info m = null;
String expectedmixer = "Speakers";
//-----mixer FINDER-----
System.out.println("Number of mixers: " + mixers.length);
for(int i = 0; i < mixers.length; i++) {
System.out.println(getWord(mixers[i].getName()));
if(getWord(mixers[i].getName()).compareto(expectedmixer) == 0){
m = mixers[i];
}
}
if(m==null) throw new Exception("No such mixer found: " + expectedmixer);
else System.out.println('\n'+"Device choosen: "+m.getName());
//-----LINE TESTER-----
boolean v = false,showError = true; // show error or keep trying several times
int tries = 3,i = 0;
while(v==false && i++ < tries){
try {
//sourceDataLine = AudioSystem.getTargetDataLine(getAudioFormat(),m);
targetDataLine = AudioSystem.getTargetDataLine(getAudioFormat(),m);
targetDataLine.open(getAudioFormat());
v=true;
//System.out.println("Success!");
} catch (IllegalArgumentException e){
if (showError) {
v = true;
e.printstacktrace();
}
else {
System.out.println("Error! retrying... "+i+'/'+tries);
v = false;
}
wait(2000);
}
}
if(i-1==tries)
//System.out.println("No success :(");
throw new Exception("No success :(");
else
if(v==false)
System.out.println("SourceData line found and accepted !");
//-----SIGNAL PROCESSING-----
//nothing here because the rest isn't working
} catch(Exception e) { e.printstacktrace();}
}
}
我注意到在第 67 行
targetDataLine = AudioSystem.getTargetDataLine(getAudioFormat(),m);
他正在使用带有 2 个参数的 getTargetDataLine,如果您删除了第二个参数 (m)
代码继续执行并且没有出现错误......(“我的错误可能来自这里”)
我重新修改了代码并删除了 (m) 参数并将 data-target-line 设为静态和全局并添加了我自己的其他修改以开始录制系统音频 10 秒(我确定我做到了这样做时犯了一个错误,但我真的不知道),:
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import javax.sound.sampled.*;
public class App1 {
static TargetDataLine targetDataLine = null;
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
static DataLine.Info info = new DataLine.Info(SourceDataLine.class,getAudioFormat());
public static String getWord(String arr) {
int i = 0;
for (; i < arr.length(); i++) {
if (arr.charat(i) == ' ')
break;
}
return arr.substring(0,i);
}
public static void wait(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
public static AudioFormat getAudioFormat() {
float sampleRate = 48000;
// 8000,44100
int sampleSizeInBits = 16;
// 8,16
int channels = 2;
// 1,2
boolean signed = true;
// true,false
boolean bigEndian = false;
// true,false
// return new AudioFormat(Encoding.PCM_SIGNED,// false);
return new AudioFormat(sampleRate,bigEndian);
}
static void showLineInfoFormats(final Line.Info lineInfo) {
if (lineInfo instanceof DataLine.Info) {
final DataLine.Info dataLineInfo = (DataLine.Info) lineInfo;
Arrays.stream(dataLineInfo.getFormats()).forEach(format -> System.out.println(" " + format.toString()));
}
}
public static void main(String[] args) throws LineUnavailableException,IOException,InterruptedException {
try {
// -----DECLaraTIONS-----
mixer.Info[] mixers = AudioSystem.getmixerInfo();
mixer.Info m = null;
String expectedmixer = "Speakers";
// -----mixer FINDER-----
System.out.println("Number of mixers: " + mixers.length);
for (int i = 0; i < mixers.length; i++) {
System.out.println(getWord(mixers[i].getName()));
if (getWord(mixers[i].getName()).compareto(expectedmixer) == 0) {
m = mixers[i];
}
}
if (m == null)
throw new Exception("No such mixer found: " + expectedmixer);
else
System.out.println('\n' + "Device choosen: " + m.getName());
// showLineInfoFormats(info);
// -----LINE TESTER-----
boolean v = false,i = 0;
while (v == false && i++ < tries) {
try {
// sourceDataLine = AudioSystem.getTargetDataLine(getAudioFormat(),m);
targetDataLine = AudioSystem.getTargetDataLine(getAudioFormat());
targetDataLine = (TargetDataLine) ((mixer) m).getLine(info);
targetDataLine.open(getAudioFormat());
v = true;
// System.out.println("Success!");
} catch (IllegalArgumentException e) {
if (showError) {
v = true;
e.printstacktrace();
} else {
System.out.println("Error! retrying... " + i + '/' + tries);
v = false;
}
wait(2000);
}
}
if (i - 1 == tries)
// System.out.println("No success :(");
throw new Exception("No success :(");
else if (v == false)
System.out.println("SourceData line found and accepted !");
// -----SIGNAL PROCESSING-----
// nothing here because the rest isn't working
} catch (Exception e) {
e.printstacktrace();
}
System.out.println("We are here");
// targetDataLine.open();
System.out.println("Starting REcord");
targetDataLine.start();
System.out.println("targetDataLine.start() finished");
Thread thread = new Thread();
{
run();
System.out.println("run() finished");
}
thread.start();
System.out.println("thread.start() finished");
Thread.sleep(10000);
System.out.println("Thread.sleep(5000) finished");
targetDataLine.stop();
System.out.println("targetDataLine.stop() finished");
targetDataLine.close();
System.out.println("NO WAAAAAAAAAAY!!!");
}
private static void run() throws IOException {
AudioInputStream audioStream = new AudioInputStream(targetDataLine);// issue maybe?
File wavFile = new File("E:/Test/RecordAudio.wav");
AudioSystem.write(audioStream,AudioFileFormat.Type.WAVE,wavFile);
}
}
您可以看到我添加了一些 System.out.println()
语句来指示代码的结束位置。
现在我收到此错误消息的问题:
java.lang.classCastException:类 com.sun.media.sound.DirectAudioDeviceProvider$DirectAudioDeviceInfo 不能转换为类 javax.sound.sampled.mixer(com.sun.media.sound.DirectAudioDeviceProvider$DirectAudioDeviceInfo 和 javax.sound.sound.sampled.mixer。 sampled.mixer 在 loader 'bootstrap' 的模块 java.desktop 中) 在 Test2.App1.main(App1.java:88)
输出“RecordAudio.wav”不播放任何内容,甚至不到 10 秒。
所以我认为我对 TargetDataLine 的声明是错误的,因为这个答案指出 How to get TargetDataLine from Speakers?
所以我将 static TargetDataLine targetDataLine = null;
更改为 static SourceDataLine targetDataLine = null;
并对其进行了其他相关更改,最后使代码看起来像这样...
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import javax.sound.sampled.*;
public class App1 {
static SourceDataLine targetDataLine = null;
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
static DataLine.Info info = new DataLine.Info(SourceDataLine.class,m);
targetDataLine = (SourceDataLine) AudioSystem.getTargetDataLine(getAudioFormat());
targetDataLine = (SourceDataLine) ((mixer) m).getLine(info);
targetDataLine.open(getAudioFormat());
v = true;
// System.out.println("Success!");
} catch (IllegalArgumentException e) {
if (showError) {
v = true;
e.printstacktrace();
} else {
System.out.println("Error! retrying... " + i + '/' + tries);
v = false;
}
wait(2000);
}
}
if (i - 1 == tries)
// System.out.println("No success :(");
throw new Exception("No success :(");
else if (v == false)
System.out.println("SourceData line found and accepted !");
// -----SIGNAL PROCESSING-----
// nothing here because the rest isn't working
} catch (Exception e) {
e.printstacktrace();
}
System.out.println("We are here");
// targetDataLine.open();
System.out.println("Starting REcord");
targetDataLine.start();
System.out.println("targetDataLine.start() finished");
Thread thread = new Thread();
{
run();
System.out.println("run() finished");
}
thread.start();
System.out.println("thread.start() finished");
Thread.sleep(10000);
System.out.println("Thread.sleep(5000) finished");
targetDataLine.stop();
System.out.println("targetDataLine.stop() finished");
targetDataLine.close();
System.out.println("NO WAAAAAAAAAAY!!!");
}
private static void run() throws IOException {
AudioInputStream audioStream = new AudioInputStream((TargetDataLine) targetDataLine);// issue maybe?
File wavFile = new File("E:/Test/RecordAudio.wav");
AudioSystem.write(audioStream,wavFile);
}
}
现在我收到此错误 java.lang.classCastException:类 com.sun.media.sound.DirectAudioDevice$DirectTDL 不能转换为类 javax.sound.sampled.sourceDataLine(com.sun.media.sound.DirectAudioDevice$DirectTDL 和 javax.sound.sampled.sourceDataLine位于加载程序“引导程序”的模块 java.desktop 中) 在 Test2.App1.main(App1.java:86)
线程“main”中的异常java.lang.NullPointerException:无法调用“javax.sound.sampled.sourceDataLine.start()”,因为“Test2.App1.targetDataLine”为空 在 Test2.App1.main(App1.java:121)
我想到并尝试过的其他事情: 我认为我的问题可能来自音频格式,所以我使用此代码查看我的默认扬声器音频格式
import javax.sound.sampled.*;
public class AudioFormatChecker {
public static void main(String[] args) throws LineUnavailableException {
mixer mixer = AudioSystem.getmixer(null); // default mixer
mixer.open();
System.out.printf("Supported SourceDataLines of default mixer (%s):\n\n",mixer.getmixerInfo().getName());
for (Line.Info info : mixer.getSourceLineInfo()) {
if (SourceDataLine.class.isAssignableFrom(info.getLineClass())) {
SourceDataLine.Info info2 = (SourceDataLine.Info) info;
System.out.println(info2);
System.out.printf(" max buffer size: \t%d\n",info2.getMaxBufferSize());
System.out.printf(" min buffer size: \t%d\n",info2.getMinBufferSize());
AudioFormat[] formats = info2.getFormats();
System.out.println(" Supported Audio formats: ");
for (AudioFormat format : formats) {
System.out.println(" " + format);
}
System.out.println();
} else {
System.out.println(info.toString());
}
System.out.println();
}
mixer.close();
}
}
我尽我最大的努力去理解和实现声音 API 的概念,但我做不到。我使用声音 API 的主要目的是从系统中捕获音频,然后将其用于其他目的。我尝试录制系统,以便我可以测试我在程序中管理的内容是否确实有效,并且我的程序是否正在录制音频。
我也不明白,为什么互联网上的任何地方都没有针对此类常见问题的有效样本???
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。