I have been looking for the best way to mix audio tracks with B4x for quite a while. Java basically provides a number of methods which I have tried. The audio Clip class allows skipping through the track, but it does not allow access to the raw byte data necessary to perform audio mixing. Then AudioInputStream (and related classes) do allow access to the raw byte so mixing can be performed, but it does not allow moving to any other positions in the track easily.
I came up with the idea of creating a WavRandomAccessFile class, which is basically a RandomAccessFile that is wav audio aware. It gets the all important AudioFormat from the file and parses the Wav header to find the start and end of the audio 'data' chunk. This is important as wav files can contain many different chunks, and the data chunk is not necessarily at the end of the file.
The WavRandomAccessFile class can be found in jAudioTrack2 v1.2+. There is also a B4xLib version which doesn't rely on JavaxSound so should be cross platrofm.
This example app provides 2 code modules that do the mixing of the audio files. TrackMixer_G mixes the tracks on the Gui thread and as you can see from the image below, can mix quite a few tracks. I have not found it's limit, but if you know anything about digital audio, you will know that the audio buffer size is very important. TrackMixer_T mixes the tracks on a separate thread. This allows the same performance with a lower buffer size or potentially more tracks. The choice is up to you, if you are only mixing a few tracks and the responsiveness is not an issue then basing your mixer on TrackMixer_G will be more than adequate, and you won't need the Threading Library. If you are mixing in the background when other things are going on, then base your mixer on TrackMixer_T to provide the best performance.
They are named as they are so that you can do a global replace on the names in the app to switch between the two methods. I have not provided a b4xlib with either of them as it would be a lot more work, and creating a complex app requires more classes to do things specific to your requirements. Feel free to copy the Mixer code and use it as you need.
Demo App
The JAudioTrack2-Mixer-Full demo app gives an example of creating a mixer with classes that manage the Gui for each track. It is complex by necessity. I have also created a simple mixer example with no Gui posted separately.
Both mixer classes require the audio to be 16bit stereo files. A utility app FFMpegConvert that will convert a folder of wav files to the required format is attached. A Sample Rate of 44100 is recommended as most sound cards can process at that rate. You may be able to use other sample rates if your sound card and Java supports them. You will need to download and set up FFMPeg if you haven't already (https://ffmpeg.org/) and point the converter at the ffmpeg.exe.
Depends On
Try it out
Limitations
Caveat
This is not for the faint hearted. Audio programming is a complex topic, although the code that does the mixing is only a few lines long there are many things that have to be just right for it to work.
How well it works will also depend on the speed of your PC. It is unlikely to provide good performance on older slow PC's. Mine is a 3 year old i5-7400 3.00Ghz. definitely not high spec and anything approaching that should be fine. If you're not sure, just try it.
Enjoy and let me know how you get on with it.
I came up with the idea of creating a WavRandomAccessFile class, which is basically a RandomAccessFile that is wav audio aware. It gets the all important AudioFormat from the file and parses the Wav header to find the start and end of the audio 'data' chunk. This is important as wav files can contain many different chunks, and the data chunk is not necessarily at the end of the file.
The WavRandomAccessFile class can be found in jAudioTrack2 v1.2+. There is also a B4xLib version which doesn't rely on JavaxSound so should be cross platrofm.
This example app provides 2 code modules that do the mixing of the audio files. TrackMixer_G mixes the tracks on the Gui thread and as you can see from the image below, can mix quite a few tracks. I have not found it's limit, but if you know anything about digital audio, you will know that the audio buffer size is very important. TrackMixer_T mixes the tracks on a separate thread. This allows the same performance with a lower buffer size or potentially more tracks. The choice is up to you, if you are only mixing a few tracks and the responsiveness is not an issue then basing your mixer on TrackMixer_G will be more than adequate, and you won't need the Threading Library. If you are mixing in the background when other things are going on, then base your mixer on TrackMixer_T to provide the best performance.
They are named as they are so that you can do a global replace on the names in the app to switch between the two methods. I have not provided a b4xlib with either of them as it would be a lot more work, and creating a complex app requires more classes to do things specific to your requirements. Feel free to copy the Mixer code and use it as you need.
Demo App
The JAudioTrack2-Mixer-Full demo app gives an example of creating a mixer with classes that manage the Gui for each track. It is complex by necessity. I have also created a simple mixer example with no Gui posted separately.
Both mixer classes require the audio to be 16bit stereo files. A utility app FFMpegConvert that will convert a folder of wav files to the required format is attached. A Sample Rate of 44100 is recommended as most sound cards can process at that rate. You may be able to use other sample rates if your sound card and Java supports them. You will need to download and set up FFMPeg if you haven't already (https://ffmpeg.org/) and point the converter at the ffmpeg.exe.
Depends On
- jAudioTrack2 V0.12+
- DragDrop2-b4xlib (attached) It may be slightly different from Erels b4xlib, so download this one. It won't cause any conflicts as it is named differently.
- Threading
- ByteConverter (Internal)
- jDateUtils (Internal)
- jRandomaccessFile (Internal)
- jXUI and XUI Views (Internal)
- JavaObject (internal)
Try it out
To play tracks in the demo app, drag a folder of wav files (44100 16bit stereo files) onto the Label in between the Folder label and the open folder button, or press the open folder button and load the folder.
There are two folders with tracks available on my google drive for you to try it out. one with 3 Tracks (my creation) and one with 15 which was downloaded from Then Mixing Secrets and converted with the attached FFMpegconvert utility. Download either or both, unzip then and drag or open the folder. These folders are too large to include within the app so unfortunately you will have to download them separately.
Limitations
- The demo app only plays on the default output device, it is complex enough as it is for a demo. Changing outputs can easily be accomplished with the JAudioTrackLibrary which is required for the mixer.
- There are no effects to add to the tracks. That would require a whole new project on it's own.
- Files should be 16bit Stereo and preferably 44100hz sample rate. It may work with other sample rates if Java and your soundcard support them.
Caveat
This is not for the faint hearted. Audio programming is a complex topic, although the code that does the mixing is only a few lines long there are many things that have to be just right for it to work.
How well it works will also depend on the speed of your PC. It is unlikely to provide good performance on older slow PC's. Mine is a 3 year old i5-7400 3.00Ghz. definitely not high spec and anything approaching that should be fine. If you're not sure, just try it.
Enjoy and let me know how you get on with it.
Attachments
Last edited: