Using/Reading FMOD (.fsb) Files in Java - java

Heyo Everyone. I am currently working on an Application which should play music files from an FMOD Database. It currently does it by Extracting the files (using a runtime and an external programm called "fsbextract.exe" (link)) as MP3 and then playing them. I am okay with this as it is, but i would now also love to edit/replace the files within the .fsb file. So my question is: Can i somehow directly acces the MP3 files in there without extracting them? I searched the internet for something like this but couldn't find any help.
For reference, here are some informations i can get from within fsbextract:
FileID is |FSB4> | Version is 4.0 | Number of Entries 7412
Global Flags:
0x40 | FMOD_FSB_SOURCE_MPEG_PADDED4 | MPEG frames are aligned to the nearest 4 bytes, 16 bytes for multichannel (Use Frame Verification option)
And from the first (index 0) file within the fsb file:
Format: MP3 (85)
Sample rate: 44100Hz
Channels: Mono
Duration: 01.541
Bitrate: 160,62 kbit/s
Bits/Sample 3.64
Sample Mode Flags [0x10000200]
0x200 | FSOUND_MPEG | Sample is stored in MPEG format
0x10000000 | FSOUND_MPEG_LAYER3 | Samples are stored in MPEG Layer 3 format
I hope someone knows more than me, but thanks in advance
Marenthyu

Jérôme Jouvie wrote a JNI wrapper for FMOD 4+, NativeFmodEx. If your FSB files are not encrypted I think you can use the API to extract streaming data from the FSB banks.
I tried to write my own wrapper as well but I didn't have the time to get past a simple proof of concept.
UPDATE: Sure. So basically what I did was to use JNAerator to wrap the native FMODex libraries and then targeting the resulting glue code to the BridJ runtime environment. That essentially allows you to invoke the native FMOD C library.
I'm not exactly sure if Jerome did something similar or if he created his own JNI stubs to achieve the same result. You'd have to check out and read his project's code.
But essentially, once you're able to make FMOD calls inside your application, you can use the API to do as you please. If you download the latest FMOD studio or FMODex SDK's from the FMOD web site you'll find a help .chm file which contains some documentation for the API.
You should also take a look at the examples in the SDK.
The following code is basically one example translated into Java, using the above mentioned strategy. The code isn't portable, robust or actually useful for an application. It really needs cleanup yet it still illustrates the point.
Like I said, you should be much better off using Jerome's SDK port.
Hope it helps.
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));
}
}
Hope this helps.

Related

How to execute Python codes from Java code in Android Studio?

I am building an Android application in Android studio with Java. I want to use Speech to text and Text to speech and some Machine Learning based python programs that I had already written.
Is it possible to do this? What is the technology stack that I need to accomplish this?
I came across various solutions like using sl4A, Jython, QPython and running the python code on the server.I have also gone through the following but I haven't found a solution yet
Execute python script from android App in Java
How to execute Python script from Java code in Android
Execute python script from android App in Java
Please explain with an example. As an example if I want to use the following python code (Speech to Text conversion using Google Speech recognition API) to run in my android app:
import speech_recognition as sr
r = sr.Recognizer()
with sr.Microphone() as src:
print("speak....")
audio = r.listen(src, 2)
print("over")
try:
print("you said: "+r.recognize_google(audio))
except:
print("cannot recognize")
What steps am I supposed to follow? What is the best way to achieve it?
Thank you in advance.
EDIT 1: Can it be achieved using azure services?
I've been using JEP as a bridge between java and python, I've never actually tried this on android apps, only webapps. (in the FAQS of the project they state that it could work)
private RunOutputModel run(RunInputModel model, String path) throws Exception {
RunOutputModel retVal = new RunOutputModel();
try (SharedInterpreter jep = new SharedInterpreter()) {
jep.eval("import sys");
jep.eval("sys.path.append('" + path + "')");
jep.eval("import master_main");
jep.set("well", model.getWell());
jep.set("startDate", model.getStartDate());
jep.set("endDate", model.getEndDate());
//other vars
jep.eval("objClass = master_main.master()");
jep.eval("x = objClass.main(path, well, startDate, endDate,/*vars*/)");
Object result1 = jep.getValue("x");
//manager result
}
} catch (Exception e) {
retVal.setStatus(e.getMessage());
Utils.log("error", e.getMessage(), path);
}
return retVal;
}
And here's python:
class master:
def __init__(self):
self.SETVARIABLES = ''
def main(self, path, well, startDate, endDate):
#stuff
By searching I've found this, they even have project examples of mixed source code app (both python and java).

How to crash my OS programatically?

Have written a Java code which sends mail when whole system RAM reaches > 95%.
I want to write a Java code to test this scenario. Have written few(recursive etc...), but those are crashing the JVM but not System.
Any help please ?
UN_ORTHODOX SOLUTION but it works anyway
NOTE! I Used WINDOWS 8.1 host machine
I found this DOC on myself too! in old days; about JVM and host system access issues. I used this code to get details about host system!
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
private static void printUsage() {
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
for (Method method : operatingSystemMXBean.getClass().getDeclaredMethods()) {
method.setAccessible(true);
if (method.getName().startsWith("get")
&& Modifier.isPublic(method.getModifiers())) {
Object value;
try {
value = method.invoke(operatingSystemMXBean);
} catch (Exception e) {
value = e;
} // try
System.out.println(method.getName() + " = " + value);
} // if
} // for
}
NOTE !
that's not the real way To do but I did it by opening the Default browser (in most of cases I know most of the time its GOOGLE CHROME) , had 8GB ram those days so opening a few tabs with some random youtube and other links it helped me to reach up the memory usage unto 90% in no time! because it eats the RAM (No offence to CHROME people!) doing that I was able to achieve the test you are trying to get. :-)
TO Open a default browser just take a look on this thread its quite nice with different ways to do it!
well if you are using it for android well read about proguard rules for memory management and try using any external library which takes up too much memory like any dummy faceRecog library or simply just accessing some NDK features or so check this link for more

Does JCODEC Support MPEG-TS or MPEG-PS

I am trying to be able to pick out frames (video and metadata) from MPEG, MPEG-TS and MPEG-PS files and live streams (network / UDP / RTP streams). I was looking into using JCODEC to do this and I started off by trying to use the FrameGrab / FrameGrab8Bit classes, and ran into an error that those formats are "temporarily unsupported". I looked into going back some commits to see if I could just use older code, but it looks like both of those files have had those formats "temporarily unsupported" since 2013 / 2015, respectively.
I then tried to plug things back into the FrameGrab8Bit class by putting in the below code...
public static FrameGrab8Bit createFrameGrab8Bit(SeekableByteChannel in) throws IOException, JCodecException {
...
SeekableDemuxerTrack videoTrack = null;
...
case MPEG_PS:
MPSDemuxer psd = new MPSDemuxer(in);
List tracks = psd.getVideoTracks();
videoTrack = (SeekableDemuxerTrack)tracks.get(0);
break;
case MPEG_TS:
in.setPosition(0);
MTSDemuxer tsd = new MTSDemuxer(in);
ReadableByteChannel program = tsd.getProgram(481);
MPSDemuxer ptsd = new MPSDemuxer(program);
List<MPEGDemuxerTrack> tstracks = ptsd.getVideoTracks();
MPEGDemuxerTrack muxtrack = tstracks.get(0);
videoTrack = (SeekableDemuxerTrack)tstracks.get(0);
break;
...
but I ran into a packet header assertion failure in the MTSDemuxer.java class in the parsePacket function:
public static MTSPacket parsePacket(ByteBuffer buffer) {
int marker = buffer.get() & 0xff;
int marker = by & 0xff;
Assert.assertEquals(0x47, marker);
...
I found that when I reset the position of the seekable byte channel (i.e.: in.setPosition(0)) the code makes it past the assert, but then fails at videoTrack = (SeekableDemuxerTrack)tstracks.get(0) (tstracks.get(0) cannot be converted to a SeekableDemuxerTrack)
Am I waisting my time? Are these formats supported somewhere in the library and I am just not able to find them?
Also, after going around in the code and making quick test applications, it seems like all you get out of the demuxers are video frames. Is there no way to get the metadata frames associated with the video frames?
For reference, I am using the test files from: http://samples.ffmpeg.org/MPEG2/mpegts-klv/
In case anyone in the future also has this question. I got a response from a developer on the project's GitHub page to this question. Response:
Yeah, MPEG TS is not supported to the extent MP4 is. You can't really seek in TS streams (unless you index the entire stream before hand).
I also asked about how to implement the feature. I thought that it could be done by reworking the MTSDemuxer class to be built off of the SeekableDemuxerTrack so that things would be compatible with the FrameGrab8Bit class, and got the following response:
So it doesn't look like there's much sense to implement TS demuxer on top of SeekableDemuxerTrack. We haven't given much attention to TS demuxer actually, so any input is very welcome.
I think this (building the MTSDemuxer class off of the SeekableDemuxerTrack interface) would work for files (since you have everything already there). But without fully fleshing out that thought, I could not say for sure (it definitely makes sense that this solution would not work for a live MPEG-TS / PS connection).

Program that uses jpbc takes a long time

This is a very simple program I have written that uses jpbc library.
It compiles without any errors, but takes an unusually long time to show the output, or in fact it doesn't show the output at all. (Who in this era will have the patience to wait for nearly half an hour for such a tiny program?) I am using a system with i7 processor but still this is the case.
Could anyone tell what might be wrong with this code?
import it.unisa.dia.gas.jpbc.*;
import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory;
import it.unisa.dia.gas.plaf.jpbc.pairing.parameters.*;
import it.unisa.dia.gas.jpbc.PairingParametersGenerator;
import it.unisa.dia.gas.jpbc.PairingParameters;
import it.unisa.dia.gas.plaf.jpbc.pairing.a1.TypeA1CurveGenerator;
public class PairingDemo {
public static void main(String [] args){
try{
int rBits = 160;
int qBits = 512;
PairingParametersGenerator pg = new TypeA1CurveGenerator(rBits, qBits);
PairingParameters params = pg.generate();
Pairing pair = PairingFactory.getPairing("D:\\JPBCLib\\params\\curves\\a1.Properties");
Field Zr = pair.getZr();
int degree = pair.getDegree();
System.out.println("Degree of the pairing : " + degree);
}catch(Exception e){
e.printStackTrace();
}
}
}
There are three issues that you're dealing with here
Generating the pairing parameters takes some time, but this only has to be done once for a system that you're building. You should store the generated pairing parameter for later use.
Since you're not using pg or params, you can remove that code. Instead you're reading precomputed parameters from a file.
jPBC is a complete and pure Java implementation of PBC. It is fully portable and therefore quite slow. jPBC has an option of using a PBCWrapper library which is a wrapper around libpbc which would enable you to get the performance of the native library. I wasn't able to make it work on Windows, but Linux should not be an issue (make sure to check the JNI version or load your own).

Editing SWF files using Transform SWF for Java from Flagstone

Has anyone successfully used the Transform SWF for Java library from [Flagstone Software][1]
[1]: http://www.flagstonesoftware.com/transform/index.html to edit an existing swf file. Mainly what I want to accomplish is load a swf file and replace images or texts dynamically. Thank you.
I know it is a little bit late, but google searchers will still land here :-) This code will color the first text span of all text elements to red.
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.zip.DataFormatException;
import com.flagstone.transform.Movie;
import com.flagstone.transform.MovieTag;
import com.flagstone.transform.datatype.Color;
import com.flagstone.transform.text.DefineText;
public class Flash {
public static void main(String args[]) throws MalformedURLException, DataFormatException, IOException {
Movie m = new Movie();
m.decodeFromFile(new File("C:\\tmp\\Movie.swf"));
for (MovieTag mt : m.getObjects()) {
System.out.println(mt.getClass() + " " + mt.toString());
if (mt instanceof DefineText) {
((DefineText) mt).getSpans().get(0).setColor(new Color(255, 0, 0));
}
}
m.encodeToFile(new File("C:\\tmp\\foo.swf"));
}
}
Yes, I am working on a desktop application that generates swf files. It is a little tricky but the samples in the Cookbook will help you a lot. Just go through the samples and you will find almost anything that you need.One thing is that, the developer stopped working on the framwork but it still works fine. Transform library only supports Flash 10 and Translate supports ActionScript 1.0. I had to change the ActionScript 2 and 3 code to AS1 for the framework to work which was for me to only replace the variable types when declaring variables.

Categories