Author Topic: Mixing two stream channels and record result to hard disk/stream to web  (Read 5145 times)

kafffee

  • Posts: 276
I am about to implement the test application into my project and ran into error 38 - The channel is a decoding channel.

The difference to the test app is that I added some effects on stream like equalizer, tempo and pitch...

Code: [Select]
Bass.BASS_ChannelStop(stream)
stream = Bass.BASS_StreamCreateFile(Playlist(PlaylistSelectedIndex).Filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN)
MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_STREAM_AUTOFREE Or BASSFlag.BASS_FX_FREESOURCE Or BASSFlag.BASS_STREAM_DECODE)

Bass.BASS_ChannelSetDevice(MainModule.mixer, 2)
BassMix.BASS_Mixer_StreamAddChannel(MainModule.mixer, MainModule.streamfx(WelchesDeck - 1), BASSFlag.BASS_MIXER_NORAMPIN Or BASSFlag.BASS_STREAM_AUTOFREE)
Debug.WriteLine("add stream to mix: " & Bass.BASS_ErrorGetCode)

When I remove  BASSFlag.BASS_STREAM_DECODE from line 3 in the code, I get error 5 - invalid handle and streamfx(WhichDeck-1) is 0

Anybody can help?
« Last Edit: 29 Jun '22 - 18:45 by kafffee »

Ian @ un4seen

  • Administrator
  • Posts: 26102
With some functions, BASS_ERROR_DECODE means that the provided channel isn't a decoding channel when it should be. This is one of those cases - the BASS_STREAM_DECODE flag needs to be set on a stream in order to use it in a BASS_FX_TempoCreate call.

kafffee

  • Posts: 276
I dont know if you understood me right. The errors occur when calling BASS_Mixer_StreamAddChannel.

What would you suggest?

Chris

  • Posts: 2217
should to be
stream = Bass.BASS_StreamCreateFile(Playlist(PlaylistSelectedIndex).Filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN Or BASS_STREAM_DECODE)
MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_STREAM_AUTOFREE Or BASSFlag.BASS_FX_FREESOURCE Or BASSFlag.BASS_STREAM_DECODE)

to add a stream to a Mixer the (BassStream) and the Tempostream both must to be decoded Streams

kafffee

  • Posts: 276
Yes I've already tried that. But I keep on getting error 5 - invalid handle...

Chris

  • Posts: 2217
just check with Bass_ErrorGetCode after every call .
are your shure that the stream Handle is valid ?

so try something like this
if stream <> 0 then
   BASS_StreamFree(stream);

stream = Bass.BASS_StreamCreateFile(Playlist(PlaylistSelectedIndex).Filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN Or BASS_STREAM_DECODE);
if stream <> 0 then
begin
      MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_STREAM_AUTOFREE Or BASSFlag.BASS_FX_FREESOURCE Or BASSFlag.BASS_STREAM_DECODE);
............
else
 .. look like stream is not ok
   Bass_ErrorGetCode ...

   if the return of bass_ErrorGetCode is 2 .... then try this

stream = Bass.BASS_StreamCreateFile(Playlist(PlaylistSelectedIndex).Filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN Or BASS_STREAM_DECODE or BASS_UNICODE);



kafffee

  • Posts: 276
OK, I called BASS_ErrorGetCode after every call and I freed stream and streamfx before assigning them and I get error 37 (Requested data is not available) on my BassFx.BASS_FX_TempoCreate call

Ian @ un4seen

  • Administrator
  • Posts: 26102
You will need to remove the BASS_STREAM_AUTOFREE flag from the BASS_FX_TempoCreate call because it cannot be combined with the BASS_STREAM_DECODE flag, ie. decoding channels cannot be auto-freed. If you want to automatically free the stream after a mixer is done with it then you can use the BASS_STREAM_AUTOFREE flag in the BASS_Mixer_StreamAddChannel call.

kafffee

  • Posts: 276
Ok now every method is called successful:

Code: [Select]
Public Sub Play_Execute(obj As Object)
        Bass.BASS_ChannelStop(stream)
        If stream <> 0 Then Bass.BASS_StreamFree(stream)
        stream = Bass.BASS_StreamCreateFile(Playlist(PlaylistSelectedIndex).Filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN Or BASSFlag.BASS_STREAM_DECODE)
        Debug.WriteLine("streamcreatefile: " & CStr(Bass.BASS_ErrorGetCode))

        If MainModule.streamfx(WhichDeck - 1) <> 0 Then Bass.BASS_StreamFree(MainModule.streamfx(WelchesDeck - 1))

        MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE Or BASSFlag.BASS_STREAM_DECODE)
        Debug.WriteLine("tempocreate: " & CStr(Bass.BASS_ErrorGetCode))
        'Bass.BASS_ChannelPlay(MainModule.streamfx(WhichDeck - 1), False)
        Bass.BASS_ChannelSetDevice(MainModule.mixer, 2)
        Debug.WriteLine("setdevice: " & CStr(Bass.BASS_ErrorGetCode))
        Debug.WriteLine("channelsetdevice" & Bass.BASS_ErrorGetCode)
        BassMix.BASS_Mixer_StreamAddChannel(MainModule.mixer, MainModule.streamfx(WhichDeck - 1), BASSFlag.BASS_MIXER_NORAMPIN Or BASSFlag.BASS_STREAM_AUTOFREE)
        Debug.WriteLine("add stream to mix: " & CStr(Bass.BASS_ErrorGetCode))
        MainModule.MyEQ(WhichDeck - 1) = New Equalizer(MainModule.streamfx(WhichDeck - 1))
        MainModule.MyEQ(WelchesDeck - 1).EQ_Init()
        MainModule.VisualizationTimer.Start()
    End Sub

But when I start my music, it is not audible, even though my peak meter and spectrum anaylzer show some action.

When I add a microphone to the mixer channel first, the music is audible but sounds kind of totally chopped up...:

Code: [Select]
Bass.BASS_ChannelSetAttribute(MainModule.mikro, BASSAttribute.BASS_ATTRIB_VOL, 1)
                BassMix.BASS_Mixer_StreamAddChannel(MainModule.mixer, MainModule.mikro, BASSFlag.BASS_MIXER_NORAMPIN Or BASSFlag.BASS_STREAM_AUTOFREE)

Any idea what this is all about? Do you need some extra code? Maybe the chopped up sound has soemthing to do with mono/stereo playback? At some point I remember you could add a flag like ...MONO or so to some method, but i cant remember which one...

PS:
VisualisationTimer repeatedly calls this:
Code: [Select]
Dim Flag As BASSLevel = CType(16, BASSLevel)
        peak = Bass.BASS_ChannelGetLevels(MainModule.streamfx(WhichDeck - 1), 0.1, Flag)
        If peak IsNot Nothing Then

            PeakLeft = peak(0)
            PeakRight = peak(1)
        End If

and this:

Code: [Select]
BMP = Spektrum.CreateSpectrumLinePeak(MainModule.streamfx(WhichEQ - 1), Width, Height, System.Drawing.Color.Green, System.Drawing.Color.IndianRed, System.Drawing.Color.SlateGray, System.Drawing.Color.Transparent, Resolution, 3, Distance, 40, False, True, True)
        Picture = BitmapToImageSource(BMP)
« Last Edit: 1 Jul '22 - 06:11 by kafffee »

Ian @ un4seen

  • Administrator
  • Posts: 26102
But when I start my music, it is not audible, even though my peak meter and spectrum anaylzer show some action.

I guess you're currently using BASS_ChannelGetLevel/Data in that? BASS_ChannelGetLevel/Data shouldn't be used on a mixer source because the data decoded/used by those calls will not be seen by the mixer, ie. you'll hear skips in the mixer output. You can instead use BASS_Mixer_ChannelGetLevel/Data, after including BASS_MIXER_CHAN_BUFFER in the BASS_Mixer_StreamAddChannel call.

kafffee

  • Posts: 276
There is no BASS_MIXER_CHAN_BUFFER provided, only BASS_MIXER_BUFFER. Am I using an obsolete version of BassMix.dll? Currently I got version 2.4.10.0

And is this correct?:

Code: [Select]
Dim peak() As Single = {0, 0}
Dim Flagge As BASSLevel = CType(16, BASSLevel)
BassMix.BASS_Mixer_ChannelGetLevel(MainModule.streamfx(WhichDeck - 1), peak, 0.1, Flagge Or BASSLevel.BASS_LEVEL_STEREO)

or should i go with this:

Code: [Select]
peakint = BassMix.BASS_Mixer_ChannelGetLevel(MainModule.streamfx(WelchesDeck - 1))

Chris

  • Posts: 2217
Yes after a look into the bass.net docs
MIXER_CHAN_BUFFER is in net BASS_MIXER_BUFFER.

both Level Calls are possible because that are overloads in bass.net

http://www.bass.radio42.com/help/html/aa94bf9a-48e3-6b95-fdf1-8fc4bd46fb39.htm

http://www.bass.radio42.com/help/html/01bebc71-0c3d-75ce-fc40-199d4b8b14fc.htm

kafffee

  • Posts: 276
OK did this - still no change.

But thinking of the word "buffer": I removed this from directly after my BASS_Mixer_StreamCreate call:

Code: [Select]
Bass.BASS_ChannelSetAttribute(MainModule.mixer, BASSAttribute.BASS_ATTRIB_BUFFER, 0)
Now i can play my music without adding the mic to the mix before. Its still chopped up, but it plays, and the peak meter looks like it's working fine... Maybe "chopped up" is the wrong word. It seems like "a bit out of order"... Its hard to tell but it also seems like its slowly increasing playback speed at the beginning... I might be wrong though...

Maybe I gotta try something with BASS_CONFIG_BUFFER? What do you think? What would be a good value?

Or maybe it has something to do with my BASS_ATTRIB_TEMPO and BASS_ATTRIB_TEMPO_PITCH calls, which I apply on streamfx

Ian @ un4seen

  • Administrator
  • Posts: 26102
The mixer's playback buffer shouldn't affect whether sources are heard in the mix. If it sounds like bits of a source are being skipped then there are probably still some BASS_ChannelGetLevel/Data calls on the source somewhere. Looking again at the code you posted above, I suspect it's the Spektrum.CreateSpectrumLinePeak call, which will be using BASS_ChannelGetData internally by default. BASS.Net's Visuals class has a "ChannelIsMixerSource" property that you can set to "true" to make it use BASS_Mixer_ChannelGetData instead.

kafffee

  • Posts: 276
Thank God it works  ;D Thank you so much guys!!

There's a little problem left though.... When I use Bass.BASS_ChannelSetAttribute(MainModule.mixer, BASSAttribute.BASS_ATTRIB_BUFFER, 0) after my BASS_Mixer_StreamCreate call, the music wont start playing at all, neither does the peak meter and spectrum analyzer show any action. When I do leave it out, everything works fine but the microphone which is added to the stream as well, has this long delay again. What can I do to fix this?

Ian @ un4seen

  • Administrator
  • Posts: 26102
That's strange. If you monitor what BASS_ChannelIsActive and BASS_ChannelGetPosition say about the mixer, does it show the mixer is active and advancing? If not, also check the mixer's BASS_ChannelPlay return value.

kafffee

  • Posts: 276
BASS_ChannelPlay(mixer) returns 0, but BASS_ChannelIsActive(mixer) returns 2 - Playback of the stream has been stalled due to there not being enough sample data to continue playing. The playback will automatically resume once there's sufficient data to do so.
BASS_ChannelGetPosition(mixer) starts increasing as soon as I play a song via StreamAddChannel

Ian @ un4seen

  • Administrator
  • Posts: 26102
Did you mean BASS_ChannelPlay is returning 0, or the error code is 0? If the former then that means the call failed - please check the error code with BASS_ErrorGetCode. If BASS_ChannelPlay is successful then next check what BASS_Mixer_ChannelIsActive says about the source.

kafffee

  • Posts: 276
BASS_ChannelPlay(mixer) returns BASS_ErrorGetCode = 0, and also BASS_Mixer_ChannelIsActive(streamfx(0)) returns 1 (The channel is playing (or recording)) when I add my stream to the mixer, no matter if I do BASS_ChannelSetAttribute(MainModule.mixer, BASSAttribute.BASS_ATTRIB_BUFFER, 0) or not

Ian @ un4seen

  • Administrator
  • Posts: 26102
OK. To get a clearer picture of what's happening, please post the mixer and source setup code that's producing the problem.

kafffee

  • Posts: 276
Sure  :)

I'm initializing with this:

Code: [Select]
Public Sub GetPlaybackDevices()
        Dim PlaybackDeviceInfo As New BASS_DEVICEINFO
        For i = 0 To Bass.BASS_GetDeviceCount - 1
            Bass.BASS_GetDeviceInfo(i, PlaybackDeviceInfo)
            Speakers.Add(PlaybackDeviceInfo.name)
            If IsInDesignMode = False Then          'only initialize when  in runtime
                Bass.BASS_Init(i, 44100, BASSInit.BASS_DEVICE_DEFAULT, Nothing)
            End If
        Next
        Headphones = Speakers 'Headphones and Speakers are each a list of playback devices
        SpeakerIndex = 1           'Selecting playback devices via index. this is the index of Headphones and Speakers
        HeadphoneIndex = 1
    End Sub

I am selecting playback devices like this: (same as for HeadphoneIndex)

Code: [Select]
Private _SpeakerIndex As Integer
    Public Property SpeakerIndex As Integer
        Get
            Return _SpeakerIndex
        End Get
        Set(value As Integer)
            _SpeakerIndex = value
            Bass.BASS_ChannelSetDevice(MainModule.mixer, value)
            Debug.WriteLine("setdevice mixer to speaker: " & Bass.BASS_ErrorGetCode)
            RaisePropertyChanged()
        End Set
    End Property

I am creating the mixer as follows:

Code: [Select]
GetPlaybackDevices()

MainModule.mixer = Un4seen.Bass.AddOn.Mix.BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT Or BASSFlag.BASS_SAMPLE_FLOAT)
        Debug.WriteLine("mixerstreamcerate" & Bass.BASS_ErrorGetCode)
        Bass.BASS_ChannelSetAttribute(MainModule.mixer, BASSAttribute.BASS_ATTRIB_BUFFER, 0) ' disable playback buffering'
        'Debug.WriteLine("mixer disable playback buffering: " & Bass.BASS_ErrorGetCode)
        Bass.BASS_ChannelSetDevice(MainModule.mixer, SpeakerIndex)
        Debug.WriteLine("set mixerdevice to selected speaker: " & Bass.BASS_ErrorGetCode)
        Bass.BASS_ChannelPlay(MainModule.mixer, False)
        Debug.WriteLine("mixer play: " & Bass.BASS_ErrorGetCode)
        Debug.WriteLine("bass_channelisactive: " & CStr(Bass.BASS_ChannelIsActive(MainModule.mixer)))
        Debug.WriteLine("bass.channelgetposition: " & CStr(Bass.BASS_ChannelGetPosition(MainModule.mixer)))

When I hit play, the following is being executed:

 
Code: [Select]
Public Sub Play_Execute(obj As Object)
        Bass.BASS_ChannelStop(stream)
        If stream <> 0 Then Bass.BASS_StreamFree(stream)
        stream = Bass.BASS_StreamCreateFile(Playlist(PlaylistSelectedIndex).Filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN Or BASSFlag.BASS_STREAM_DECODE)
        Debug.WriteLine("streamcreatefile: " & CStr(Bass.BASS_ErrorGetCode))

        If MainModule.streamfx(WhichDeck - 1) <> 0 Then Bass.BASS_StreamFree(MainModule.streamfx(WhichDeck - 1))

        MainModule.streamfx(WhichDeck - 1) = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE Or BASSFlag.BASS_STREAM_DECODE)
        Debug.WriteLine("tempocreate: " & CStr(Bass.BASS_ErrorGetCode))
        Bass.BASS_ChannelSetDevice(MainModule.mixer, SpeakerIndex)
        Debug.WriteLine("channelsetdevice" & Bass.BASS_ErrorGetCode)
        BassMix.BASS_Mixer_StreamAddChannel(MainModule.mixer, MainModule.streamfx(WhichDeck - 1), BASSFlag.BASS_MIXER_NORAMPIN Or BASSFlag.BASS_STREAM_AUTOFREE Or BASSFlag.BASS_MIXER_BUFFER)
        Debug.WriteLine("add stream to mix: " & CStr(Bass.BASS_ErrorGetCode))
        MainModule.MeinEQ(WhichDeck - 1) = New Equalizer(MainModule.streamfx(WhichDeck - 1))
        MainModule.MeinEQ(WhichDeck - 1).EQ_Init()
        MainModule.VisualizationTimer.Start()
    End Sub

VisualizationTimer calls this every 25 milliseconds:

Code: [Select]
Public Sub ShowPeak(ByVal sender As Object, ByVal e As EventArgs)
        Dim Flag As BASSLevel = CType(16, BASSLevel)
       
        BassMix.BASS_Mixer_ChannelGetLevel(MainModule.streamfx(WhichDeck - 1), peak, 0.1, Flag Or BASSLevel.BASS_LEVEL_STEREO)
        If peak IsNot Nothing Then
            'Debug.WriteLine("L" & CStr(peak(0)) & "R" & CStr(peak(1)))
            Debug.WriteLine("bass.channelgetposition: " & CStr(Bass.BASS_ChannelGetPosition(MainModule.mixer)))
            Debug.WriteLine("bass.cjannelisactive: " & CStr(BassMix.BASS_Mixer_ChannelIsActive(MainModule.streamfx(0))))
            PeakLeft = peak(0)
            PeakRight = peak(1)
        End If
    End Sub

and this:

Code: [Select]
Private Sub UpdateVisualization(ByVal sender As Object, ByVal e As EventArgs)
        BMP = Spektrum.CreateSpectrumLinePeak(MainModule.streamfx(WhichEQ - 1), Width, Height, System.Drawing.Color.Green, System.Drawing.Color.IndianRed, System.Drawing.Color.SlateGray, System.Drawing.Color.Transparent, Resolution, 3, Distance, 40, False, True, True)
        Bild = BitmapToImageSource(BMP)
    End Sub

There  is also code to add input devices, I dont know if its relevant, it follows the same pattern as GetPlaybackDevices():

Code: [Select]
Public Sub GetRecordingDevices()
        Dim RecordingDeviceInfo As New BASS_DEVICEINFO
        For i = 0 To Bass.BASS_RecordGetDeviceCount - 1
            Bass.BASS_RecordGetDeviceInfo(i, RecordingDeviceInfo)
            Microphone.Add(RecordingDeviceInfo.name)
            If IsInDesignMode = False Then
                Bass.BASS_RecordInit(i)
            End If
        Next
        LineIn = Microphone
        MicrophoneIndex = 0
        LineInIndex = 0
    End Sub

This code produces of course some invalid handlers, is this relevant to the issue? I did not get to fix this yet....

Code: [Select]
Private _MikrophoneIndex As Integer
    Public Property MicrophoneIndex As Integer
        Get
            Return _MicrophoneIndex
        End Get
        Set(value As Integer)
            _MicrophoneIndex = value

            BassMix.BASS_Mixer_ChannelRemove(MainModule.mikro)
            Debug.WriteLine("mikro channelremove: " & Bass.BASS_ErrorGetCode)
            Bass.BASS_RecordSetDevice(value)
            Debug.WriteLine("recordsetdevice mikro: " & CStr(Bass.BASS_ErrorGetCode))
            MainModule.mikro = Bass.BASS_RecordStart(44100, 1, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT, Nothing, IntPtr.Zero)
            Debug.WriteLine("recordstart mikro: " & CStr(Bass.BASS_ErrorGetCode))
            BassMix.BASS_Mixer_StreamAddChannel(MainModule.mixer, MainModule.mikro, BASSFlag.BASS_MIXER_NORAMPIN Or BASSFlag.BASS_STREAM_AUTOFREE)
            Debug.WriteLine("mikro streamaddchannel: " & Bass.BASS_ErrorGetCode)
            RaisePropertyChanged()
        End Set
    End Property

Ian @ un4seen

  • Administrator
  • Posts: 26102
OK. Next please try reducing that code to the minimum required to produce the problem, and post that. For example, does it still happen if you basically just create the mixer and add the file to it, without any effects and vis stuff?

kafffee

  • Posts: 276
Yes it still happens with this when I reduce to this: (I also encountered no errors, BASS_ErrorGetCode returns 0 on any call)

Edit:
When I skip BASS_ChannelSetDevice, it works.... But I don't know why, there is no error...

Edit2: Okay I see - there is no need to keep it - I already set the Speaker device in GetPlaybackDevices... But would be interesting to know why it behaves that way...

Code: [Select]
Public Sub Play_Execute(obj As Object)
Bass.BASS_ChannelStop(stream)
        If stream <> 0 Then Bass.BASS_StreamFree(stream)
        stream = Bass.BASS_StreamCreateFile(Playlist(PlaylistSelectedIndex).Filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN Or BASSFlag.BASS_STREAM_DECODE)
Bass.BASS_ChannelSetDevice(MainModule.mixer, 2)
        BassMix.BASS_Mixer_StreamAddChannel(MainModule.mixer, stream, BASSFlag.BASS_MIXER_NORAMPIN Or BASSFlag.BASS_STREAM_AUTOFREE Or BASSFlag.BASS_MIXER_BUFFER)
End Sub
« Last Edit: 8 Jul '22 - 15:08 by kafffee »

Ian @ un4seen

  • Administrator
  • Posts: 26102
If you call BASS_ChannelGetDevice before and after BASS_ChannelSetDevice, which values do you get?

kafffee

  • Posts: 276
Don't know if you have read my two edits, but:

When I set to index 1 in GetPlaybackDevices and I set to 2 in Play_Execute()

I get the same before and after: 5 (which would be the speakers of my screen)