B4J Library [B4j] jAudioRecord2

This is an new version of the jAudioRecord library (but not a direct plugin replacement) provided as a b4xlib and uses current B4x practices and classes.

It allows selection of audio inputs and capturing directly to file or to a byte array so you can process the data further.

1659623984359.png

The library no longer relies on the threading library.

The CaptureRaw class uses B4xBytesBuilder from theB4xCollections library.

Demo
  • jAudioRecord2-Demo
    • Demonstrates the full functionality of the library and enumerates and allows selecting the input device and capturing directly to a file or to a byte array (which is subsequently written to a file in the demo, but doesn't have to be).
    • Contains CaptureMethod class which is a parent class to the CaptureRaw, CaptureToFile, CaptureRaw_TH and CaptureToFile_TH classes and uses duck typing to enable switching between the classes within the app. If you only want to use one method, you can just use the class you want directly.
  • For an example of recording and playing see the jAudioRecAndPlay demo in jAudioTrack2 library.
  • jAudiorecordNonUI
    • An example for a non-ui app. Just records for 10 seconds and then exits the application. You will need to provide the start/stop recording controls as appropriate to your app.

CaptureRaw vs CaptureToFile
The method GetBuffer is only relevant to the CaptureRaw class, a zero length byte array is returned from the CaptureToFile class as it does not buffer the data and is therefore more memory efficient.

B4xlib
The jAudioRecord2 b4xlib contains the code and some necessary utilities. Feel free to unzip and inspect or change it as you wish.

Dependencies
Updates
V0.11

  • Added sub GetDevices and related Constants to JAudioRecordUtils
V0.12 - 2023-10-13
Added Threaded classes (now depends on the Threading library. The threaded classes cannot be used in debug mode)​
Demo contains the source code​
Removed dependency on Xui for use in Non-ui apps.​

Comments
There are as many device configurations as there are PC's. It does work with mine and I have an external sound card as well as an internal sound card, Whether java supports all devices will remain to be seen.

Please bear in mind that the demo and B4xlib provides all of the capabilities for the library. For your code, you can pick which classes you want to use. If you don't want to use the threaded classes you can copy only the classes you want to your project (or build a b4xlib) and remove the dependency on the threading library.

Please try it and let me know how you get on and report any issues.
 

Attachments

  • jAudioRecord2-Demo.zip
    18.7 KB · Views: 101
  • jAudiorecordNonUI.zip
    1.5 KB · Views: 94
  • jAudioRecord2-b4xlib.b4xlib
    13.3 KB · Views: 111
Last edited:

stevel05

Expert
Licensed User
Longtime User
Update to V0.11
  • Added sub GetDevices and related Constants to JAudioRecordUtils
 

Jmu5667

Well-Known Member
Licensed User
Longtime User
Nice Job Steve, was waiting for the update to allow for the selection of input/output devices.
 

max123

Well-Known Member
Licensed User
Longtime User
Nice work !
 

peacemaker

Expert
Licensed User
Longtime User
Super, thanks !
Is it lib for Windows OS only ? Not for Linux ?
 

stevel05

Expert
Licensed User
Longtime User
Is it lib for Windows OS only ? Not for Linux ?
No. I don't think there are any reasons it shouldn't work on Mac and Linux as well. I haven't tried it though. Let me know if there are issues.
 

stevel05

Expert
Licensed User
Longtime User
Is this plugin/update compatible with JDK19?
I haven't tried it, but I can't see why it wouldn't be unless the API has changed.
 

m4.s

Member
Licensed User
Longtime User
Hi @stevel05,

Fantastic library - thank you for developing and sharing!

I'm using my laptop's 'Stereo Mix' device, and [MP4 video] speaker output is being successfully captured (as desired/required). However, its sound quality on playback is somewhat choppy and occasionally disrupted; the volume is also much lower than when recorded.

I use the default parameter values below for the NewAudioFormat method:

B4X:
    Private SampleRateHz As Float = 44100
    Private SampleSizeInBits As Int = 16
    Private ChannelConfig As Int = 2
   
    'Create an Audioformat Instance
    AudioFormat = jAudioRecord2_Utils.NewAudioFormat(SampleRateHz,SampleSizeInBits,ChannelConfig, True, False)

Can you please explain these params in more detail, and advise possible alternative values for them which might improve captured sound quality?

NOTE: I forgot to mention that my B4J (GUI) application is using MediaPlayer to play the MP4 video, and I'm concurrently capturing all its main form user activity while recording the speaker sound. I just read in another related posting that it may be necessary for me to use your jAudioRecord (v1) library, which inherently supports threading (albeit via some dependency jars) - correct, or no?
 
Last edited:

stevel05

Expert
Licensed User
Longtime User
@m4.s

The choppy recording is probably caused by using media player at the same time. The threaded version should stop / reduce that. There may well be a recording input gain on your sound card, check the soundcard setup to address the volume issue.

The parameters you listed are the default for a standard audio file. There is a lot of information available on the internet, you could start here. Bearing in mind that reducing any of the parameters will reduce the overall quality of the sound. Java AudioRecord only works with PCM samples, and not compressed data.

You can try a threaded version of jAudioTrack2 posted here
 

m4.s

Member
Licensed User
Longtime User
Thanks @stevel05!

Your threaded version of jAudioTrack2 works perfectly for me (I compiled your project files to a new local library, since I could not find one from you); it seems you could support the threaded flag in a single library with only minor code changes.
 

stevel05

Expert
Licensed User
Longtime User
I compiled your project files to a new local library, since I could not find one from you
I was waiting for some feedback on the implementation to see if it was working for those that requested it. I will update the jAudiotrack2 thread with a b4xlib now that you have confirmed it is working.
 

stevel05

Expert
Licensed User
Longtime User
Update to V0.12
Added Threaded classes (now depends on the Threading library. The threaded classes cannot be used in debug mode)
Demo contains the source code
Removed dependency on Xui for use in Non-ui apps.
 
Last edited:

m4.s

Member
Licensed User
Longtime User
Hi again @stevel05,

I've found a bug in your threading-related jAudioRecord2 code only when a B4J project is compiled in 'Release (obfuscated)' mode, right when audio recording is started, resulting in this exception error:

1698373766794.png


Per my forum research, it appears to be related to a missing underscore (_) character in the invoked method name within the CaptureToFile_TH module.

Not sure if there's additional methods within your library module code which might similarly fail.
 

m4.s

Member
Licensed User
Longtime User
And @stevel05 I also have just a question:

Do you know of any way to concurrently capture both PC speaker output (such as, again, when an MP4 video file is playing) and PC microphone input (as voice over)? I've not been able to accomplish that regardless of whether capturing to file or in raw memory, using my Primary Sound Capture and Stereo Mix drivers. I can only capture either PC speaker output -or- PC microphone input (using my Microphone Array driver), i.e. separately.
 

stevel05

Expert
Licensed User
Longtime User
threading-related jAudioRecord2 code
While I can see why this could happen, the library is one big demo. You should not really be using the library as is and should choose which module(s) you need and incorporate it into your project directly, or create a cut down library. It is unlikely that you would want more than one capture method in a project. The CaptureMethod module uses Duck Typing to be able to call any of the methods for recording, which is where it could also fail in obfuscated mode and is included for demo purposes.
 

stevel05

Expert
Licensed User
Longtime User
concurrently capture both
To do this properly, you would need to capture both input devices in separate instances of the recording method and to separate files (or arrays) and use an audio mixer to mix the two either in realtime if using arrays, or on playback if saving to files.

As a hack, if your soundcard allows the microphone to be passed directly to the speaker output, you could then capture the speaker output which would include the microphone audio. Getting the level right in this scenario would need some experimentation.
 

stevel05

Expert
Licensed User
Longtime User
P.S. It is sufficient to delete (or comment out) the relevant lines of code.
The attached project demonstrates all possible scenarios. If you don't want to have the threading library selected, you would need to copy the classes excluding the threaded classes to your project, or create a second library and exclude the threaded classes.

The non threaded library runs all the code on the Gui thread, so it may or may not work depending on the speed or your hardware and what else it and your program are doing at the time.

I would advise you to use the standard library first, until you are certain that the non threaded version will work adequately so you can easily switch between the two. Working with audio can be hit and miss, it can run on some computers, but not others. If it is for your own use and used in a controlled manner i.e. not much else running on the PC at the time, then you may get away with the non threaded versions. If it is for release, then it is probably wisest to use the threaded versions as it would be more likely to be compatible with older and slower hardware.
 
Top