Author Topic: BASS for Android  (Read 746210 times)

Alpinador

  • Posts: 3
Re: BASS for Android
« Reply #1900 on: 2 Jan '22 - 14:23 »
yeah Ian, i understand Rad Studio not much on your line but im ensure you could have it in mind cos its great C++ environment

but yes, i make the Radio player in Windows app and no problems, you have 1st add the Bass.LIB from Bass.dll in the proyect and then it works and recognize the functions but seem android libraries are a bit different

anyway im going to look what people recommend me or if somebody trick with Rad Studio C++ Builder version and give me some class of idea

Thanks Chris!!! im going to deal with that example.....could have some help for im searching.....thanks pal

Thanks, great library :)

crossinu

  • Posts: 7
Re: BASS for Android
« Reply #1901 on: 9 Jan '22 - 12:24 »
Hello, there's apparently a bug caused by updating to the latest BASS library on certain devices where screen recording with internal audio break's the audio's speed as shown in this video. The device used in this video is a Redmi 9 with a Mediatek Helio G80 SOC.

Ian @ un4seen

  • Administrator
  • Posts: 24330
Re: BASS for Android
« Reply #1902 on: 10 Jan '22 - 12:45 »
I'm unfamiliar with what the app in the video should be sounding like, so it isn't entirely clear to me what's going wrong in that. Is the audio too fast or slow, or both at times? And is the problem in the app's playback or only in the recording? If it's in the app's playback that's affected, to perhaps narrow down the cause, please see if you can reproduce it with one of the examples from the BASS package. If the problem doesn't affect the BASS examples then please post your app's BASS_Init call and any CONFIG settings that you're using for comparison.

otherside

  • Posts: 57
Re: BASS for Android
« Reply #1903 on: 11 Jan '22 - 12:17 »
Hi. Can you please guide me on how to implement the following app:

1. Mix multiple streams into one. Some streams can have altered start/end time as well as being looped
2. Take this mixed stream and write it as a audio for a video on android using mediaMuxer.

Is it possible to accomplish with BASS? If yes, then could you please provide me with first steps on how to implement that.

Ian @ un4seen

  • Administrator
  • Posts: 24330
Re: BASS for Android
« Reply #1904 on: 11 Jan '22 - 17:24 »
The mixing part can be done with the BASSmix add-on, but I've never used MediaMuxer myself so I'm not sure about that part. If you just need the mixed data in a ByteBuffer then you can get that by calling BASS_ChannelGetData on the mixer. Note that the BASS_STREAM_DECODE flag should be set on the mixer to enable processing the mix with BASS_ChannelGetData. Please see the BASS_Mixer_StreamCreate and BASS_ChannelGetData documentation for details on them.

otherside

  • Posts: 57
Re: BASS for Android
« Reply #1905 on: 1 Feb '22 - 17:36 »
The mixing part can be done with the BASSmix add-on, but I've never used MediaMuxer myself so I'm not sure about that part. If you just need the mixed data in a ByteBuffer then you can get that by calling BASS_ChannelGetData on the mixer. Note that the BASS_STREAM_DECODE flag should be set on the mixer to enable processing the mix with BASS_ChannelGetData. Please see the BASS_Mixer_StreamCreate and BASS_ChannelGetData documentation for details on them.

Thanks. I am still struggling with the one part: how to get looping of a track inside of a mixer?
Imagine:
The final recording duration should be 12 seconds.

I have a user picked track which can be at any length. Then user selects a part of the track that is 4 seconds and enables loop mode.

What I want to archieve is to record that selected piece 3 times sequentially into one file. (because it is looped and 3 times = 12 total / 4 seconds of a track)
Is it possible to archieve with bass?


« Last Edit: 1 Feb '22 - 18:34 by otherside »

Ian @ un4seen

  • Administrator
  • Posts: 24330
Re: BASS for Android
« Reply #1906 on: 2 Feb '22 - 16:23 »
You can set the BASS_SAMPLE_LOOP flag on the source to enable looping, and use the BASS_POS_LOOP and BASS_POS_END options with BASS_ChannelSetPosition to set the loop start/end positions. Then set a BASS_SYNC_END sync on the source via BASS_ChannelSetSync, which will be triggered at the end of each loop. You can count the loops in the SYNCPROC function and remove the BASS_SAMPLE_LOOP flag from the source with BASS_ChannelFlags (to stop it looping) when it reaches the wanted number. Please see the documentation for details on the mentioned functions and options.

otherside

  • Posts: 57
Re: BASS for Android
« Reply #1907 on: 3 Feb '22 - 14:16 »
You can set the BASS_SAMPLE_LOOP flag on the source to enable looping, and use the BASS_POS_LOOP and BASS_POS_END options with BASS_ChannelSetPosition to set the loop start/end positions. Then set a BASS_SYNC_END sync on the source via BASS_ChannelSetSync, which will be triggered at the end of each loop. You can count the loops in the SYNCPROC function and remove the BASS_SAMPLE_LOOP flag from the source with BASS_ChannelFlags (to stop it looping) when it reaches the wanted number. Please see the documentation for details on the mentioned functions and options.

Thanks for the answer - it works great! I have only one remaining question. My goal is to make the audio part of the video. Right now I record data with BASSEnc addon to a wav file and then process it with MediaCodec - decoder + encoder.
Is it possible to take data from ChannelGetData and put into MediaCodec? I tried it, but I got only noise, seems like they in different audio formats. Below is the code of how I did it and it didnít work out

Code: [Select]
override fun writeToBuffer(inputBuffer: ByteBuffer): MediaCodec.BufferInfo {
        if (nextBufferEndOfStream) {
            return bufferInfo.setEndOfStream()
        }

        val c = BASS.BASS_ChannelGetData(
            mixChan,
            inputBuffer,
            BASS.BASS_DATA_FFT512
        )

        if (c == -1 || c == 0) {
            return bufferInfo.setEndOfStream()
        }

        writtenLength += c

        val currentPositionSec = BASS.BASS_ChannelBytes2Seconds(mixChan, writtenLength)
        val currentTimeUs = (currentPositionSec * 1000000).toLong()

        if (currentTimeUs > audioData.totalDurationUs) {
            nextBufferEndOfStream = true
        }
        bufferInfo.size = c
        bufferInfo.offset = 0
        bufferInfo.presentationTimeUs = currentTimeUs
        bufferInfo.flags = 0

        return bufferInfo
    }

Ian @ un4seen

  • Administrator
  • Posts: 24330
Re: BASS for Android
« Reply #1908 on: 3 Feb '22 - 18:03 »
I don't think you should be using the BASS_DATA_FFT512 flag in the BASS_ChannelGetData call, as that will give you FFT data rather than PCM sample data. You should probably use inputBuffer.capacity() there instead.

otherside

  • Posts: 57
Re: BASS for Android
« Reply #1909 on: 4 Feb '22 - 09:22 »
I don't think you should be using the BASS_DATA_FFT512 flag in the BASS_ChannelGetData call, as that will give you FFT data rather than PCM sample data. You should probably use inputBuffer.capacity() there instead.

Thanks for help. This little detail has changed everything.

rrhh_fx

  • Posts: 32
Re: BASS for Android
« Reply #1910 on: 12 May '22 - 09:27 »
I am trying to get the global level of multiple streams playing simultaneously. When trying to use BASS_GetVolume(), always return -1, and BASS_ERROR_NOTAVAIL is obtained.

Is ther another way to get the global/master voiume or any suggestions to make BASS_GetVolume() work properly?

Ian @ un4seen

  • Administrator
  • Posts: 24330
Re: BASS for Android
« Reply #1911 on: 12 May '22 - 15:32 »
It sounds like you want to get the level of the sound rather than a volume control? BASS_SetVolume/GetVolume (when available) provides the latter. One way you can get the level of the BASS output is to set a level-measuring DSP function on the output mix stream. For example, something like this:

Code: [Select]
int mixstream; // output mix stream
float mixlevel; // current level

BASS.DSPPROC MeasureLevel = new BASS.DSPPROC() {
public void DSPPROC(int handle, int channel, ByteBuffer buffer, int length, Object user) {
buffer.order(null); // little-endian
FloatBuffer ibuffer = buffer.asFloatBuffer();
float[] d = new float[length / 4]; // allocate array for data
ibuffer.get(d); // copy data from buffer to array
float level = 0;
for (int a = 0; a < length / 4; a++) {
if (level < Math.abs(d[a])) level = Math.abs(d[a]);
}
mixlevel = level;
}
};

mixstream = BASS.BASS_StreamCreate(0, 0, 0, BASS.STREAMPROC_DEVICE, null); // get output mix stream
BASS.BASS_ChannelSetDSP(mixstream, MeasureLevel, null, 0); // set level measuring DSP on it

rrhh_fx

  • Posts: 32
Re: BASS for Android
« Reply #1912 on: 16 May '22 - 08:54 »
It sounds like you want to get the level of the sound rather than a volume control? BASS_SetVolume/GetVolume (when available) provides the latter. One way you can get the level of the BASS output is to set a level-measuring DSP function on the output mix stream. For example, something like this:

Code: [Select]
int mixstream; // output mix stream
float mixlevel; // current level

BASS.DSPPROC MeasureLevel = new BASS.DSPPROC() {
public void DSPPROC(int handle, int channel, ByteBuffer buffer, int length, Object user) {
buffer.order(null); // little-endian
FloatBuffer ibuffer = buffer.asFloatBuffer();
float[] d = new float[length / 4]; // allocate array for data
ibuffer.get(d); // copy data from buffer to array
float level = 0;
for (int a = 0; a < length / 4; a++) {
if (level < Math.abs(d[a])) level = Math.abs(d[a]);
}
mixlevel = level;
}
};

mixstream = BASS.BASS_StreamCreate(0, 0, 0, BASS.STREAMPROC_DEVICE, null); // get output mix stream
BASS.BASS_ChannelSetDSP(mixstream, MeasureLevel, null, 0); // set level measuring DSP on it

That is exactly what I was trying to obtain. Regarding values of "mixlevel", how can they be interpreted? i.e. are they normalized from 0 to 1.0 and any higher value implies saturation?

Is there any way to get sepparated volume values for L-R channels in a stereo mix?

Thanks!

Ian @ un4seen

  • Administrator
  • Posts: 24330
Re: BASS for Android
« Reply #1913 on: 16 May '22 - 13:40 »
Regarding values of "mixlevel", how can they be interpreted? i.e. are they normalized from 0 to 1.0 and any higher value implies saturation?

Yes, that's correct.

Is there any way to get sepparated volume values for L-R channels in a stereo mix?

You can change "mixlevel" to a 2 element array and then check left and right sample values separately:

Code: [Select]
float[] level = { 0, 0 };
for (int a = 0; a < length / 4; a += 2) {
if (level[0] < Math.abs(d[a])) level[0] = Math.abs(d[a]); // left
if (level[1] < Math.abs(d[a + 1])) level[1] = Math.abs(d[a + 1]); // right
}
mixlevel[0] = level[0];
mixlevel[1] = level[1];

rrhh_fx

  • Posts: 32
Re: BASS for Android
« Reply #1914 on: 16 May '22 - 18:25 »
Regarding values of "mixlevel", how can they be interpreted? i.e. are they normalized from 0 to 1.0 and any higher value implies saturation?

Yes, that's correct.

Is there any way to get sepparated volume values for L-R channels in a stereo mix?

You can change "mixlevel" to a 2 element array and then check left and right sample values separately:

Code: [Select]
float[] level = { 0, 0 };
for (int a = 0; a < length / 4; a += 2) {
if (level[0] < Math.abs(d[a])) level[0] = Math.abs(d[a]); // left
if (level[1] < Math.abs(d[a + 1])) level[1] = Math.abs(d[a + 1]); // right
}
mixlevel[0] = level[0];
mixlevel[1] = level[1];

Thanks a lot, Ian
« Last Edit: 20 May '22 - 08:29 by rrhh_fx »

rrhh_fx

  • Posts: 32
Re: BASS for Android
« Reply #1915 on: 20 May '22 - 08:39 »
Hi again, 2 new questions  :):

1) When applying a Peaking EQ Affect by using "BASS_ChannelSetFX(handler, BASS_FX_BFX_PEAKEQ, 0);", I can change fGain in some bands in order to obtain output obviously saturated (what you hear), but values of mixlevel of your above example remain the same than before applying the equalization. Am I doing something wrong?

2) I am trying to obtain a waveform of a local MP3 file, but decimated (for example, obtaining data from each second). Something similar to this:

Code: [Select]
streamAmp= BASS_StreamCreateFile("file.mp3", 0, 0, BASS_STREAM_DECODE);
BASS.BASS_ChannelSetPosition(streamAmp, 0, BASS_POS_BYTE);
int currentSecond=0;
int bufLen=4000; //random quantity. It is obtained in another way
while (true)
        {
            long currentByte=BASS_ChannelGetPosition(streamAmp, BASS_POS_BYTE);
            BASS.BASS_ChannelSetPosition(streamAmp, BASS_ChannelSeconds2Bytes(streamAmp, j), BASS_POS_BYTE );
            int got = BASS.BASS_ChannelGetData(streamAmp, buffer, bufLen); // process the mixer
           
    //process data obtained
    //.....

    currentSecond++;

            if (got < 0) break;
        }

The problem here is that after using BASS_ChannelSetPosition, in debugging mode, BASS_ChannelGetPosition returns 0.
EDIT: In this last case, I have tried another MP3 and it works fine. Maybe the first one is not seekable?

Any help is appreciated
« Last Edit: 20 May '22 - 09:18 by rrhh_fx »

Ian @ un4seen

  • Administrator
  • Posts: 24330
Re: BASS for Android
« Reply #1916 on: 20 May '22 - 14:46 »
1) When applying a Peaking EQ Affect by using "BASS_ChannelSetFX(handler, BASS_FX_BFX_PEAKEQ, 0);", I can change fGain in some bands in order to obtain output obviously saturated (what you hear), but values of mixlevel of your above example remain the same than before applying the equalization. Am I doing something wrong?

If the stream isn't floating-point then its data will be clipped after the EQ, before it reaches the DSPPROC above. You can avoid that by making it floating-point (set BASS_SAMPLE_FLOAT).

The problem here is that after using BASS_ChannelSetPosition, in debugging mode, BASS_ChannelGetPosition returns 0.
EDIT: In this last case, I have tried another MP3 and it works fine. Maybe the first one is not seekable?

An MP3 file opened with BASS_StreamCreateFile will always be seekable, but perhaps the requested seek position is invalid, eg. beyond the end? What is the BASS_ChannelSetPosition return value?

By the way, you could perhaps use BASS_ChannelGetLevelEx as a simpler way to get a decimated waveform. It only gives an absolute peak (rather than positive and negative), so it won't be exactly the same but perhaps sufficient. If interested, you can find an example of doing this in the CUSTLOOP.C example (ScanPeaks function) included in the Windows and Linux BASS packages.

rrhh_fx

  • Posts: 32
Re: BASS for Android
« Reply #1917 on: 24 May '22 - 11:55 »
Sorry for the late response. I wanted to be sure to test everything properly.

If the stream isn't floating-point then its data will be clipped after the EQ, before it reaches the DSPPROC above. You can avoid that by making it floating-point (set BASS_SAMPLE_FLOAT).

There are multiple streams that are affected in mixlevel (some MIDI files, some MP3/OGG). When initialized I have included the BASS_SAMPLE_FLOAT and also in the mixlevel stream the flag is included, but it appears that nothing changes in the mixleve values. They keep in the same numbers than before the equalization.

This code is next to initilization of the proc with mixleve:

Code: [Select]
final float [] freq = {63, 150, 400, 1000, 2400, 15000};
 float [] gain = {5,  5,  5,   5,   5,   5};

streamEQ = BASS_ChannelSetFX(mixlevel , BASS_FX_BFX_PEAKEQ, 0);

// initialize EQ parameters
BASS_FX.BASS_BFX_PEAKEQ eqparam=new BASS_FX.BASS_BFX_PEAKEQ();
eqparam.fBandwidth = 1;
eqparam.lChannel = -1;

for (int band = 0; band < freq.length; band++) {
            eqparam.lBand = band;
            eqparam.fCenter = freq[band];
            eqparam.fGain = gain[band];
            BASS_FXSetParameters(streamEQ, eqparam);
}

An MP3 file opened with BASS_StreamCreateFile will always be seekable, but perhaps the requested seek position is invalid, eg. beyond the end? What is the BASS_ChannelSetPosition return value?

By the way, you could perhaps use BASS_ChannelGetLevelEx as a simpler way to get a decimated waveform. It only gives an absolute peak (rather than positive and negative), so it won't be exactly the same but perhaps sufficient. If interested, you can find an example of doing this in the CUSTLOOP.C example (ScanPeaks function) included in the Windows and Linux BASS packages.

The requested position should be valid (tested with step by step debugging) and the BASS_ChannelSetPosition returns true, but after that, you can check the current position and returns 0. It is strange, since even only decoding in my above code (not using BASS_ChannelSetPosition), the loop takes 10 times more than other MP3 with similar size. I can upload the file if you desire.

Regarding the CUSTLOOP.C it is very interesting and easy to understand. Thanks!

Ian @ un4seen

  • Administrator
  • Posts: 24330
Re: BASS for Android
« Reply #1918 on: 24 May '22 - 13:21 »
Code: [Select]
streamEQ = BASS_ChannelSetFX(mixlevel , BASS_FX_BFX_PEAKEQ, 0);

Is "mixlevel" the STREAMPROC_DEVICE stream, ie. the same stream as the level-measuring DSPPROC is on? If so, the EQ's "priority" value needs to be higher than the DSPPROC's to have it applied first, eg. you could use priority=1 in that BASS_ChannelSetFX call or priority=-1 in the BASS_ChannelSetDSP call.

The requested position should be valid (tested with step by step debugging) and the BASS_ChannelSetPosition returns true, but after that, you can check the current position and returns 0. It is strange, since even only decoding in my above code (not using BASS_ChannelSetPosition), the loop takes 10 times more than other MP3 with similar size. I can upload the file if you desire.

I guess it may be that BASS doesn't detect the file as MP3, so Android's decoder is used instead. You can check the stream's "ctype" value with BASS_ChannelGetInfo to confirm whether that's the case. If you upload the file here (or post a link), I'll have a look too:

   ftp.un4seen.com/incoming/

rrhh_fx

  • Posts: 32
Re: BASS for Android
« Reply #1919 on: 24 May '22 - 14:26 »
Is "mixlevel" the STREAMPROC_DEVICE stream, ie. the same stream as the level-measuring DSPPROC is on? If so, the EQ's "priority" value needs to be higher than the DSPPROC's to have it applied first, eg. you could use priority=1 in that BASS_ChannelSetFX call or priority=-1 in the BASS_ChannelSetDSP call.

Ohhh! My fault. I will test it. EDIT: Of course now it works :) Thx!

I guess it may be that BASS doesn't detect the file as MP3, so Android's decoder is used instead. You can check the stream's "ctype" value with BASS_ChannelGetInfo to confirm whether that's the case. If you upload the file here (or post a link), I'll have a look too:

   ftp.un4seen.com/incoming/

I'll take a look to the ctype value. In a few hours I will upload it to the FTP.

EDIT: not necessary to upload to FTP. Effectively, it was not decoded as MP3, but as BASS_CTYPE_STREAM_AM.

Thanks!
« Last Edit: 24 May '22 - 18:12 by rrhh_fx »

Ian @ un4seen

  • Administrator
  • Posts: 24330
Re: BASS for Android
« Reply #1920 on: 25 May '22 - 13:26 »
Yep, BASS_CTYPE_STREAM_AM means that an Android decoder is being used. You can use BASS_ChannelGetTags(BASS_TAG_AM_MIME) to find out what format it is. If it is MP3 then it probably has some junk at the start (before the MP3 data) that's preventing BASS detecting it. Raising the BASS_CONFIG_VERIFY setting (via BASS_SetConfig) will usually help in these cases.

johnbh3

  • Posts: 1
Re: BASS for Android
« Reply #1921 on: 26 May '22 - 03:47 »
Hi, On Android it compiles normally but when I click play it gives an error: Radio Cannot Be Started!

Android 32


1 : Library->Android->armeabi
   a : libbass.so
   b : libbass_aac.so   
   c : libbassflac.so
   Remote Path : library\lib\armeabi\
2 : Library->Android->x86
   a : libbass.so
   b : libbass_aac.so   
   c : libbassflac.so
   Remote Path : library\lib\x86\
3 : Library->Android->armeabi-v7a
   a : libbass.so
   b : libbass_aac.so   
   c : libbassflac.so
   Remote Path : library\lib\armeabi-v7a\

OK!



rrhh_fx

  • Posts: 32
Re: BASS for Android
« Reply #1922 on: 26 May '22 - 10:21 »
Yep, BASS_CTYPE_STREAM_AM means that an Android decoder is being used. You can use BASS_ChannelGetTags(BASS_TAG_AM_MIME) to find out what format it is. If it is MP3 then it probably has some junk at the start (before the MP3 data) that's preventing BASS detecting it. Raising the BASS_CONFIG_VERIFY setting (via BASS_SetConfig) will usually help in these cases.

In this case, BASS_TAG_AM_MIME reports audio/mp4a-latm, and I have tried the BASS_CONFIG_VERIFY with multiple amounts of data to scan, but I guess that it is impossible decode a MP4 file as a MP3 :). Thanks a lot for sharing your knowledge and your support!!
« Last Edit: 26 May '22 - 11:16 by rrhh_fx »