B4J Question Inline Java class with sub return question

Douglas Farias

Expert
Licensed User
Longtime User
Hello everybody.
I have a question about inline java and classes.


In summary.
I need to make an app in B4J that listens to the microphone so I can use it with the VOSK right after.

The objective is to listen to the microphone with inline java and pass the stream to b4j.

However, I am experiencing some errors when trying.


B4X:
Sub Inicia_Java
    Dim thisClass As String = (Me).As(JavaObject).RunMethod("getClass",Null)
    jo.InitializeNewInstance(thisClass.Replace("class ","") & "$" & "AudioCapture",Null)
    StartRecording
End Sub


Sub StartRecording
    jo.RunMethod("startRecording", Null)
End Sub

Sub StopRecording
    jo.RunMethod("stopRecording", Null)
End Sub



#if java
import javax.sound.sampled.*;
import java.io.ByteArrayOutputStream;

public class AudioCapture {

    public AudioCapture() {
        // inicialização necessária
    }
   
    private TargetDataLine line;
    private boolean running = false;

    public void startRecording() {
        try {
            AudioFormat format = new AudioFormat(16000, 16, 1, true, false);
            DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
            if (!AudioSystem.isLineSupported(info)) {
                subQvEvent("logs", "Line not supported");
                return;
            }

            line = (TargetDataLine) AudioSystem.getLine(info);
            line.open(format);
            line.start();
            running = true;

            new Thread(() -> {
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                while (running) {
                    int numRead = line.read(buffer, 0, buffer.length);
                    if (numRead > 0) {
                        out.write(buffer, 0, numRead);
                    }
                }
                line.drain();
                line.close();
                subQvEvent("audio_data", out.toByteArray());
            }).start();
        } catch (LineUnavailableException e) {
            subQvEvent("logs", "Line unavailable: " + e.getMessage());
        }
    }

    public void stopRecording() {
        running = false;
    }

    private void subQvEvent(String eventName, Object data) {
        getBA().raiseEventFromDifferentThread(null, null, 0, eventName.toLowerCase() + "_qv", true, new Object[]{data});
    }
}
#end if


Sub audio_data(data() As Byte)
    Log("Received audio data of length: " & data.Length)
End Sub

Sub logs(message As String)
    Log(message)
End Sub


Error



if I try to use static.



How can I use inline java, have classes in java and at the same time be able to return values to subs in b4j

Obs: I know that there are already recording libraries in b4j, but this question is about inline java/class and subs.


Thx
 

jkhazraji

Active Member
Licensed User
Longtime User
raiseEventFromDifferentThread doesn't return a value as it happens asynchronously.
Try BA.raiseEvent()
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
threads don't return anything, but callables do. try things this way.
 

Attachments

  • farias.zip
    2.8 KB · Views: 104
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
by the way, what you originally posted can work. with a few modifications. i can initialize your class and get raiseevent to work. go over it carefully if you still want to use the original approach.
 

Attachments

  • farias2.zip
    2.7 KB · Views: 111
Upvote 0

Douglas Farias

Expert
Licensed User
Longtime User
by the way, what you originally posted can work. with a few modifications. i can initialize your class and get raiseevent to work. go over it carefully if you still want to use the original approach.
Thank you very much, you gave me a way.

posted here

thx
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…