草庐IT

java - Windows 7 上的 Java 是否支持任何声音格式?

coder 2024-03-13 原文

我们会的,我一直在用头撞墙试图让 Java 播放一些简单的 wav 文件,但没有任何运气。我试过这段代码:

Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(soundBytes));
clip.open(inputStream);
clip.start();

这在“clip.open(...)”上失败,异常:

javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.

我试过更复杂的(流媒体版本):

int BUFFER_SIZE = 128000;
AudioInputStream audioStream = null;
AudioFormat audioFormat;
SourceDataLine sourceLine = null;

try {
    audioStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(soundBytes));
} catch (Exception e){
    e.printStackTrace();
}

audioFormat = audioStream.getFormat();

DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
try {
    sourceLine = (SourceDataLine) AudioSystem.getLine(info);
    sourceLine.open(audioFormat);
} catch (LineUnavailableException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}

sourceLine.start();

int nBytesRead = 0;
byte[] abData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
    try {
        nBytesRead = audioStream.read(abData, 0, abData.length);
    } catch (IOException e) {
        e.printStackTrace();
    }
    if (nBytesRead >= 0) {
       @SuppressWarnings("unused")
       int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
    }
}

sourceLine.drain();
sourceLine.close();

这在“sourceLine.open(...)”上也失败了,异常是:

javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.

我尝试了两种不同的 wav 文件,包括 C:\Windows\Media 中的古老的“tada.wav”。

我还使用 GoldWave 将其中一个文件更改为无符号 8 位单声道,但这只是将错误消息更改为:

javax.sound.sampled.LineUnavailableException: line with format PCM_UNSIGNED 44100.0 Hz, 8 bit, mono, 1 bytes/frame,  not supported.

关于我可能哪里出错的任何想法?似乎播放一个简单的 wave 文件应该很简单,所以我猜我在某个地方迷路了。

提前致谢。

更新

所以,情节变厚了。如果我们将它移到一个单独的独立 java 程序中,代码就可以正常工作。我们的应用程序中一定有什么东西在破坏 Java 播放声音的能力。

这是上述错误的堆栈跟踪:

javax.sound.sampled.LineUnavailableException: line with format PCM_UNSIGNED 44100.0 Hz, 8 bit, mono, 1 bytes/frame,  not supported.
at com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(DirectAudioDevice.java:492)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:107)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:139)
at com.hcs.orc.detail.SoundAddEdit.playButtonActionPerformed(SoundAddEdit.java:315)
at com.hcs.orc.detail.SoundAddEdit.access$100(SoundAddEdit.java:40)
at com.hcs.orc.detail.SoundAddEdit$2.actionPerformed(SoundAddEdit.java:225)

更新 2

更多有趣的发现。看来我们在加载 DLL 时发生了冲突。我们有自己的 DLL 来帮助我们做一些事情(比如找到一个可靠且可用的 MAC 地址)。如果您在加载我们的 DLL 之前播放声音(加载声音相关的 DLL),那么两者都可以工作。但是,如果您使用我们的 DLL,然后尝试播放声音,声音会给您上面报告的错误。

有人知道为什么一个看似无关的 DLL 会导致另一个 DLL 稍后加载不正确吗?

作为真正蹩脚和糟糕的解决方法的条目,我们可以在查找 MAC 地址之前在启动时播放几分之一秒的静音。这是一种糟糕的形式,原因有很多,其中包括我们的许多客户根本不使用声音。

更新 3

深入研究我们的库,问题似乎是由对 RegisterClassEx(...) 的调用引起的。我们这样做是为了可以显示带有 HTML 帮助文件的嵌入式 IE 窗口。

最佳答案

我以前遇到过类似的问题(尽管与加载 DLL 无关。)Javasound 通过使用 1 个或多个混音器在底层工作,每个混音器有 1 行或多行。这些行中的每一行都有许多它说它支持的格式,但这并不意味着它在播放该格式时不会自发燃烧(本质上,没有什么能阻止它吹嘘播放它不能播放的格式。)

当您使用 AudioSystem.getLine() 时,它将遍历所有这些混音器的所有这些行,并基本上返回它遇到的第一个表示它可以处理该格式的行。如果该行是一个大骗子,那么它就不会寻找其他行 - 它只会随之而来并产生您所看到的错误。

现在这里要记住的重要一点是它在这些行上迭代的顺序是完全任意的。所以任何事情都可能导致它发生变化,包括看似无关紧要的事情,例如加载 DLL。我可以在这里看到两种可能性之一,DLL 以某种方式提供了导致问题的另一条音频线路,或者加载 DLL 只会导致任意顺序发生变化,当您这样做时,由于某种原因它首先遇到可疑线路。

解决方法并不好,但比播放声音并稍等片刻要好,您基本上必须测试线路以查看它是否在说真话:

SourceDataLine dataline = null;
for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
    try {
        Mixer mixer = AudioSystem.getMixer(mixerInfo);
        dataline = (SourceDataLine)mixer.getLine(info);
        if(dataline==null) {
            continue; //Doesn't support this format
        }
        dataline.open(audioFormat);
        dataline.start();
    }
    catch (Exception ex) {
        //If we get here it's a buggered line, so loop round again
        continue;
    }
    try {
        dataline.close();
    }
    catch (Exception ex) {
        ex.printStackTrace(); //Shouldn't get here
    }
}


if(dataline==null) {
    //No dataline capable of *really* playing the stream
}
else {
    //We have a non-lying dataline!
}

这种方式需要更长的时间,但它本质上是双重检查 - 我们遍历每条数据线,如果它它可以播放格式,我们检查它是否真的可以 - 并且只在那种情况下,我们会确定它是否可以安全使用。

关于java - Windows 7 上的 Java 是否支持任何声音格式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20959838/

有关java - Windows 7 上的 Java 是否支持任何声音格式?的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  4. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  7. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  8. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  9. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  10. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

随机推荐