Author Topic: Remove mixer source channel from mixer and switch to another playback device  (Read 1166 times)

kafffee

  • Posts: 260
Hi there :-)

I have a little problem concerning the switching to another playback device.

I am playing my mixer source channel like this:

Code: [Select]
stream = Bass.BASS_StreamCreateFile(CurrentMP3Info.Filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN Or BASSFlag.BASS_STREAM_DECODE)
MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE Or BASSFlag.BASS_STREAM_DECODE)
BassMix.BASS_Mixer_StreamAddChannel(MainModule.mixer, MainModule.streamfx(WhichDeck - 1), BASSFlag.BASS_MIXER_NORAMPIN Or BASSFlag.BASS_STREAM_AUTOFREE Or BASSFlag.BASS_MIXER_BUFFER)

Now I want streamfx(WhichDeck - 1) to not play via the mixer anymore, but to hear over another playback device:

Code: [Select]
Public Sub SwitchToHeadPhones_Execute(obj As Object)
        Dim Position As Long = Bass.BASS_ChannelGetPosition(stream)
        Debug.WriteLine("Position: " & CStr(Position) & " Error: " & CStr(Bass.BASS_ErrorGetCode))
       
        BassMix.BASS_Mixer_ChannelRemove(MainModule.streamfx(WhichDeck - 1))
        Debug.WriteLine("ChannelRemove Error: " & CStr(Bass.BASS_ErrorGetCode))

        Bass.BASS_ChannelSetDevice(MainModule.streamfx(WhichDeck - 1), MainModule.HeadPhoneIndex)
        Debug.WriteLine("ChannelSetDevice Error: " & CStr(Bass.BASS_ErrorGetCode))

        Bass.BASS_ChannelSetPosition(stream, Position)
        Debug.WriteLine("ChannelSetPosition Error: " & CStr(Bass.BASS_ErrorGetCode))

        Bass.BASS_ChannelPlay(MainModule.streamfx(WhichDeck - 1), False)
        Debug.WriteLine("ChannelPlay Fehler: " & CStr(Bass.BASS_ErrorGetCode))

    End Sub

Unfortunately, I get error #5 (invalid handle) on ChannelSetDevice, ChannelSetPosition and ChannelPlay...

Anybody know what I am doing wrong or can give me a recoemmendation on how to do this better?

MB_SOFT

  • Posts: 495
Would not be much easy to change the device of the MainModule.mixer with BASS_ChannelSetDevice?


Ian @ un4seen

  • Administrator
  • Posts: 26015
Unfortunately, I get error #5 (invalid handle) on ChannelSetDevice, ChannelSetPosition and ChannelPlay...

Error code 5 (BASS_ERROR_HANDLE) indicates that the provided handle is invalid. I notice you're using BASS_STREAM_AUTOFREE in the BASS_Mixer_StreamAddChannel call, so perhaps it was freed due to that?

kafffee

  • Posts: 260
@MB_SOFT:
I want to keep the mixer playing on the same device, while one of the source channels is supposed to stop playing on the mixer and to play on another device instead.

Background is that I have two virtual "turntable racks" on my program which can be played as a mix, and on button click, one of the racks is supposed to be silent on the mixer and to be audible over headphone (which is connected over another Audio interface/soundcard). So this function is supposed to enable the User to pre-Listen to Audio tracks...

@Ian
OK I will check that. But the rest of the code should work?

kafffee

  • Posts: 260
Quote
I notice you're using BASS_STREAM_AUTOFREE in the BASS_Mixer_StreamAddChannel call, so perhaps it was freed due to that?

I removed that, still the same problem...

Ian @ un4seen

  • Administrator
  • Posts: 26015
What is the value of the "MainModule.streamfx(WhichDeck - 1)" variable in those failing calls, and how does that compare to the value that you set earlier? If they're the same, you could then try setting a BASS_SYNC_FREE sync on the handle (via BASS_ChannelSetSync) to find out if/when it's getting freed.

kafffee

  • Posts: 260
OK did that.

streamfx(WhichDeck - 1) is freed when calling ChannelSetDevice

Ian @ un4seen

  • Administrator
  • Posts: 26015
BASS_ChannelSetDevice won't free a stream itself. If the BASS_ERROR_HANDLE error is only happening after you call that then perhaps you're also subsequently calling BASS_Free on the new device? BASS_Free frees everything on the freed device.

kafffee

  • Posts: 260
No I don't have any BASS_Free calls in my entire application...

Did you notice I am working with two stream handles:

Code: [Select]
stream = Bass.BASS_StreamCreateFile(CurrentMP3Info.Filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN Or BASSFlag.BASS_STREAM_DECODE)
and

Code: [Select]
MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE Or BASSFlag.BASS_STREAM_DECODE)


Ian @ un4seen

  • Administrator
  • Posts: 26015
Which one are you getting the BASS_ERROR_HANDLE error on, or is it both? Check that the variable's value at that point is still the same value that you got back from BASS_StreamCreateFile or BASS_FX_TempoCreate, eg. log them and compare.

kafffee

  • Posts: 260
I am getting the error on both. And they still are the same as after StreamCreateFile/BASS_FX_TempoCreate (right before calling ChannelSetDevice).

This is so weird.

Before I was posting this issue I was playing around with this a little in order to fix it on my own. And at some point, I didnt have this invalid handle error, but the error "channel is a decoding channel". Unfortunately I cannot remember which constellation/setup it was...



Ian @ un4seen

  • Administrator
  • Posts: 26015
What is the return value from the BASS_ChannelSetDevice call? And if you call BASS_ChannelGetDevice immediately after, what return value do you get from that?

kafffee

  • Posts: 260
ChannelSetDevice returns False and ChannelGetDevice returns -1 (I tried to set it to device 5).

Ian @ un4seen

  • Administrator
  • Posts: 26015
That looks like the handle is already invalid at the BASS_ChannelSetDevice call then, which would mean the root of the problem is somewhere before that. To narrow it down, check the return values (for success or failure) from all prior calls on the handle too.

kafffee

  • Posts: 260
Do I understand right?

Right before I call ChannelSetDevice, I call ChannelGetPosition(stream) and BASS_Mixer_ChannelRemove(MainModule.streamfx(WhichDeck-1)

Either one returns success (error code 0).

So I figured it must have to do with the BASS_Mixer_ChannelRemove call.

In fact I have this in my code, to handle the event that occurs when a track ends:

Code: [Select]
SyncTrackEnd = New SYNCPROC(AddressOf WhenTrackEnds)
Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_END, 0, SyncTrackEnd, IntPtr.Zero)
...
Private Sub WhenTrackEnds(syncHandle As Integer, channel As Integer, data As Integer, user As IntPtr)
ThreadPool.QueueUserWorkItem((Sub(o)
                                          TrackEnded()
                                      End Sub))
End Sub
...
 Private Sub TrackEnded()
        IsPlaying = False
        Select Case Repeat
            Case Mode.DoNotRepeat
                If PlaylistIndex = Playlist.Count - 1 Then
                    Return
                Else
                    NextTrack_Execute(Nothing)
                End If
            Case Mode.PlaylistRepeat
                If PlaylistIndex = Playlist.Count - 1 Then
                    PlaylistIndex = 0
                Else
                    PlaylistIndex = PlaylistIndex + 1
                End If
                PlayNewTrack_Execute(Nothing)
            Case Mode.SongRepeat
                PlayNewTrack_Execute(Nothing)
        End Select
    End Sub

Public Sub PlayNewTrack_Execute(...)
...
Bass.BASS_ChannelStop(stream)
            BassMix.BASS_Mixer_ChannelRemove(MainModule.streamfx(WhichDeck - 1))
            If stream <> 0 Then Bass.BASS_StreamFree(stream)
...
If MainModule.streamfx(WhichDeck - 1) <> 0 Then Bass.BASS_StreamFree(MainModule.streamfx(WhichDeck - 1))
...
End Sub

So I assume that when I call BASS_Mixer_ChannelRemove(MainModule.streamfx(WhichDeck-1), this is being executed...
 I only want this to execute when a track ends playing on its own though of course, i.e. when the tracks playing position reaches its end... How can I do this?
« Last Edit: 20 Sep '22 - 14:16 by kafffee »

Ian @ un4seen

  • Administrator
  • Posts: 26015
Yes, BASS_Mixer_ChannelRemove will free the stream because you used the BASS_STREAM_AUTOFREE flag in the earlier BASS_Mixer_StreamAddChannel call. You can prevent that happening by first removing the BASS_STREAM_AUTOFREE flag via BASS_Mixer_ChannelFlags:

Code: [Select]
BASS_Mixer_ChannelFlags(handle, 0, BASS_STREAM_AUTOFREE); // unset BASS_STREAM_AUTOFREE

kafffee

  • Posts: 260
OK this works. But now I get error 38 - the channel is a decoding channel - when calling BASS_ChannelPlay(streamfx(WhichDeck - 1, False)).

This is how I initialize it:

Code: [Select]
MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE Or BASSFlag.BASS_STREAM_DECODE)
What do I have to change?

Chris

  • Posts: 2210
if you want to plug it into a Mixer then this
Code: [Select]
MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE Or BASSFlag.BASS_STREAM_DECODE) and you have to call
Code: [Select]
Bass_ChannelPlay(YourMixerhandle,False)
if you want to play directly then
Code: [Select]
MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE )
BASS_ChannelPlay(streamfx(WhichDeck - 1, False)).


kafffee

  • Posts: 260
@Chris:

When I want to play directly and call BASS_FX_TempoCreate again, then error 14 occurs (Already initialized/paused/whatever) and after that, error 5 on the following calls...


Ian @ un4seen

  • Administrator
  • Posts: 26015
It isn't possible for multiple tempo streams to have the same source, so that's why you get the BASS_ERROR_ALREADY error from BASS_FX_TempoCreate. You will need to free the existing tempo stream before creating another one. But note that doing that will also free the source due to the BASS_FX_FREESOURCE flag, so you will need to remove that flag. That also means you'll need to free the source yourself (via BASS_StreamFree) when you're finished with it because it won't be freed automatically any more.

kafffee

  • Posts: 260
Yessss...  ;D finally it works. Thanks guys :)

Ian @ un4seen

  • Administrator
  • Posts: 26015

hub73

  • Posts: 104
Code: [Select]
stream = Bass.BASS_StreamCreateFile(CurrentMP3Info.Filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN Or BASSFlag.BASS_STREAM_DECODE)
MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE Or BASSFlag.BASS_STREAM_DECODE)
BassMix.BASS_Mixer_StreamAddChannel(MainModule.mixer, MainModule.streamfx(WhichDeck - 1), BASSFlag.BASS_MIXER_NORAMPIN Or BASSFlag.BASS_STREAM_AUTOFREE Or BASSFlag.BASS_MIXER_BUFFER)
What is this flag for 'BASSFlag.BASS_MIXER_BUFFER' that I often see added, I can't find information in the documentation ?


hub73

  • Posts: 104
Thanks, I notice it's not mentioned here: (probably suitable for development with Delphi)
http://www.un4seen.com/doc/#bassmix/BASS_Mixer_StreamAddChannel.html