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

kafffee

  • Posts: 143
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: 432
Would not be much easy to change the device of the MainModule.mixer with BASS_ChannelSetDevice?


Ian @ un4seen

  • Administrator
  • Posts: 24692
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: 143
@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: 143
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: 24692
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: 143
OK did that.

streamfx(WhichDeck - 1) is freed when calling ChannelSetDevice

Ian @ un4seen

  • Administrator
  • Posts: 24692
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: 143
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: 24692
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: 143
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: 24692
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: 143
ChannelSetDevice returns False and ChannelGetDevice returns -1 (I tried to set it to device 5).

Ian @ un4seen

  • Administrator
  • Posts: 24692
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: 143
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: 24692
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: 143
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: 2090
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: 143
@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: 24692
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: 143
Yessss...  ;D finally it works. Thanks guys :)

Ian @ un4seen

  • Administrator
  • Posts: 24692

hub73

  • Posts: 73
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: 73
Thanks, I notice it's not mentioned here: (probably suitable for development with Delphi)
http://www.un4seen.com/doc/#bassmix/BASS_Mixer_StreamAddChannel.html