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

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 ?

Couin

Hi friends :)

I had to suspend development due to a lot of work outside of this project, but I was able to resume it.

I know you are not familiar with VB6 but perhaps you could have a small idea of where my problem comes from.

My VB6 IDE is on a Win10 machine. I compiled the exe program, and when I run it on a previous version of Windows (so 2000 to 8.1), BASS_ChannelSetSync makes often exe crash ("Program has encountered a problem and need to close." message, and the sound stuttering until I close the advert) or directly close (I got this on Win 8.1) when the FadeOutSync position is reached.

I tried to stop all timers of the project, in case of conflict somewhere, but without result.

Of course, I'm trying to reproduce on a simpler project, with for example 6 buttons to play 6 audio files, but I get no crash with this test project.
The test project has not FX integration yet.

On Win 10 it's OK.

I have no idea of where to search more for the moment :(



Couin

Hi,

The suit of my research, I added a button to the project, to add a new channel without FX and I got the same problem.

I took my test project, I added a mixer and a splitter like I have in the main project, no problem, no crash.

So it should be something in main project thant interfering with BASS when I use BASS_ChannelSetSync, but I don't know what, as well as I have no error :(
BASS, BASS_FX, BASS_MIXER and SPLIT looks not be the problem.
Timers (where I pick playback position of each streams, for one timer, where I pick the splitted ouput level, for the second timer), when I disable them (and all other timers too, to prevent of calling something else that could make disturbing), I still get the problem. So Timers should not be the problem too.

Ian @ un4seen

What does your sync callback (SYNCPROC) function look like now? To check whether the crash is caused by something in there, does the crash still happen if you empty the function? For example:

Public Sub FadeOutSync(ByVal Handle As Long, ByVal channel As Long, ByVal Data As Long, ByVal User As Long)
End Sub

Couin

Hi Ian :)

For testings, I removed the "uu" loop that I use to find the ID in "jing" array (where fade out curve and duration are memorized) from the channel value, and I put fixed values.

So it gives:
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, 500) ' fade-out and stop the stream
End Sub

I also tested with empty FadeOutSync sub but crashes still happen.

But not in the VB6 IDE, only with compiled exe .

Ian @ un4seen

If you upload a dump file from the crash, I'll see if I can spot anything in that. You will hopefully find a dump file in the "%LOCALAPPDATA%\CrashDumps" folder, which you can then ZIP and upload here:

    ftp://ftp.un4seen.com/incoming/

Please use this latest BASS.DLL build when producing the crash and dump file:

    www.un4seen.com/stuff/bass.zip

Couin

Hi Ian,

I have to check on a VM, if there is a CrashDumps folder on Windows 8, because there is not on XP.

Also, I still continue to looking to target the problem, it looks disappear if I revert from mixer/splitter method (cf. another of my topics, where the goal was to send all streams to a mixer to merge them, and split the mixer output, to send two strams, for two audio devices), to classic mode (with default soundcard).

Couin

Hi,

I think I spotted the origin of my problem :)

I you look this schematic https://www.un4seen.com/forum/?action=dlattach;attach=4599;image , you can see I split the (left) Mixer output to send to 2 devices. In fact, these devices are also mixers (to add splitted Microphone).

I noticed that the problem happens  if I do no use the auxiliarry output (so I BASS_Init device 0). But as well as I already have to BASS_Init device 0, before creating "Mixer", it comes to initialize two times the device 0. Perhaps it makes a loop or sharing problem somewhere?

I changed some code so if aux device is 0, just no initialize the (0) device.

This looks solving the problem (no crash from Win 2K to Win 8.1).