Define an End position, but with a fade out

Started by Couin,

Couin

Hi friends :)

I would add a feature to define an end position (BASS_POS_END would be great for this), but with a fade out.

I plan to use a timer where I read the playback position and once a previoulsy defined end point reached, I call a fade out Call BASS_ChannelSlideAttribute(stream, BASS_ATTRIB_VOL | BASS_SLIDE_LOG, -1, FadeOutDuration)But it requires some programming.
I searched through documentataion but not found, is existing something that combinating both features?

Something like Call BASS_ChannelSetPosition(stream, EndPosistion, BASS_POS_END | BASS_ATTRIB_VOL | BASS_SLIDE_LOG, -1,FadeOutDuration)
Thanks :D



David_AVD

Why not set a callback using BASS_ChannelSetSync so you can trigger the fade at the desired position?

Ian @ un4seen

Yes, as David suggests, you could use a sync (BASS_SYNC_POS) to trigger the fade-out. Something like this:

BASS_ChannelSetSync(stream, BASS_SYNC_POS, EndPosistion, FadeOutSync, 0); // set sync to trigger fade-out
...
void CALLBACK FadeOutSync(HSYNC handle, DWORD channel, DWORD data, void *user)
{
BASS_ChannelSlideAttribute(channel, BASS_ATTRIB_VOL | BASS_SLIDE_LOG, -1, FadeOutDuration); // fade-out and stop the stream
}

Couin

Hi,

Thanks for idea :)

I tried to adapt to VB6 (I know you are not familiar with VB6 ^^ ) and using it in BassTest example.
If I understand well, BASS_ChannelSetSync should trigger a function (here, FadeOutSync) at EndPosition (in samples)?
If yes, I probably miss something, because the the function is called directly.

On the "Play" button of BassTest example:
' Play the stream (continue from current position)
Private Sub cmdStreamPlay_Click()
    If (lstStream.ListIndex >= 0) Then
        If (BASS_ChannelPlay(lstStream.ItemData(lstStream.ListIndex), BASSFALSE) = 0) Then
            Call Error_("Can't play stream")
        Else
            Timer1.Enabled = True
            Dim chan As Long
            chan = lstStream.ItemData(lstStream.ListIndex)
            Call BASS_ChannelSetSync(chan, BASS_SYNC_POS, BASS_ChannelSeconds2Bytes(chan, 3), pocpoc, 0) ' set sync to trigger fade-out
        End If
    End If
End Sub

and a "pocpoc" function to test the triggering:
Private Function pocpoc()
    Debug.Print "POCPOC"
End Function

Result: when I click on "Play", "POCPOC" appears directly in the console window, not after 3 seconds.

David_AVD

Don't call the callback yourself. Set the BASS_ChannelSetSync to do it for you at the right time.

Create the stream.
Set up the callback using BASS_ChannelSetSync.
Start playback.

At the chosen position, Bass will call your callback function for you.

Check the "CustLoop" example for VB in the Bass download.

Couin

Hi David,

Thanks for precisions :)

I'm not at home now but I'll have a look to CustLoop.

I should change code for something like:
' Play the stream (continue from current position)
Private Sub cmdStreamPlay_Click()
    If (lstStream.ListIndex >= 0) Then
        Dim chan As Long
        chan = lstStream.ItemData(lstStream.ListIndex)
        Call BASS_ChannelSetSync(chan, BASS_SYNC_POS, BASS_ChannelSeconds2Bytes(chan, 3), pocpoc, 0) ' set sync to trigger fade-out
        If (BASS_ChannelPlay(chan, BASSFALSE) = 0) Then Call Error_("Can't play stream")
    End If
End Sub
Right?

David_AVD

I don't know VB at all sorry.

BASS_ChannelSetSync is designed to return a handle to the event when successful.

https://www.un4seen.com/doc/#bass/BASS_ChannelSetSync.html

Couin

I really have difficulties to understand how setsync works :(

I tried to re-use some code from CustLoop in BassTest, but I get "Invalid use of AddressOf operator" error...
After some search, AddressOf is usable only in a module, so I moved in a new module, I no longer have error but LoopSyncProc is never triggered :(

Ian @ un4seen

I'm not a VB6 user myself, but I think a VB6 version of the C/C++ snippet I posted would look like this:

Call BASS_ChannelSetSync(stream, BASS_SYNC_POS, EndPosistion, AddressOf FadeOutSync, 0) ' set sync to trigger fade-out
...
Public Sub FadeOutSync(ByVal handle As Long, ByVal channel As Long, ByVal data As Long, ByVal user As Long)
Call BASS_ChannelSlideAttribute(channel, BASS_ATTRIB_VOL Or BASS_SLIDE_LOG, -1, FadeOutDuration) ' fade-out and stop the stream
End Sub

Callbacks can be dodgy in VB6 because VB6 doesn't really support multi-threading, but I think they'll usually be OK if you stick to using BASS or Win32 functions (not VB functions) in them. I'm not sure whether "Debug.Print" is OK - try removing that if you get a crash.

Couin

Hi Ian,

Thanks :)

I moved some code from Form to a module and I can get some wanted result.

In the module:
Public Sub play()
    stream = frmBassTest.lstStream.ItemData(frmBassTest.lstStream.ListIndex)
    Call BASS_ChannelPlay(stream, BASSFALSE)
    Call BASS_ChannelSetSync(stream, BASS_SYNC_POS, BASS_ChannelSeconds2Bytes(stream, 2), AddressOf FadeOutSync, 0) ' set sync to trigger fade-out
End Sub

Public Sub FadeOutSync(ByVal handle As Long, ByVal channel As Long, ByVal data As Long, ByVal user As Long)
    Call BASS_ChannelSlideAttribute(channel, BASS_ATTRIB_VOL Or BASS_SLIDE_LOG, -1, 2000) ' fade-out and stop the stream
End Sub

and I call "play" from the command button.

Thanks :)

Ian @ un4seen

Good to hear there's progress :)

If that "play" function may be called multiple times on the same stream then you should check if the sync has already been set (eg. by retaining the returned sync handle) to avoid having multiple syncs, or if that'll complicate things too much then you could just add the BASS_SYNC_ONETIME flag to the BASS_ChannelSetSync call. The BASS_ChannelSetSync call should also come before the BASS_ChannelPlay call, to avoid any chance of playback/decoding going past the sync position before the sync is set.

Couin

Hi,

I plan to define the fadeout point after the stream create, and eventually redifine it by moving a fader, so I should ne define it on each play.

Ian @ un4seen

If you may need to change the sync position, then you would need to retain the sync handle returned by BASS_ChannelSetSync so that you can later call BASS_ChannelRemoveSync on it before setting another sync at the new position (and replace the retained handle with that one so that you can do the same again if necessary).

Couin


Couin

Hi,

With somes tests, I see that FadeOutSync is called at definied position only when I play the sound and when the defined position is reached. I though it was called at BASS_ChannelSetSync, so when (in the final project) I set the position point where to fadeout (without playing).

My problem now is that the stream is from an array of 120 possible streams, and each stream can have a different FadeOut position and FadeOutCurve (LOG or not) from the others:

Public JID As Integer
Public Type JingCheck
    ...
    FadeOut As Long
    FadeOutCurve As Long
    Strm As Long
    ...
End Type
Public Jing(119) As JingCheck

Public Sub FadeOutSync(ByVal Handle As Long, ByVal channel As Long, ByVal Data As Long, ByVal User As Long)
    Call BASS_ChannelSlideAttribute(channel, Jing(JID).FadeOutCurve, -1, Jing(JID).FadeOut)
End Sub
Where "JID" is the number of sound (from 0 to 119) that I edit (to set the fadeout point), but not when I play the sound in normal use.

If I add a loop to find the JID from the channel, I can get the JID value of playing sound.Public Sub FadeOutSync(ByVal Handle As Long, ByVal channel As Long, ByVal Data As Long, ByVal User As Long)

    Dim uu As Integer
    For uu = 0 To 120
        If uu = 120 Then GoTo uunotfound
        If Jing(uu).Strm = channel Then GoTo uufound
    Next uu
uufound:
    Call BASS_ChannelSlideAttribute(channel, Jing(uu).FadeOutCurve, -1, Jing(uu).FadeOut) ' fade-out and stop the stream
uunotfound:
    Exit Sub

End Sub
But perhaps is there a easier/cleaner method ?