Author Topic: Clone "mixed" stream to another output device ?  (Read 3482 times)

Ian @ un4seen

  • Administrator
  • Posts: 25884
Re: Clone "mixed" stream to another output device ?
« Reply #25 on: 24 May '24 - 18:02 »
Nice schematic :D

BASS_ATTRIB_BUFFER should be set on the splitters, so that looks fine above. The latency you're hearing may be because you've started the recording before the splitters, and there's a build-up of buffered data in the meantime. Try adding the BASS_RECORD_PAUSE flag to the BASS_RecordStart call so that it's paused, and then call BASS_ChannelStart on the recording after the splitters.

Regarding using BASS_ChannelGetData to remove data from the recording, that doesn't look necessary with the code above, but you would set the "buffer" parameter to NULL (0) and the "length" parameter to the amount that you want to remove.

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #26 on: 25 May '24 - 06:29 »
Hi Ian,
Nice schematic :D
Ahah ! Yes, thanks  I quickly did it with Draw.io (Google)

About BASS_ChannelGetData, I don't notice changes, even with different lengthes.

Code: [Select]
    Call BASS_RecordFree
    Call BASS_RecordInit(-1)
    Call BASS_RecordSetInput(-1, BASS_INPUT_ON, -1)
    MicInput = BASS_RecordStart(44100, 2, BASS_RECORD_PAUSE, 0, 0)
    Call BASS_ChannelGetData(MicInput, ByVal 0, BASS_DATA_FFT256)
    Call BASS_ChannelSetAttribute(MicInput, BASS_ATTRIB_BUFFER, 0)
   
    For nDev = 0 To 1
        Call BASS_SetDevice(OutDev(nDev))
        SplitInput(nDev) = BASS_Split_StreamCreate(MicInput, 0, ByVal 0)
        Call BASS_ChannelSetAttribute(SplitInput(nDev), BASS_ATTRIB_BUFFER, 0)
        If nDev <> 0 Then
            Call BASS_ChannelSetLink(SplitInput(0), SplitInput(nDev))
        End If
        Call BASS_ChannelSetAttribute(SplitInput(nDev), BASS_ATTRIB_VOL, 0)
    Next nDev
    Call BASS_ChannelStart(SplitInput(0))
    Call BASS_ChannelPlay(MicInput, BASSTRUE)
I tried something else, directly Listen the input in the Audio settings of Windows, I measure 140 ms between input and output. It could explain why I can get under ~120 ms (?).

I tested with a cheap USB sound device (look in the zip file) for input (but stil play with PC onboard device) and I get strange behavior : the sound is slow down and all is not recorded (like if it is synchronizing each x seconds to make up for the time lost by the slowdown). I don't know from what it comes lol

jpf

  • Posts: 196
Re: Clone "mixed" stream to another output device ?
« Reply #27 on: 26 May '24 - 05:55 »
If I were you I'd start from zero trying to get a simple low latency path between the mic and the headphones, leaving aside all other stuff. Like and independent project you can later merge into Jingle Palette.

From my experience in the radio station I can say that normal DirectX or Wasapi drivers don't have short enough latency for direct monitoring. You should use ASIO drivers. A free alternative is ASIO4ALL. And you can't use this with regular BASS audio input/output; you should use BASS_Asio plugin for both input and output.

The microphone should be plugged in the same soundcard as the headphones so the Dac and Adc converters are driven by the same clock and stay in sync. Otherwise you're likely to get data buildup or exhaustion.

If that doesn't help much you must try a different USB audio interfase. I suggest Behringer UCA202 (at less than €50) as the cheapest candidate.

You should be able to get latencies under 10 ms using that setup.

Then integrating this block into Jingle Pallete should go as you were planning.

If you're broadcasting you probably won't have other monitoring than the headphones driven directly by your app. This is fine. You can't monitor on-air sound because that will have a very long latency. Mixing console output can be used but then you need a low latency path also from the mic to the console.

If you're DJ'ng for an audience in the same room then you have main speakers coming into play. I don't think the latency from mic to the main speakers should be a problem. A bit of latency can even be pleasant if you're simultaneously listening to your own voice in the low latency headphones.

Using ASIO drivers also for the main speakers can help if their latency turns out to be disturbing. That depends on the headphones vs main speakers volume ratio. The louder the headphones are the less important is the main speakers latency, but high levels can damage your hearing. I advice on using noise cancelling headphones in this case. Even cheap ones can help because they'll still be effective on high frequencies, which are the most dangerous. Frequencies below 100 Hz can be annoying but they aren't really dangerous.

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #28 on: 27 May '24 - 02:50 »
Hi jpf

Happy to see you there too ;)

For my personal usage, I have no problem because I do my show with a real mixer (TTM57SL) and SL1200s with mic (low cost but good for what I do lol Neewer NW-700 + 48V phantom PS) on it. JP send its sound in AUX IN of the mixer.

The (eventual) "Mic input" feature for JP is for who wants to do a (radio) show without real mixer, decks, just a PC and a microphone (commonly USB microphone, ie. low cost Neewer NW-7000/8000) and headphones (USB or jack 1/4").

I downloaded ASIO4ALL, Bass_Asio and trying to make running :)
I use "Multi" project in vb directory.

VB6 IDE reveals a Compile error: Expected: identifier in bassasio.bas at runtime:
Code: [Select]
Declare Function BASS_ASIO_Lock Lib "bassasio.dll" (ByVal lock As Long) As Long(where "lock" is highbrighted).
I renamed "lock" for "lockk" to overide error (but I don't know the consequences).
I can get sound.

But when I try to understand the code, I see the approach looks totally different than from Bass: No Bass_ChannelPlay/Stop(chan ... ), etc.
I'm afraid that it would be very hard to use in JP because of lot of code modification, so that both methods (BASS and BASS_ASIO) can work according to the users choice. Or perhaps it's just on the 2 splitted streams I should apply the BASS ASIO (and not on each commands Play/Stop of channels before mixer)?

About Mic input, I checked the online documentation, I don't also see any BASS_ASIO equivalent for RecordFree/Init etc.

Just tried this:

Code: [Select]
Dim MicInput As Long
Call BASS_RecordFree
Call BASS_RecordInit(outdev(0))
Call BASS_RecordSetInput(outdev(0), BASS_INPUT_ON, -1)
MicInput = BASS_RecordStart(44100, 2, BASS_RECORD_PAUSE, 0, 0)
Call BASS_ChannelGetData(MicInput, ByVal 0, BASS_DATA_FFT256)
Call BASS_ChannelSetAttribute(MicInput, BASS_ATTRIB_BUFFER, 0)
Call BASS_ChannelPlay(MicInput, BASSTRUE)

'start ASIO output
Dim i As BASS_CHANNELINFO, a As Long
Call BASS_ChannelGetInfo(MicInput, i)
Call BASS_ASIO_ChannelEnableBASS(0, 0, MicInput, BASSTRUE) 'enable ASIO channel(s)
Call BASS_ASIO_SetRate(i.freq) 'try to set the device rate to avoid resampling
If (BASS_ASIO_Start(0, 0) = 0) Then 'start output using default buffer/latency
Call Error_("Can't start ASIO output")
End If
   
I get sound from the microphone but with the same latency than without BASS ASIO.

jpf

  • Posts: 196
Re: Clone "mixed" stream to another output device ?
« Reply #29 on: 27 May '24 - 16:25 »
I was looking at the code I used in my virtual pipe organ app. BASS_ASIO_ChannelEnableBASS isn't defined in bassasio ver 1.3, the one I used by then. Now I see version 1.4 is out and includes that function.

I see that in the vb examples there's a "livefx" one, that should get you started. Did you run it? I just did. I had to fix a couple of errors. The device is harcoded to the default, which probably isn't what you want, but you can try setting it to another one.

When I tried it as it was the device used turned to be the onboard soundcard. The app then shows a latency of 27 ms. The ASIO4ALL control panel shows a 512 samples buffer for input and another 512 samples for output. I can reduce or raise the latency displayed by the app reducing or raising those buffers. I don't know what could be the minimun latency to get a stable audio output (without crackling) because I didn't test it with a microphone or any other record source. Also I don't know if the displayed latency will match that that you measuring. I don't have a setup to measure it. I guess I'll need an external recorder (another PC?) recording the mic and the sondcard output so I can align the waves an see what offset I needed to apply?

Edit:
Now reading the help I found something I didn't notice before: the asio driver runs in the same thread thet loaded it in an appartment model. That's the same as VB6. Does this mean I can debug into the asio callback without crashing the IDE? So far I was placing the callback in a separate dll to avoid crashing the Ide.
« Last Edit: 27 May '24 - 16:50 by jpf »

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #30 on: 28 May '24 - 06:51 »
Hi jpf,

I just tried with LiveFX project, it's better, I can get 66 ms of (measured by recording with my phone) latency.
I think I won't get better with these type of soundcard. If I find a second hand UCA202/222 I would test with it.

I have also Rane/Serato SL1 and SL3 interfaces (I was beta tester during few years), if I remember well, there are ASIO drivers for them. It could be a good test. But now, I go to bed (work by night).

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #31 on: 29 May '24 - 05:43 »
Hi  :)

I get some difficulties to understand how BASS ASIO runs.

I merged a light version of "LiveFX" (without any effects etc etc, just listen the microphone and play it to the speakers, with ASIO4ALL) to JP, but I don't know how to do anything else  :'( :
- I don't see any BASS ASIO Split in the doc, to send ASIO Mic to Output device 0 (ie. Virtual Cable or other WDM device).
- I don't see how to send the mixer output to ASIO Output (and so merge with microphone).
(i the nice draw  ;D , ex-Output(1) is ASIO In and Out)

Plus, I noticed that for exemple, I listen something with winamp or other, once I start project using ASIO, what I was listening cuts/plays on another device (ie USB 3D soundcard like previoulsy shown), is it normal ?

Ian @ un4seen

  • Administrator
  • Posts: 25884
Re: Clone "mixed" stream to another output device ?
« Reply #32 on: 30 May '24 - 17:58 »
Plus, I noticed that for exemple, I listen something with winamp or other, once I start project using ASIO, what I was listening cuts/plays on another device (ie USB 3D soundcard like previoulsy shown), is it normal ?

Yes, some/most ASIO drivers only allow one user at a time, ie. other things won't be able to use the device while ASIO is. If you want the device to remain usable for everyone then I think it's probably best to avoid ASIO. The same goes for exclusive-mode WASAPI.

Since Windows 10, shared-mode WASAPI allows smaller buffers than the usual 10ms, for lower latency. I don't think you'll be able to get as low as ASIO or exclusive-mode WASAPI, but perhaps low enough. BASS doesn't include the option but BASSWASAPI (BASS_WASAPI_Init) does if you would like to try it.

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #33 on: 31 May '24 - 13:56 »
Hi Ian,
Thanks, I will have a look.
But about mixing ASIO and non-ASIO (like on my last schematic), do you think it is possible ? I did not found yet how to do :(

Ian @ un4seen

  • Administrator
  • Posts: 25884
Re: Clone "mixed" stream to another output device ?
« Reply #34 on: 31 May '24 - 16:41 »
It is possible to use ASIO and non-ASIO playback at the same time on different devices, but not on the same device if the ASIO driver doesn't allow other users. Note that BASSASIO doesn't include mixing, so you will need to use BASSmix for that, ie. feed a mixer to the ASIO output (perhaps using a mixer in a BASS_ASIO_ChannelEnableBASS call).

jpf

  • Posts: 196
Re: Clone "mixed" stream to another output device ?
« Reply #35 on: 2 Jun '24 - 06:38 »
I just saw that the VB6 livefx example hasn't been updated to use BASS_ASIO_ChannelEnableBASS instead of callbacks.

I still think the livefx example is a good start to your project but you'd feel more confortable not having to deal with callbacks and instead use normal BASS channels.

That way you could probably be able to translate your last schematic into working code with little effort using Ian's suggestions. You've proved that you know your way around.

The C code example seems easy enough to translate into VB6 code if you understand both languages.

If you feel unable to do that I may give it a try. Just let me know. I've been quite busy lately the last couple of years and still am so don't expect a quick return.

That won't solve your problem with other apps sharing the same audio device, though. There might be a way around using a 3rd part app like VBMatrix Coconut (https://vb-audio.com/Matrix/coconut.htm). I never used it so I can't help you there. 

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #36 on: 2 Jun '24 - 15:00 »
Hi friends,

Thanks for answers :)

I'm trainning for the moment with a lighted version of "Multi", to first split mixer output to 2 device (1 ASIO , 1 Non ASIO). I will check for input after getting a good result of split.

So, on form load, I create a mixer with DECODE, split the mixer output to 2 streams:

Code: [Select]
    Call BASS_ASIO_SetDevice(outdev(0)) 'set the ASIO device to work with
    Call BASS_ASIO_Stop   'stop the device
    Call BASS_ASIO_ChannelReset(0, -1, BASS_ASIO_RESET_ENABLE Or BASS_ASIO_RESET_JOIN) 'disable & unjoin all output channels

    Dim i As BASS_ASIO_DEVICEINFO
    Call BASS_ASIO_GetDeviceInfo(outdev(0), i)
   
    Call BASS_StreamFree(mixer)
    mixer = BASS_Mixer_StreamCreate(BASS_ASIO_GetRate(), 2, BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE)
   
    SplitOutput(0) = BASS_Split_StreamCreate(mixer, BASS_STREAM_DECODE, ByVal 0)
    Call BASS_ChannelStart(SplitOutput(0))
   
    Call BASS_ASIO_ChannelEnableBASS(False, 0, SplitOutput(0), True)
    Call BASS_ASIO_Start(0, 0)
   
    Dim dev ' NON ASIO device number
    dev = 5
    Call BASS_Init(dev, 44100, 0, 0, 0)
    Call BASS_SetDevice(dev)
    SplitOutput(1) = BASS_Split_StreamCreate(mixer, 0, ByVal 0)
    Call BASS_ChannelStart(SplitOutput(1))
   
On the button to load the audio file:
Code: [Select]
    Call BASS_StreamFree(chan(Index))

    chan(Index) = BASS_StreamCreateFile(BASSFALSE, StrPtr(cmd.FileName), 0, 0, BASS_SAMPLE_LOOP Or BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE)

    If (chan(Index) = 0) Then
        cmdOpen(Index).Caption = "click here to open a file..."
        Call Error_("Can't play the file")
        Exit Sub
    End If

    Call BASS_Mixer_ChannelRemove(chan(Index))
    Call BASS_Mixer_StreamAddChannel(mixer, chan(Index), BASS_MIXER_CHAN_BUFFER)
   
I get the sound of both device once the track is loaded. Good.

I want to set the volume for each splitted channels before sending to their device, so I added an array of 2 sliders to the main form, and an the Scroll event:

Code: [Select]
Private Sub Slider1_Scroll(Index As Integer)
    volval(Index).Caption = Slider1(Index).value
    Call BASS_ChannelSetAttribute(SplitOutput(Index), BASS_ATTRIB_VOL, Slider1(Index).value / 100)
End Sub

I acts correctly on the splitted stream (1) that going to NON ASIO device, but it does nothing to splitted stream (0) that going to ASIO device.

I could set the volume of ASIO master with:
Code: [Select]
Private Sub Slider1_Scroll(Index As Integer)
    volval(Index).Caption = Slider1(Index).value
    If Index < 2 Then
    Call BASS_ChannelSetAttribute(SplitOutput(Index), BASS_ATTRIB_VOL, Slider1(Index).value / 100)
    Else
    Call BASS_ASIO_ChannelSetVolume(False, -1, Slider1(Index).value / 100) '; // apply it to output channel 0
    End If
End Sub

But it would also change the volume of (future) mic input, I would to understand why it does nothing with the first method.

If you have an idea :)

Thanks :)

jpf

  • Posts: 196
Re: Clone "mixed" stream to another output device ?
« Reply #37 on: 2 Jun '24 - 19:30 »
The documentation on BASS_ATTRIB_VOL states: "This attribute applies to playback of the channel, and does not affect the channel's sample data, so has no real effect on decoding channels. It is still adjustable then though, so that it can be used by the BASSmix add-on and anything else that wants to use it. "

So I guess BASS_ASIO_ChannelEnableBASS is just internally calling BASS_ChannelGetData to pull data from the splitter without caring about the  BASS_ATTRIB_VOL set on it. There may be a new flag allowing  BASS_ATTRIB_VOL to affect BASS_ChannelGetData but I don't recall it. If there isn't any you can set a bassfx BASS_BFX_VOLUME on the splitter and control its volume by setting BASS_BFX_VOLUME with BASS_FXSetParameters. Aren't you using a mixer after the splitter to mix in JP's mixer? If so you can enable matrix mixing and control volumes individually by setting the matrix parameters.

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #38 on: 3 Jun '24 - 12:49 »
Thanks jpf, this is true that I not though to return to BASS_ATTRIB_VOL  documentation  :-[

After some hours to have result, BASS_BFX_VOLUME  did the jobs  :)

Quote
Aren't you using a mixer after the splitter to mix in JP's mixer?
I don't understand what you mean ?
For the moment, I have only one mixer, to mix all sounds, and I split the mixer output to send the splitted stream to each output device. This is actually done :)

I'm now working on MIC INPUT with ASIO (based on LiveFX example). (I will see to split to both devices after).
I can ear the Mic in the ASIO output:
Code: [Select]
micchan = BASS_StreamCreate(BASS_ASIO_GetRate(), 2, BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE, STREAMPROC_PUSH, 0)
Call BASS_ASIO_ChannelEnableBASS(True, 0, micchan, True)
Call BASS_ASIO_ChannelEnableBASS(False, 0, micchan, True)
But the other audio files I load does not plays on ASIO (I mean , like if this line was not present:
Code: [Select]
Call BASS_ASIO_ChannelEnableBASS(False, 0, SplitOutput(0), True)
Is is not possible to send multiple streams to the same ASIO output ?

Ian @ un4seen

  • Administrator
  • Posts: 25884
Re: Clone "mixed" stream to another output device ?
« Reply #39 on: 3 Jun '24 - 17:20 »
Thanks jpf, this is true that I not though to return to BASS_ATTRIB_VOL  documentation  :-[

After some hours to have result, BASS_BFX_VOLUME  did the jobs  :)

If you don't need ramping then a simpler alternative to BASS_BFX_VOLUME is the BASS_ATTRIB_VOLDSP option, which you can use just like BASS_ATTRIB_VOL (with BASS_ChannelSetAttribute).

I'm now working on MIC INPUT with ASIO (based on LiveFX example). (I will see to split to both devices after).
I can ear the Mic in the ASIO output:
Code: [Select]
micchan = BASS_StreamCreate(BASS_ASIO_GetRate(), 2, BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE, STREAMPROC_PUSH, 0)
Call BASS_ASIO_ChannelEnableBASS(True, 0, micchan, True)
Call BASS_ASIO_ChannelEnableBASS(False, 0, micchan, True)
But the other audio files I load does not plays on ASIO (I mean , like if this line was not present:
Code: [Select]
Call BASS_ASIO_ChannelEnableBASS(False, 0, SplitOutput(0), True)
Is is not possible to send multiple streams to the same ASIO output ?

No, you will need a mixer to play multiple streams on the same ASIO output. You would use the mixer handle in a BASS_ASIO_ChannelEnableBASS call, and then pass the streams to BASS_Mixer_StreamAddChannel. For best results (avoid possibly resampling twice), also use the BASS_ASIO_GetRate value in the BASS_Mixer_StreamCreate call.

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #40 on: 4 Jun '24 - 03:52 »
Hi Ian,

Thanks, I got the same result with simpler solution.

About ASIO output, I so added a mixer which receive mic and the other mixer. Now I have audio files and mic played by ASIO output  :)

Here is the code, perhapps is there a better way ?

Code: [Select]
Private Sub Form_Load()
    'change and set the current path
    'so it won't ever tell you, that "bass.dll" isn't found
    ChDrive App.Path
    ChDir App.Path

    'check if "bass.dll" is exists
    If (Not FileExists(RPP(App.Path) & "bass.dll")) Then
        Call MsgBox("BASS.DLL does not exists", vbCritical, "BASS.DLL")
        End
    End If

    ' check the correct BASS was loaded
    If (HiWord(BASS_GetVersion) <> BASSVERSION) Then
        Call MsgBox("An incorrect version of BASS.DLL was loaded", vbCritical)
        End
    End If

    'check if "bassasio.dll" is exists
    If (Not FileExists(RPP(App.Path) & "bassasio.dll")) Then
        Call MsgBox("BASSASIO.DLL does not exists", vbCritical, "BASSASIO.DLL")
        End
    End If

    'let the user choose the output devices
    With frmDevice
        .SelectDevice 1
        .Show vbModal, Me
        outdev(0) = .device
    End With

    'not playing anything via BASS, so don't need an update thread
    Call BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 0)

    'initialize BASS - "no sound" device
    Call BASS_Init(0, 48000, 0, 0, 0)

    'initialize ASIO devices
    If (BASS_ASIO_Init(outdev(0), 0) = 0) Then
        Call Error_("Can't initialize device 1")
        Unload Me
    End If

    Call BASS_ASIO_SetDevice(outdev(0)) 'set the ASIO device to work with
    Call BASS_ASIO_Stop   'stop the device
    Call BASS_ASIO_ChannelReset(0, -1, BASS_ASIO_RESET_ENABLE Or BASS_ASIO_RESET_JOIN) 'disable & unjoin all output channels

    ' Mixer for audio files
    Call BASS_StreamFree(mixer)
    mixer = BASS_Mixer_StreamCreate(BASS_ASIO_GetRate(), 2, BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE)
   
    SplitOutput(0) = BASS_Split_StreamCreate(mixer, BASS_STREAM_DECODE, ByVal 0)
    Call BASS_ChannelSetAttribute(SplitOutput(0), BASS_ATTRIB_BUFFER, 0)
    Call BASS_ChannelStart(SplitOutput(0))
   
    'Mixer for ASIO output (receive mic splitted stream and audio files mixer output)
    Call BASS_StreamFree(mixermic)
    mixermic = BASS_Mixer_StreamCreate(BASS_ASIO_GetRate(), 2, BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE)
    Call BASS_Mixer_StreamAddChannel(mixermic, SplitOutput(0), BASS_MIXER_CHAN_BUFFER)
   
    Call BASS_ASIO_ChannelEnableBASS(False, 0, mixermic, True)
       
    ' Mic stream
    micchan = BASS_StreamCreate(BASS_ASIO_GetRate(), 2, BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE, STREAMPROC_PUSH, 0)
    Call BASS_ASIO_ChannelEnableBASS(BASSTRUE, 0, micchan, BASSTRUE)
       
    SplitMic(0) = BASS_Split_StreamCreate(micchan, BASS_STREAM_DECODE, ByVal 0)
    Call BASS_ChannelSetAttribute(SplitMic(0), BASS_ATTRIB_BUFFER, 0)
    Call BASS_ChannelSlideAttribute(SplitMic(0), BASS_ATTRIB_VOL, 0, 10)
    Call BASS_ChannelStart(SplitMic(0))
   
    Call BASS_Mixer_StreamAddChannel(mixermic, SplitMic(0), BASS_MIXER_CHAN_BUFFER)
   
    Call BASS_ASIO_Start(0, 0)
   
    Dim dev ' NON ASIO device number
    dev = 5
    Call BASS_Init(dev, 44100, 0, 0, 0)
    Call BASS_SetDevice(dev)
    SplitOutput(1) = BASS_Split_StreamCreate(mixer, 0, ByVal 0)
    Call BASS_ChannelSetAttribute(SplitOutput(1), BASS_ATTRIB_BUFFER, 0)
    Call BASS_ChannelStart(SplitOutput(1))
    SplitMic(1) = BASS_Split_StreamCreate(micchan, 0, ByVal 0)
    Call BASS_ChannelSetAttribute(SplitMic(1), BASS_ATTRIB_BUFFER, 0)
    Call BASS_ChannelSlideAttribute(SplitMic(1), BASS_ATTRIB_VOL, 0, 10)
    Call BASS_ChannelStart(SplitMic(1))   
End Sub
Of course, the audio files plays once loaded (from a Commond Dialog), like in the "Multi" project.

Minor question: Is a mixer adding latency ?

About mic volume, I added a push button to set volume to volume setting when push button and 0 when release it. It sometimes make an audio "click", so I changed for:
Code: [Select]
Call BASS_ChannelSlideAttribute(SplitMic(Index), BASS_ATTRIB_VOL, Slider2(Index).value / 100, 100) to get a smooth volume transistion (so no more "click").

If code looks OK, I just have to implent ii (with also condition to switch between "ASIO + NON ASIO" and "NON ASIO + NON ASIO" devices), so again some neurons will die  ;D

Ian @ un4seen

  • Administrator
  • Posts: 25884
Re: Clone "mixed" stream to another output device ?
« Reply #41 on: 4 Jun '24 - 13:41 »
Minor question: Is a mixer adding latency ?

No. When BASS_STREAM_DECODE is set on it, the mixer won't have any buffering, so no extra latency. If the mixer has to resample a source (due to differing sample rates) then there will actually be a small buffer for that, but nothing very significant.

About mic volume, I added a push button to set volume to volume setting when push button and 0 when release it. It sometimes make an audio "click", so I changed for:
Code: [Select]
Call BASS_ChannelSlideAttribute(SplitMic(Index), BASS_ATTRIB_VOL, Slider2(Index).value / 100, 100) to get a smooth volume transistion (so no more "click").

The mixer should automatically ramp its sources' BASS_ATTRIB_VOL changes to avoid clicks, so it shouldn't be necessary to use BASS_ChannelSlideAttribute for that purpose. Are you sure it is?

This doesn't apply to BASS_ATTRIB_VOLDSP changes. If you happen to want to ramp that then using the BASS_BFX_VOLUME effect (which includes ramping) instead will give a smoother result.

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #42 on: 5 Jun '24 - 11:02 »
Hi Ian,
I was getting "clicks" with BASS_ATTRIB_VOLDSP  on split DECODE channels of MIC Input. But with Slide it's OK :)

I'm now trying to implent the test example in JP (the target app), but of course, I get problems (not working AHAH). So I'm trying to build mixer etc one by one and I get big latency to measure playback posiition with BASS_ChannelGetPosition(chan(index), BASS_POS_BYTE) .

Also, to send a mixer output, just have to BASS_ChannelStart(mixer) ? Because I get no playback (and not position measurement) when I play a soruce.

I probably miss something :)

Thanks

Ian @ un4seen

  • Administrator
  • Posts: 25884
Re: Clone "mixed" stream to another output device ?
« Reply #43 on: 5 Jun '24 - 15:06 »
I was getting "clicks" with BASS_ATTRIB_VOLDSP  on split DECODE channels of MIC Input. But with Slide it's OK :)

OK, so you're calling BASS_ChannelSlideAttribute with BASS_ATTRIB_VOLDSP rather than BASS_ATTRIB_VOL? Are you plugging the splitter into a mixer? If so, you could use BASS_ATTRIB_VOL instead, so that the mixer automatically ramps changes to avoid clicks.

Also, to send a mixer output, just have to BASS_ChannelStart(mixer) ? Because I get no playback (and not position measurement) when I play a soruce.

You would use BASS_ChannelStart with normal BASS output but not ASIO. Basically, if a stream has the BASS_STREAM_DECODE flag set then it can't be played with BASS_ChannelStart/Play. If the call is having no effect then perhaps you used it on your ASIO mixer? Check the return value to confirm whether it was successful (and error code if not).

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #44 on: 7 Jun '24 - 04:33 »
Hi Ian,

By doing tons of tests and modifications, I finish to no longer know what I did or didn't, my head is burning :(

I'm re-taking from the beginning the adding mixers etc etc to the project.

I would build a "common" structure with 4 mixers:
- 1 for audio files (MixerSources)
- 1 for mic input (MixerMic)
- 1 for main output device (MixerMain)
- 1 for aux output device (MixerAux)

About aux output device, it will be for example, to send to Virtual Cable, so NON ASIO.

About Mic Input and Main output device, they could be NON ASIO or ASIO devices, so I should only change code before MixerMic and after MixerMain, depending of which device type user choose.

For the moment, I use NON ASIO.

Refering to the nice joined schematic, after some hours of code work, I get now good results: I can set the output volume for each devices (SplitOutDev), and mic volume sent to each mixer before output devices (SplitMic).

I would make the ASIO code part tomorow but now, the duck goes to bed now (AM 5:30, French timezone hahah) !

Ian @ un4seen

  • Administrator
  • Posts: 25884
Re: Clone "mixed" stream to another output device ?
« Reply #45 on: 7 Jun '24 - 15:16 »
Yes, if ASIO would be optional then I would suggest getting everything else working well first, and only add the ASIO stuff (if still needed) after that.

Regarding your latest schematic, are you sure the "MixerMic" is needed, as it doesn't appear to be mixing anything? Couldn't you create the "SplitMic" splitters directly on the recording?

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #46 on: 7 Jun '24 - 17:20 »
I agree, I will see with optional ASIO input, and if possible , I will replace MixerMic by a splitter :)

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #47 on: 12 Jun '24 - 06:05 »
Hi :)

A minor (because I get it only on one XP virtual machine) question:
I measure the level of SplitOutDev (0 or 1) with BASS_ChannelGetLevel and I noticed that it randomly miss measure and returns level at 0 resulting to blinking (off) VU-meters. I get the same with BASS_ChannelGetLevelEx.

If I measure SplitSources(0 or 1) level, no problem.

Different buffer 0 flags are there, here is the code of mixers assembly:

Code: [Select]
    MixerSources = BASS_Mixer_StreamCreate(44100, 2, BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE)
    Call BASS_ChannelSetAttribute(MixerSources, BASS_ATTRIB_BUFFER, 0)

    MixerMic = BASS_Mixer_StreamCreate(44100, 2, BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE)
    Call BASS_ChannelSetAttribute(MixerMic, BASS_ATTRIB_BUFFER, 0)
   
    For nSplit = 0 To 1
        SplitSources(nSplit) = BASS_Split_StreamCreate(MixerSources, BASS_STREAM_DECODE, ByVal 0)
        SplitMic(nSplit) = BASS_Split_StreamCreate(MixerMic, BASS_STREAM_DECODE, ByVal 0)
    Next nSplit
   
    MixerMain = BASS_Mixer_StreamCreate(44100, 2, BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE)
    Call BASS_ChannelSetAttribute(MixerMain, BASS_ATTRIB_BUFFER, 0)
   
    MixerAux = BASS_Mixer_StreamCreate(44100, 2, BASS_SAMPLE_FLOAT Or BASS_STREAM_DECODE)
    Call BASS_ChannelSetAttribute(MixerAux, BASS_ATTRIB_BUFFER, 0)
       
    Call BASS_Mixer_StreamAddChannel(MixerMain, SplitSources(0), BASS_MIXER_CHAN_BUFFER)
    Call BASS_Mixer_StreamAddChannel(MixerAux, SplitSources(1), BASS_MIXER_CHAN_BUFFER)
    Call BASS_Mixer_StreamAddChannel(MixerMain, SplitMic(0), BASS_MIXER_CHAN_BUFFER)
    Call BASS_Mixer_StreamAddChannel(MixerAux, SplitMic(1), BASS_MIXER_CHAN_BUFFER)
       
    Call BASS_SetDevice(OutDev(0))
    SplitOutDev(0) = BASS_Split_StreamCreate(MixerMain, 0, ByVal 0)
    Call BASS_ChannelSetAttribute(SplitOutDev(0), BASS_ATTRIB_BUFFER, 0)
    Call BASS_ChannelStart(SplitOutDev(0))
   
    Call BASS_SetDevice(OutDev(1))
    SplitOutDev(1) = BASS_Split_StreamCreate(MixerAux, 0, ByVal 0)
    Call BASS_ChannelSetAttribute(SplitOutDev(1), BASS_ATTRIB_BUFFER, 0)
    Call BASS_ChannelStart(SplitOutDev(1))

Is there something I missed ?

Ian @ un4seen

  • Administrator
  • Posts: 25884
Re: Clone "mixed" stream to another output device ?
« Reply #48 on: 12 Jun '24 - 13:57 »
That code looks fine, although you could remove the BASS_ATTRIB_BUFFER settings on the streams with BASS_STREAM_DECODE because they have no effect (no playback buffers involved). Does the stream still sound fine (eg. no breaks) when BASS_ChannelGetLevel returns 0 on it? Also, are you customising the BASS_CONFIG_DEV_PERIOD/BASS_CONFIG_DEV_BUFFER/BASS_CONFIG_BUFFER settings or using the defaults?

When you get the level of SplitSources, I guess you use BASS_Mixer_ChannelGetLevel rather than BASS_ChannelGetLevel?

Couin

  • Posts: 118
Re: Clone "mixed" stream to another output device ?
« Reply #49 on: 12 Jun '24 - 21:32 »
I tried with both , no problem with measurement between MixerSources and MixerMain (excepted that with BASS_ChannelGetLevel the audio plays too fast).

Measuring MixerMain output receving zeros but sound still ok (no dropouts).

Ok for removing buffer on DECODE, (but it does not change the zeros problem).