在Java中使用/读取FMOD(.fsb)文件
大家好。我目前正在开发一个应用程序,可以播放FMOD数据库中的音乐文件。目前,它通过将文件(使用一个运行时和一个名为“fsbextract.exe”()的外部程序)提取为MP3,然后播放它们来实现。我可以接受这个事实,但我现在也希望编辑/替换.fsb文件中的文件。所以我的问题是:我可以直接访问那里的MP3文件而不提取它们吗?我在网上搜索了类似的东西,但找不到任何帮助 以下是我可以从fsbextract内部获得的一些信息,以供参考: FileID为| FSB4>|版本为4.0 |条目数7412 全球标志: 0x40 | FMOD | FSB |源| MPEG |填充4 | MPEG帧与最接近的4字节对齐,多通道为16字节(使用帧验证选项) 从fsb文件中的第一个(索引0)文件: 格式:MP3(85) 采样率:44100Hz 频道:单声道 持续时间:01.541 比特率:160,62 kbit/s 位/样本3.64 采样模式标志[0x10000200] 0x200 | FSOUND | U MPEG |样本以MPEG格式存储 0x10000000 | FSOUND | U MPEG |层3 |样本以MPEG第3层格式存储 我希望有人知道的比我多,但先谢谢你在Java中使用/读取FMOD(.fsb)文件,java,mp3,fmod,Java,Mp3,Fmod,大家好。我目前正在开发一个应用程序,可以播放FMOD数据库中的音乐文件。目前,它通过将文件(使用一个运行时和一个名为“fsbextract.exe”()的外部程序)提取为MP3,然后播放它们来实现。我可以接受这个事实,但我现在也希望编辑/替换.fsb文件中的文件。所以我的问题是:我可以直接访问那里的MP3文件而不提取它们吗?我在网上搜索了类似的东西,但找不到任何帮助 以下是我可以从fsbextract内部获得的一些信息,以供参考: FileID为| FSB4>|版本为4.0 |条目数7412 全
MarenthyuJérôme Jouvie为FMOD 4+编写了一个JNI包装器。如果您的FSB文件未加密,我认为您可以使用API从FSB银行提取流数据 我也试着写我自己的包装器,但我没有时间通过一个简单的概念证明 更新:当然。因此,基本上我所做的是包装本机FMODex库,然后将生成的粘合代码定向到运行时环境。这基本上允许您调用本机FMOD C库 我不确定Jerome是否做了类似的事情,或者他是否创建了自己的JNI存根来实现同样的结果。你必须检查并阅读他的项目代码 但本质上,一旦您能够在应用程序中进行FMOD调用,您就可以使用API来做您想做的事情。如果您从下载最新的FMOD studio或FMODex SDK,您将找到一个帮助
.chm
文件,其中包含一些API文档
您还应该看看SDK中的示例
下面的代码基本上是使用上述策略翻译成Java的一个示例。代码不是可移植的、健壮的,对于应用程序来说也不是真正有用的。它确实需要清理,但它仍然说明了这一点
正如我所说,使用Jerome的SDK端口应该会更好
希望能有帮助
package net.unsungstories.fmodex;
import net.unsungstories.fmodex.FmodexLibrary.FMOD_CHANNEL;
import net.unsungstories.fmodex.FmodexLibrary.FMOD_SOUND;
import net.unsungstories.fmodex.FmodexLibrary.FMOD_SYSTEM;
import org.apache.log4j.Logger;
import org.bridj.IntValuedEnum;
import org.bridj.Platform;
import org.bridj.Pointer;
import org.junit.Test;
import static org.bridj.Pointer.*;
import static net.unsungstories.fmodex.FmodexLibrary.*;
import static com.google.common.base.Throwables.*;
import static java.lang.String.format;
public class PlaySound {
private static final Logger log = Logger.getLogger(PlaySound.class);
@Test
public void playSound() {
log.info("Test started...");
String soundPath = "./src/test/resources/picus_get_to_finicular_music_0.fsb";
Platform.addEmbeddedLibraryResourceRoot("net/unsungstories/fmodex/");
IntValuedEnum<FMOD_RESULT> result;
Pointer<Pointer<FMOD_SYSTEM>> ppSystem = allocatePointer(FMOD_SYSTEM.class);
Pointer<Pointer<FMOD_SOUND>> ppSound1 = allocatePointer(FMOD_SOUND.class);
Pointer<Integer> pSubSounds = allocateInt();
Pointer<Pointer<FMOD_CHANNEL>> ppChannel = allocatePointer(FMOD_CHANNEL.class);
@SuppressWarnings("unchecked")
Pointer<FMOD_CREATESOUNDEXINFO> soundExInfo = Pointer.NULL;
Pointer<Byte> targetSoundPath = allocateBytes(soundPath.length() + 1);
targetSoundPath.setCString(soundPath);
result = FMOD_System_Create(ppSystem);
result = FMOD_System_Init(ppSystem.get(), 2, FmodexLibrary.FMOD_INIT_NORMAL, Pointer.NULL);
result = FMOD_System_CreateSound(ppSystem.get(), targetSoundPath, FMOD_HARDWARE, soundExInfo, ppSound1);
result = FMOD_Sound_GetNumSubSounds(ppSound1.get(), pSubSounds);
try {
Pointer<Integer> pChanelPlaying = allocateInt();
for (int k = 0; k < pSubSounds.get(); k++) {
Pointer<Pointer<FMOD_SOUND>> ppSubSound = allocatePointer(FMOD_SOUND.class);
result = FMOD_Sound_GetSubSound(ppSound1.get(), k, ppSubSound);
result = FMOD_System_PlaySound(ppSystem.get(), FMOD_CHANNELINDEX.FMOD_CHANNEL_FREE, ppSubSound.get(), 0, ppChannel);
FMOD_Channel_IsPlaying(ppChannel.get(), pChanelPlaying);
while (ppChannel.getBoolean()) {
log.info("Playing...");
Thread.sleep(1000);
FMOD_Channel_IsPlaying(ppChannel.get(), pChanelPlaying);
}
result = FMOD_Sound_Release(ppSubSound.get());
}
result = FMOD_System_Close(ppSystem.get());
result = FMOD_System_Release(ppSystem.get());
} catch (Exception e) {
log.error(getStackTraceAsString(getRootCause(e)));
}
log.info(format("Finished... %s", result));
}
}
package net.unsongstories.fmodex;
导入net.unsungstories.fmodex.FmodexLibrary.FMOD_频道;
导入net.unsongstories.fmodex.FmodexLibrary.FMOD_声音;
导入net.unsungstories.fmodex.FmodexLibrary.FMOD_系统;
导入org.apache.log4j.Logger;
导入org.bridj.IntValuedEnum;
导入org.bridj.Platform;
导入org.bridj.Pointer;
导入org.junit.Test;
导入静态org.bridj.Pointer.*;
导入静态net.unsongstories.fmodex.FmodexLibrary.*;
导入静态com.google.common.base.Throwables.*;
导入静态java.lang.String.format;
公共类播放声音{
私有静态最终记录器log=Logger.getLogger(PlaySound.class);
@试验
公共空间播放声音(){
log.info(“测试已启动…”);
String soundPath=“/src/test/resources/picus_get_to_finicular_music_0.fsb”;
Platform.addEmbeddedLibraryResourceRoot(“net/unsungstories/fmodex/”);
内在价值结果;
指针ppSystem=allocatePointer(FMOD_SYSTEM.class);
指针ppSound1=allocatePointer(FMOD_SOUND.class);
指针pSubSounds=allocateInt();
指针ppChannel=allocatePointer(FMOD_CHANNEL.class);
@抑制警告(“未选中”)
指针soundExInfo=Pointer.NULL;
指针targetSoundPath=allocateBytes(soundPath.length()+1);
targetSoundPath.setCString(声音路径);
结果=FMOD_系统_创建(ppSystem);
结果=FMOD_System_Init(ppSystem.get(),2,FmodexLibrary.FMOD_Init_NORMAL,Pointer.NULL);
结果=FMOD_System_CreateSound(ppSystem.get(),targetSoundPath,FMOD_硬件,soundExInfo,ppSound1);
结果=FMOD_Sound_GetNumSubSounds(ppSound1.get(),pSubSounds);
试一试{
指针pChanelPlaying=allocateInt();
for(int k=0;k
希望这有帮助。hmmm。。。我真的不知道如何使用这个。你能给我看看你的概念证明吗?那太棒了!哇,这看起来比我最初想象的要复杂得多。我还是一个编程新手(2年了),我真的不知道该怎么做。如果我现在听起来很愚蠢,我很抱歉,但我想我现在会放弃这个,继续我所得到和理解的。但真的很感谢你的帮助,伙计!