Author Topic: BASS_StreamCreate using Delphi + FFmpeg + BASS  (Read 160 times)

tacoban

  • Posts: 4
Hi,

I have been exprerimenting FFmpeg libraries + SDL2 library  using Delphi for audio and video output(playing).

Currently since few days I am trying to use BSS library for audio output but I am stuck at some point. It seems BASS is a powerfull library for playing files like mp3 etc.

But I my point is not to let BASS play (radio)streams or (aduio)files. I am trying to play audio samples got from FFmpeg libraries which I am able to play using SDL2 library.

I am using the following construct:

initialize;
BASS_Init(-1, freq, 0, WindowHandleToPlatform(wHandle).Wnd, nil) //frequency retrieved from FFmpeg's format context

create a streamhandle;
StreamHandle  := BASS_StreamCreate(freq,  channels, 0, strmproc, Self);//I assume using "0" -> sample format s16 ?
BASS_ChannelPlay(StreamHandle, false);

in the callback "strmproc" I get audio "frames" from FFmpeg libraries, try to convert them to sample format s16 and put in the buffer;
 move(audio_buf^, buf^, c);
 Result := c;

This way I get some noisy audio, I don't know how to fix.
Is this the converted frame or something else ? Or can somebody give a small example ? 

Ian @ un4seen

  • Administrator
  • Posts: 23288
Re: BASS_StreamCreate using Delphi + FFmpeg + BASS
« Reply #1 on: 6 Jan '21 - 14:06 »
What sample format is the FFmpeg library producing? If you just hear noise then it could be there's a mismatch between that and what BASS is expecting. If FFmpeg is producing floating-point data then you can use the BASS_SAMPLE_FLOAT flag in your BASS_StreamCreate call and avoid the need for "s16" conversion.

One thing to note is that the STREAMPROC function deals in bytes rather than frames, so you will need to convert the "length" parameter accordingly and then convert back for the return value. For example:

Code: [Select]
DWORD CALLBACK MyStreamProc(HSTREAM handle, void *buffer, DWORD length, void *user)
{
DWORD bytesperframe = 2 * sizeof(float); // assuming stereo float
DWORD frames = length / bytesperframe;
...
return frames * bytesperframe
}

tacoban

  • Posts: 4
Re: BASS_StreamCreate using Delphi + FFmpeg + BASS
« Reply #2 on: 9 Jan '21 - 23:41 »
I allmost got it working.

when I fill the buffer less then length param and send the result I get very noisy sound.
When I keep filling the buffer until it gets the size of length, then I get better audio but there is a little noise in it. This can be something with decoding or converting.

About FFmpeg sample format, I did not check yet wat it is by default but I need to convert the audio sample(s) from a Frame because of the source can have more speaker output then destination like my laptop has 2 speakers and a movie can have 6 (5.1)

However I'd like to fill the buffer partially and play like I am able with SDL2 because I need to sync the audio together with video. This is probably possible by choosing for a smaller buffer size but I will check why I get that small noise. It seems like this noise happens by refilling the buffer.

David_AVD

  • Posts: 36
Re: BASS_StreamCreate using Delphi + FFmpeg + BASS
« Reply #3 on: 10 Jan '21 - 09:08 »
I think you can tell FFmpeg to decode as stereo only?

tacoban

  • Posts: 4
Re: BASS_StreamCreate using Delphi + FFmpeg + BASS
« Reply #4 on: 10 Jan '21 - 18:01 »
FFmpeg is a very powerful opensource library which is able to decode almost any type of audio or video. 
As I checked it is decoding audio by default to Sample format FLTP which is equal to BASS_SAMPLE_FLOAT.
Almost any conversion to any format (video or audio) is possible, but the problem with FFmpeg is the documentation.

FFmpeg is decoding the audio to the same count channels as the source by default. After decoding u need to convert it according to the destination. Converting is again done by FFmpeg using some functions.

In my current working code, the sound is playing twice faster as normal. I need to understand why this is and this is probably one of  the reasons for the noise.

In this case another problem seems like that I need a little bit more knowledge about audio manipulation.
« Last Edit: 10 Jan '21 - 18:29 by tacoban »

David_AVD

  • Posts: 36
Re: BASS_StreamCreate using Delphi + FFmpeg + BASS
« Reply #5 on: 10 Jan '21 - 21:13 »
I'm currently using the FFVCL components to play video with Bass audio, but that doesn't really help you.

I looked at using FFmpeg directly but haven't wrapped my head around how to do that yet.

tacoban

  • Posts: 4
Re: BASS_StreamCreate using Delphi + FFmpeg + BASS
« Reply #6 on: 11 Jan '21 - 02:54 »
About FFVCL, it's doing about exact the same as what I am doing on my own. If u can work directly with FFmpeg libraries, u are able to do more than u are able with FFVCL.

If you look at the source of FFPlay.exe/FFmpeg.exe of FFmeg, it's not too hard but in first case also not easy to understand to decode audio/video or convert a video format to another.  The problem is that those source codes are in C/C++ and the documentation of FFmpeg.
We need to convert a lot from C source to Delphi source.

I have no problems on windows using FFmpeg + SDL2 coding in Delphi. My point is to create an app for Android and it seems that SDL2 + Delphi for android is a problem.

BASS can be loaded from Android without problems using Delphi created application but at the moment I need som experience with BASS. Sepcially with streaming from decoded samples from FFmpeg libraries.
As I mentioned before, I think it's not BASS but decoding en converting is the point because I need to understand some points which I will research.

Ian @ un4seen

  • Administrator
  • Posts: 23288
Re: BASS_StreamCreate using Delphi + FFmpeg + BASS
« Reply #7 on: 11 Jan '21 - 13:45 »
BASS will accept multi-channel data even if there aren't that many speakers available, so you could just set the BASS_StreamCreate "chans" parameter to the value from FFmpeg without having to do any conversion yourself. BASS will discard any extra channels (you won't hear them). If you would like to downmix them instead (eg. convert 5.1 to stereo) then you could use the BASSmix add-on to do that. For example, something like this:

Code: [Select]
mixer = BASS_Mixer_StreamCreate(freq, 2, BASS_MIXER_END); // create a stereo mixer with same sample rate as the source
BASS_Mixer_StreamAddChannel(mixer, source, BASS_MIXER_DOWNMIX); // plug in the source with downmixing enabled
BASS_ChannelPlay(mixer, 0); // start it

"source" would be the handle from your BASS_StreamCreate call. You would also need to add the BASS_STREAM_DECODE flag to that call. Please see the BASSmix documentation for details on the mentioned functions.