BASS_ChannelGetData from a mixer?

Started by Couin,

Couin

Hi :)

I built a stream caster and I used BASS_ChannelGetData to make an oscilloscope based on Maverick's code, after some code fix, here is a good result:
oscillogood.jpg

and I want to implent the same oscilloscope in another project, but instead of getting datas from input soundcard, I would get them from a splitted outpout of MixerAux (I have two mixers in the app).

My splitted output code:Call BASS_SetConfig(BASS_CONFIG_DEV_NONSTOP, 1)
Call BASS_Init(OutDev(1), MixerFreq, 0, frmMain.hwnd, 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))

If I set:BASS_ChannelGetData SplitOutDev(0), SampleData(0), nDataSizeI get no good result (I get only a small part of left channel of oscilloscope):
oscillo.jpg

What could be the problem?

Thanks :)


Ian @ un4seen

It looks like you're using different handles in those calls, ie. SplitOutDev(0) vs SplitOutDev(1). Is that intentional or just a typo? If it's intentional, please also show how SplitOutDev(0) is created.

Couin

Hi Ian :)

Sorry it's a typo. I would get datas from SplitOutDev(1).

I join here a diagram of splitters/mixers:
BASS Mixers.jpg

I would purpose possibility to encode SplitOutDev(1) encode to wav (fot saving to file) and as mp3 (for streaming to Icecast server), in place of AUX Output (Virtual Cable).
And to see the signal quality, I would have the oscilloscope plugged on SplitOutDev(1).

BASS_ChannelGetData SplitOutDev(0), SampleData(0), nDataSize(where nDataSize = 3000), makes drawing the second oscilloscope screenshot, and add latency and strange playback to the sound on both SplitOutDev.
I tried BASS_Mixer_ChannelGetData, I get Error 5.

Ian @ un4seen

That looks like the splitter isn't really needed, and you could play MixerAux directly instead? But the splitter should work too. How much data is the BASS_ChannelGetData call delivering, ie. what's the return value? Does it vary?

If you set a WAV writer (BASS_Encode_StartPCMFile) on the splitter or MixerAux, does the written WAV file look correct?

Couin

#4
Hi Ian :)

I needed to add splitters to mixers outputs because I would be able do change audio device without restarting the software.

About return values, with a Timer of 10 (in fact 16 ms, in VB6) interval, with this code:
Debug.Print BASS_ChannelGetData(SplitOutDev(0), ByVal 0, BASS_DATA_AVAILABLE)(Don't take care about SplitOutDev(0) or (1), because I'm making tests with the main mixer), here is a sample of returned values:
Quote15712
15448
15136
14904
15120
14288
17320
I joint a capture of SampleData array for BASS_ChannelGetData lenght = 200
SampleData capture SplitOutDev(0).zip

I tried with adding another splitted stream to the (main, for the moment) mixer:
SplitOutDevScope = BASS_Split_StreamCreate(MixerMain, 0, ByVal 0)
Call BASS_ChannelSetAttribute(SplitOutDevScope, BASS_ATTRIB_BUFFER, 0)
Call BASS_ChannelSlideAttribute(SplitOutDevScope, BASS_ATTRIB_VOLDSP, 0, 0)
Call BASS_ChannelStart(SplitOutDevScope)

Here is what the scopes give me:
scopes Splitoutdevscope.jpg
Of course, waveform is random, it's like binary signal before a DAC (Digital to Analog Converter) like when we put aan oscilloscope probe of a bits input of DAC1408 of some Gottlieb's 80 pinball soundcards like B lack Hole, Haunted House...
Also, this is not logical, as well as I set the Splitoutdevscope vol to 0.

Recording as wav file from SplitOutDev(0) is OK.

Ian @ un4seen

Quote from: CouinAbout return values, with a Timer of 10 (in fact 16 ms, in VB6) interval, with this code:
Debug.Print BASS_ChannelGetData(SplitOutDev(0), ByVal 0, BASS_DATA_AVAILABLE)(Don't take care about SplitOutDev(0) or (1), because I'm making tests with the main mixer), here is a sample of returned values:
Quote15712
15448
15136
14904
15120
14288
17320

To hopefully get some clues on the almost empty oscilloscope problem, please check the return values of the BASS_ChannelGetData call (on SplitOutDev(1)?) that you're using in that. Specifically, how does the return value compare to your "length" parameter? Also set the WAV writer on the splitter in that call to check what data it's receiving.

Quote from: CouinHere is what the scopes give me:
scopes Splitoutdevscope.jpg

That waveform looks like you may be mixing sample formats there. The code in the old post you linked is expecting 16-bit integer. Have you changed that code, and what format is your data?

Couin

Hi :)

Debug.Print BASS_ChannelGetData(SplitOutDev(0), SampleData(0), nDataSize)Returns 2000 (as well as nDataSize = 2000).

Quote from: Ian @ un4seenAlso set the WAV writer on the splitter in that call to check what data it's receiving.
I have difficulties to understand, what do you mean exactly?

The wav writing of my previous message (#4) is done with two buttons (one for WavWriter = BASS_Encode_StartPCMFile(SplitOutDev(0), 0, App.path & "\record.wav") and the other to BASS_Encode_Stop (WavWriter)There is a new ununderstandable thing :( : This morning, it gaves me this file format:
QuoteFormat                      : Wave
Format settings             : PcmWaveformat
File size                   : 397 KiB
Duration                    : 2 s 306 ms
Overall bit rate mode       : Constant
Overall bit rate            : 1 411 kb/s

Audio
Format                      : PCM
Format settings             : Little / Signed
Codec ID                    : 1
Duration                    : 2 s 306 ms
Bit rate mode               : Constant
Bit rate                    : 1 411.2 kb/s
Channel(s)                  : 2 channels
Sampling rate               : 44.1 kHz
Bit depth                   : 16 bits
Stream size                 : 397 KiB (100%)

This afternoon, after sleeping (working by night), without any change, it gives:
QuoteFormat                      : Wave
Format settings             : PcmWaveformat
File size                   : 1.61 MiB
Duration                    : 4 s 785 ms
Overall bit rate mode       : Constant
Overall bit rate            : 2 822 kb/s

Audio
Format                      : PCM
Format profile              : Float
Codec ID                    : 3
Codec ID/Hint               : IEEE
Duration                    : 4 s 785 ms
Bit rate mode               : Constant
Bit rate                    : 2 822 kb/s
Channel(s)                  : 2 channels
Sampling rate               : 44.1 kHz
Bit depth                   : 32 bits
Stream size                 : 1.61 MiB (100%)

I don't understand why :(



Quote from: Ian @ un4seenThat waveform looks like you may be mixing sample formats there. The code in the old post you linked is expecting 16-bit integer. Have you changed that code, and what format is your data?
Do you talk about Maverick's code (link)? I just changed some code in the For loop.
But I use the same (changed) code in my other app (to stream and record from input device) and all is OK.
nDataSize = 2000

Dim SampleData() As Integer
ReDim SampleData(nDataSize)

BASS_ChannelGetData recording, SampleData(0), nDataSize

'left channel
If ScopeFreeze(0) = False Then
PicSpectrum(0).Cls
For iScope = 0 To nDataSize / 2 - 1 Step 2
ScopeY1 = ((VolGain * SampleData(iScope) + 32767) / 65535 * TraceHeight)
ScopeX = (TraceWidth * iScope * 2) / nDataSize
If iScope = 0 Then PicSpectrum(0).PSet (0, ScopeY1)
PicSpectrum(0).Line -(ScopeX, ScopeY1), ScopeColor
Next
End If

'right channel
If ScopeFreeze(1) = False Then
PicSpectrum(1).Cls
For iScope = 1 To nDataSize / 2 Step 2
ScopeY2 = ((VolGain * SampleData(iScope) + 32767) / 65535 * TraceHeight)
ScopeX = (TraceWidth * iScope) / (nDataSize / 2)
If iScope = 1 Then PicSpectrum(1).PSet (0, ScopeY2)
PicSpectrum(1).Line -(ScopeX, ScopeY2), ScopeColor
Next
End If

Ian @ un4seen

Quote from: CouinDebug.Print BASS_ChannelGetData(SplitOutDev(0), SampleData(0), nDataSize)Returns 2000 (as well as nDataSize = 2000).

Is that the BASS_ChannelGetData call that's providing the data for the troublesome oscilloscope display in the first post? If so, that means most of the data is 0s?

Quote from: Couin
Quote from: Ian @ un4seenAlso set the WAV writer on the splitter in that call to check what data it's receiving.
I have difficulties to understand, what do you mean exactly?

The wav writing of my previous message (#4) is done with two buttons (one for
WavWriter = BASS_Encode_StartPCMFile(SplitOutDev(0), 0, App.path & "\record.wav") and the other to
BASS_Encode_Stop (WavWriter)

Yes, that (BASS_Encode_StartPCMFile) is what I meant, but make sure you use the same handle as in the oscilloscope display. You want the WAV file to contain the same data as the oscilloscope is displaying. And then load the WAV file in a sample editor and check if it has gaps too (like in your oscilloscope).

Quote from: CouinThere is a new ununderstandable thing :( : This morning, it gaves me this file format:
QuoteFormat                      : Wave
Format settings            : PcmWaveformat
File size                  : 397 KiB
Duration                    : 2 s 306 ms
Overall bit rate mode      : Constant
Overall bit rate            : 1 411 kb/s

Audio
Format                      : PCM
Format settings            : Little / Signed
Codec ID                    : 1
Duration                    : 2 s 306 ms
Bit rate mode              : Constant
Bit rate                    : 1 411.2 kb/s
Channel(s)                  : 2 channels
Sampling rate              : 44.1 kHz
Bit depth                  : 16 bits
Stream size                : 397 KiB (100%)

This afternoon, after sleeping (working by night), without any change, it gives:
QuoteFormat                      : Wave
Format settings            : PcmWaveformat
File size                  : 1.61 MiB
Duration                    : 4 s 785 ms
Overall bit rate mode      : Constant
Overall bit rate            : 2 822 kb/s

Audio
Format                      : PCM
Format profile              : Float
Codec ID                    : 3
Codec ID/Hint              : IEEE
Duration                    : 4 s 785 ms
Bit rate mode              : Constant
Bit rate                    : 2 822 kb/s
Channel(s)                  : 2 channels
Sampling rate              : 44.1 kHz
Bit depth                  : 32 bits
Stream size                : 1.61 MiB (100%)

I don't understand why :(

I guess you must have set the WAV writer on a different stream in each case? The first is 16-bit, while the 2nd is floating-point. The floating-point data could explain your 2nd dodgy oscilloscope display.

Quote from: CouinnDataSize = 2000

Dim SampleData() As Integer
...

Right, so it's still expecting 16-bit data. If you would like to use floating-point data instead, it should only need a few small changes:

nDataSize = 2000

Dim SampleData() As Single ' changed
ReDim SampleData(nDataSize)

BASS_ChannelGetData recording, SampleData(0), nDataSize

'left channel
If ScopeFreeze(0) = False Then
    PicSpectrum(0).Cls
    For iScope = 0 To nDataSize / 4 - 1 Step 2 ' changed
        ScopeY1 = ((VolGain * SampleData(iScope) + 1) / 2 * TraceHeight) ' changed
        ScopeX = (TraceWidth * iScope * 2) / nDataSize
        If iScope = 0 Then PicSpectrum(0).PSet (0, ScopeY1)
        PicSpectrum(0).Line -(ScopeX, ScopeY1), ScopeColor
    Next
End If

'right channel
If ScopeFreeze(1) = False Then
    PicSpectrum(1).Cls
    For iScope = 1 To nDataSize / 4 Step 2 ' changed
        ScopeY2 = ((VolGain * SampleData(iScope) + 1) / 2 * TraceHeight) ' changed
        ScopeX = (TraceWidth * iScope) / (nDataSize / 2)
        If iScope = 1 Then PicSpectrum(1).PSet (0, ScopeY2)
        PicSpectrum(1).Line -(ScopeX, ScopeY2), ScopeColor
    Next
End If

Couin

Hi Ian,

Yes, wav writer was on the same stream, and was OK.

Changing SampleData to Single gives better results !

With changes, only the first horizontal half of scopes was drawing the waveforms, the right half was at 0.

After some analyzing of returned datas, I rewrote the code:
    nDataSize = 4000

    Dim SampleData() As Single
    ReDim SampleData(nDataSize)

    Call BASS_ChannelGetData(SplitOutDev(0), SampleData(0), nDataSize)

    If ScopeFreeze(0) = False Then
        PicSpectrum(0).Cls
        For iScope = 0 To nDataSize / 4 - 1 Step 2
            ScopeY1 = (SampleData(iScope) + 1) / 2 * TraceHeight
            ScopeX = TraceWidth * iScope / (nDataSize / 4 - 1)
            If iScope = 0 Then PicSpectrum(0).PSet (0, ScopeY1)
            PicSpectrum(0).Line -(ScopeX, ScopeY1), ScopeColor
        Next
    End If

    If ScopeFreeze(1) = False Then
        PicSpectrum(1).Cls
        For iScope = 1 To nDataSize / 4 Step 2
            ScopeY2 = (SampleData(iScope) + 1) / 2 * TraceHeight
            ScopeX = TraceWidth * iScope / (nDataSize / 4)
            If iScope = 0 Then PicSpectrum(1).PSet (0, ScopeY2)
            PicSpectrum(1).Line -(ScopeX, ScopeY2), ScopeColor
        Next
    End If
And now it's OK.

I made a video capture where I'm running my other software (stream caster) and the software where I implented the oscilloscpes:
https://www.youtube.com/watch?v=IKXnPJrwuJQ
The left oscilloscopes are the actual project, where I play a track, the right oscilloscopes are of the caster (that is set to listen the PC's speakers). We can see that waveforms are similar :)

Thanks again for great help :)