Probleme with BASS_Mixer_StreamAddChannel

Started by Phil75,

Phil75

@Falcosoft Thanks for the reply.

in the plugin's info dialog, "Program data are handled in formatless chunks" is listed.
"VSTHost" creates a ".FXP" file with a rather large header, probably data it adds to the "Chunk" it takes from the VST.
But it contains the same XML data as with "BASS_VST_GetChunk".
I could save all the VST Parameter values, unfortunately it handles an external file name.
And this external file name appears in the "Chunk" returned by "BASS_VST_GetChunk".
Usually I change the file name, and I send the Bytes array with "BASS_VST_SetChunk",
but with this VST it does not work. Even if I send the same "Chunk".

Capture1.png

kafffee

Sry to interrupt but I started reading this thread out of curiosity...:

What would be the difference between loading audio data with .StreamCreateFile (the overload that streams from memory) and .SampleLoad?

Greetings, kafffee :-)

Ian @ un4seen

Quote from: kafffeeWhat would be the difference between loading audio data with .StreamCreateFile (the overload that streams from memory) and .SampleLoad?

The big difference is that BASS_SampleLoad pre-decodes the entire file to memory, while BASS_StreamCreateFile doesn't. BASS_SampleLoad = decoded sample data in memory, BASS_StreamCreateFile(mem=true) = encoded file in memory. Samples and streams also have other different features, eg. samples can be played multiple times simultaneously, while streams can have syncs and DSP applied. BASS_SampleGetChannel with BASS_SAMCHAN_STREAM can be used to combine the features of both.

Falcosoft

#23
Quote from: Phil75@Falcosoft Thanks for the reply.

in the plugin's info dialog, "Program data are handled in formatless chunks" is listed.
"VSTHost" creates a ".FXP" file with a rather large header, probably data it adds to the "Chunk" it takes from the VST.
But it contains the same XML data as with "BASS_VST_GetChunk".
I could save all the VST Parameter values, unfortunately it handles an external file name.
And this external file name appears in the "Chunk" returned by "BASS_VST_GetChunk".
Usually I change the file name, and I send the Bytes array with "BASS_VST_SetChunk",
but with this VST it does not work. Even if I send the same "Chunk".

Capture1.png

Hi,
I have checked this EasyConvolver.dll plugin and it is buggy in multiple ways:

1. It can only load saved settings before the plugin editor and processing is activated. You can check this even in VSTHost. Once the plugin is fully loaded the 'Plugin menu -> Load bank' option has no effect.

2. You can only change the 'DryWet' parameter's value from the GUI. The DryWet VST parameter reflects the value that is set from the GUI but not the other way around. That is setting the parameter's value programatically during runtime has no effect on either the GUI or the audio processing.
(This bug can also be tested with VSTHost by opening the 'Edit Parameters' dialog and changing the value of the DryWet parameter.)

3. Bass_VST_SetChunk() call is actually successfull somewhat even when it is called during in active state of the plugin in the sense it sets the DryWet VST parameter's value properly but because of bug 2. it has no effect either on the GUI or audio processing.

4. Bass_VST_Setchunk() calls dispatcher with effSetChunk parameter internally. This call should return the bytes accepted/processed by the plugin. But in case of this plugin the call always returns 0 so you cannot determine if the call was successful or not.


Overall Bass_VST_SetChunk() works well, the problems are caused by the quirks of the plugin.

Phil75

Hello,
you are definitely right. I hadn't checked all these details. Thanks for taking the time to check all this out. I'll look for a better convolution VST plugin.

kafffee

@Ian

Okay, that's a good thing, so far I have just used .StreamCreateFile for my jingles.

What would be the best thing to start a track's (not a sample) playback, though, with least possible latency? I've experienced a little delay on slow computers when I start playback. Would you pick the overload that loads the stream into memory first or the one that plays directly from the file? Respectively any other guesses to accelerate that?

Ian @ un4seen

Quote from: kafffeeWhat would be the best thing to start a track's (not a sample) playback, though, with least possible latency? I've experienced a little delay on slow computers when I start playback. Would you pick the overload that loads the stream into memory first or the one that plays directly from the file? Respectively any other guesses to accelerate that?

If you're creating the stream some time in advance (ie. there's a delay between the BASS_StreamCreateFile and BASS_ChannelPlay/Start calls) then you could also call BASS_ChannelUpdate in advance so that there's some decoded data ready to play immediately. Note BASS_ChannelUpdate is only applicable when using normal BASS playback (eg. not through a mixer).

kafffee

@Ian

Okay, I am using a mixer. So what would you recommend? The overload that loads the file into memory and then plays back or the one that plays back directly from the file?

What about this BASS_ASYNCFILE flag? It sounds like a good idea... Do I have to consider anything when using that?

Ian @ un4seen

How much of a delay are you getting when you start playback, and is it every time or only sometimes? Is there less delay when not using a mixer? When playing through a mixer, the mixer's playback buffer will add latency, but you can disable that via the BASS_ATTRIB_BUFFER setting:

BASS_ChannelSetAttribute(mixer, BASS_ATTRIB_BUFFER, 0); // disable playback buffering

You can give the BASS_ASYNCFILE option a try (on the source streams) to see if it helps. It's mostly helpful for files on slow storage media.

Phil75

Hello  :)

Finally the solution of adding "Thread.Sleep(50)" to remove the "Clicks" does not work.
Additionally, it adds a noticeable delay when playing the piano.
I tried something else.

I add the Sample this way by specifying "Max = 1" :

hSampleTest = Bass.BASS_SampleLoad("D:\Sample.wav", 0, 0, 1, BASSFlag.BASS_DEFAULT Or BASSFlag.BASS_SAMPLE_FLOAT)
Then I use a Button to do the test (normally I use the data that comes from the Midi input. "NoteOn" and "NoteOff").

Instead of retriggering the Sample with "BASS_ChannelSetPosition" with the previously stored Channel Handle, I tried to do this:

Private Sub Button1_MouseDown(sender As Object, e As MouseEventArgs) Handles Button1.MouseDown

hChannelTest = Bass.BASS_SampleGetChannel(hSampleTest, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMCHAN_STREAM)
BassMix.BASS_Mixer_StreamAddChannel(hMixer, hChannelTest, BASSFlag.BASS_DEFAULT)

End Sub

Private Sub Button1_MouseUp(sender As Object, e As MouseEventArgs) Handles Button1.MouseUp

Bass.BASS_ChannelSlideAttribute(hChannelTest, BASSAttribute.BASS_ATTRIB_VOL, 0F, 1000.0F)

End Sub

and it seems to be working fine. There are no more "Clicks" and the sound gradually stops.

But I noticed, by regularly consulting "BassMix.BASS_Mixer_StreamGetChannelCount(hMixer)",
that the number of hChannels increased with each "click" on the button.

If I add the function "BASS_Mixer_Channel Remove(hChannelTest)", obviously the sound stops abruptly.

Bass.BASS_ChannelSlideAttribute(hChannelTest, BASSAttribute.BASS_ATTRIB_VOL, 0F, 1000.0F)
BassMix.BASS_Mixer_ChannelRemove(hChannelTest)

Is there a solution to my problem?

Phil75

I added a timer with this code and it seems to work. But I don't know if it will be enough :

        Dim ListChannels() As Integer
        Dim i As Short

        ListChannels = BassMix.BASS_Mixer_StreamGetChannels(hMixer)

        For i = 0 To ListChannels.Length - 1
            Select Case BassMix.BASS_Mixer_ChannelIsActive(ListChannels(i))
                Case BASSActive.BASS_ACTIVE_PAUSED, BASSActive.BASS_ACTIVE_STALLED, BASSActive.BASS_ACTIVE_STOPPED
                    BassMix.BASS_Mixer_ChannelRemove(ListChannels(i))
            End Select
        Next i

Ian @ un4seen

The issue there is that each BASS_SampleGetChannel(BASS_SAMCHAN_STREAM) call is creating a new stream, and they aren't being freed. To fix that, try including the BASS_STREAM_AUTOFREE flag in the BASS_Mixer_StreamAddChannel call and using value=-1 in the BASS_ChannelSlideAttribute(BASS_ATTRIB_VOL) call, so that the source ends after fading-out and then gets freed:

Private Sub Button1_MouseDown(sender As Object, e As MouseEventArgs) Handles Button1.MouseDown
hChannelTest = Bass.BASS_SampleGetChannel(hSampleTest, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMCHAN_STREAM)
BassMix.BASS_Mixer_StreamAddChannel(hMixer, hChannelTest, BASSFlag.BASS_STREAM_AUTOFREE) ' auto-free source
End Sub

Private Sub Button1_MouseUp(sender As Object, e As MouseEventArgs) Handles Button1.MouseUp
Bass.BASS_ChannelSlideAttribute(hChannelTest, BASSAttribute.BASS_ATTRIB_VOL, -1, 1000.0F) ' fade-out and end
End Sub

Phil75

@Ian Thanks for the reply.

But if I add "BASSFlag.BASS_STREAM_AUTOFREE", hChannel = 0

hChannel = Bass.BASS_SampleGetChannel(hSample, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMCHAN_STREAM Or BASSFlag.BASS_STREAM_AUTOFREE)
BASS_ErrorGetCode = BASS_ERROR_NOTAVAIL "The BASS_STREAM_AUTOFREE flag cannot be combined with the BASS_STREAM_DECODE flag"

If i remove BASSFlag.BASS_STREAM_DECODE, BASS_Mixer_StreamAddChannel return False

BassMix.BASS_Mixer_StreamAddChannel(hMixer, hChannel, BASSFlag.BASS_DEFAULT Or BASSFlag.BASS_MIXER_CHAN_PAUSE)

Phil75

Sorry, I added "BASS_STREAM_AUTOFREE" in "BASS_SampleGetChannel" instead of "BASS_Mixer_StreamAddChannel"  ;D

Everything works very well  :)