Author Topic: Set a stream priority  (Read 268 times)

teq

  • Posts: 26
Set a stream priority
« on: 18 Nov '18 - 09:45 »
I use Bass.Net in Unity, and my player has metronome option.
My main song channel
Code: [Select]
netStream = Bass.BASS_StreamCreateURL(Uri.EscapeUriString(CommonSettings.Instance.assetBundlesURL + model.clipName.ToLower() + ".mp3"),
                                                          0,
                                                          BASSFlag.BASS_STREAM_DECODE,
                                                          _trackDownloadProc,
                                                          IntPtr.Zero);
streamTempoFX = BassFx.BASS_FX_TempoCreate(streamingTrack ? netStream : stream, BASSFlag.BASS_FX_FREESOURCE);
Metronome stream
Code: [Select]
metronomeStream = Bass.BASS_StreamCreateFile(_clickHGCFile.AddrOfPinnedObject(),
                                                     0L, clickBytes.Length, BASSFlag.BASS_SAMPLE_FLOAT);

Independent thread for metronome
Code: [Select]
private async void Infinite()
    {
        while (infiniteLoopEnabled)
        {
            await Task.Delay(300);

            Bass.BASS_ChannelPlay(metronomeStream, true);
        }
    }

UI has some CG allocations which triggers some lags, and they are not affecting main channel, but metrome lags with them

I thinks it's because tracks is already loaded and due to his not affecting by garbage collector, but metronome click is every time Play in cycle.

May be i need to use another flags or somehow set priority?
« Last Edit: 18 Nov '18 - 12:05 by teq »

Ian @ un4seen

  • Administrator
  • Posts: 21370
Re: Set a stream priority
« Reply #1 on: 19 Nov '18 - 13:41 »
You could use a mixer and BASS_SYNC_POS syncs to precisely time the metronome playbacks, something like this:

Code: [Select]
BASS_CHANNELINFO info;
BASS_ChannelGetInfo(metronomeStream, &info); // get metronome sample format
metronomemixer = BASS_Mixer_StreamCreate(info.freq, info.chans, BASS_SAMPLE_FLOAT | BASS_MIXER_NONSTOP); // create non-stop mixer with same format
BASS_Mixer_StreamAddChannel(metronomemixer, metronomeStream, BASS_MIXER_NORAMPIN); // plug metronome into mixer
QWORD syncpos = BASS_ChannelSeconds2Bytes(metronomemixer, 0.3); // repeat playback position (300ms)
BASS_ChannelSetSync(metronomemixer, BASS_SYNC_POS | BASS_SYNC_MIXTIME | BASS_SYNC_ONETIME, syncpos, MetronomeSyncProc, NULL); // set a sync there
BASS_ChannelPlay(metronomemixer, 0); // start the mixer

...

void CALLBACK MetronomeSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
BASS_ChannelSetPosition(metronomeStream, 0, BASS_POS_BYTE); // rewind metronome sound
QWORD syncpos = BASS_ChannelGetPosition(channel, BASS_POS_BYTE | BASS_POS_DECODE); // get mixer's current position
syncpos += BASS_ChannelSeconds2Bytes(metronomemixer, 0.3); // next playback position
BASS_ChannelSetSync(metronomemixer, BASS_SYNC_POS | BASS_SYNC_MIXTIME | BASS_SYNC_ONETIME, syncpos, MetronomeSyncProc, NULL); // set a sync there
}

Please see the documentation for details on the mentioned functions. Note you will also need to add the BASS_STREAM_DECODE flag to the metronome sound's BASS_StreamCreateFile call.

teq

  • Posts: 26
Re: Set a stream priority
« Reply #2 on: 19 Nov '18 - 19:39 »
You could use a mixer and BASS_SYNC_POS syncs to precisely time the metronome playbacks, something like this:

Code: [Select]
BASS_CHANNELINFO info;
BASS_ChannelGetInfo(metronomeStream, &info); // get metronome sample format
metronomemixer = BASS_Mixer_StreamCreate(info.freq, info.chans, BASS_SAMPLE_FLOAT | BASS_MIXER_NONSTOP); // create non-stop mixer with same format
BASS_Mixer_StreamAddChannel(metronomemixer, metronomeStream, BASS_MIXER_NORAMPIN); // plug metronome into mixer
QWORD syncpos = BASS_ChannelSeconds2Bytes(metronomemixer, 0.3); // repeat playback position (300ms)
BASS_ChannelSetSync(metronomemixer, BASS_SYNC_POS | BASS_SYNC_MIXTIME | BASS_SYNC_ONETIME, syncpos, MetronomeSyncProc, NULL); // set a sync there
BASS_ChannelPlay(metronomemixer, 0); // start the mixer

...

void CALLBACK MetronomeSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
BASS_ChannelSetPosition(metronomeStream, 0, BASS_POS_BYTE); // rewind metronome sound
QWORD syncpos = BASS_ChannelGetPosition(channel, BASS_POS_BYTE | BASS_POS_DECODE); // get mixer's current position
syncpos += BASS_ChannelSeconds2Bytes(metronomemixer, 0.3); // next playback position
BASS_ChannelSetSync(metronomemixer, BASS_SYNC_POS | BASS_SYNC_MIXTIME | BASS_SYNC_ONETIME, syncpos, MetronomeSyncProc, NULL); // set a sync there
}

Please see the documentation for details on the mentioned functions. Note you will also need to add the BASS_STREAM_DECODE flag to the metronome sound's BASS_StreamCreateFile call.

Thanks again! It works like a charm!

teq

  • Posts: 26
Re: Set a stream priority
« Reply #3 on: 20 Nov '18 - 10:34 »
You could use a mixer and BASS_SYNC_POS syncs to precisely time the metronome playbacks, something like this:

Code: [Select]
BASS_CHANNELINFO info;
BASS_ChannelGetInfo(metronomeStream, &info); // get metronome sample format
metronomemixer = BASS_Mixer_StreamCreate(info.freq, info.chans, BASS_SAMPLE_FLOAT | BASS_MIXER_NONSTOP); // create non-stop mixer with same format
BASS_Mixer_StreamAddChannel(metronomemixer, metronomeStream, BASS_MIXER_NORAMPIN); // plug metronome into mixer
QWORD syncpos = BASS_ChannelSeconds2Bytes(metronomemixer, 0.3); // repeat playback position (300ms)
BASS_ChannelSetSync(metronomemixer, BASS_SYNC_POS | BASS_SYNC_MIXTIME | BASS_SYNC_ONETIME, syncpos, MetronomeSyncProc, NULL); // set a sync there
BASS_ChannelPlay(metronomemixer, 0); // start the mixer

...

void CALLBACK MetronomeSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
BASS_ChannelSetPosition(metronomeStream, 0, BASS_POS_BYTE); // rewind metronome sound
QWORD syncpos = BASS_ChannelGetPosition(channel, BASS_POS_BYTE | BASS_POS_DECODE); // get mixer's current position
syncpos += BASS_ChannelSeconds2Bytes(metronomemixer, 0.3); // next playback position
BASS_ChannelSetSync(metronomemixer, BASS_SYNC_POS | BASS_SYNC_MIXTIME | BASS_SYNC_ONETIME, syncpos, MetronomeSyncProc, NULL); // set a sync there
}

Please see the documentation for details on the mentioned functions. Note you will also need to add the BASS_STREAM_DECODE flag to the metronome sound's BASS_StreamCreateFile call.

Can't figure one moment. How to instantly play metronome sound (not waiting first n seconds) ?
And how to reset that sync? So user has one bit per 5 seconds, he off/on or change metronome tempo and it must be restarted with new value (so i need to interrupt started sync)

And i need to use  Bass.BASS_ChannelSetSync or BassMix.BASS_Mixer_ChannelSetSync ?

UPDATE
All done. I just used this before initial play
Code: [Select]
Bass.BASS_ChannelSetPosition(metronomeStream, 0, BASSMode.BASS_POS_BYTE);
and made a reset method
Code: [Select]
Bass.BASS_ChannelRemoveSync(metronomeMixer, metronomeMixerSync);
Bass.BASS_ChannelStop(metronomeMixer);
Bass.BASS_StreamFree(metronomeMixer);
metronomeMixer = 0;

But one question is still remains: can i somehow sync when track is actually started ?
« Last Edit: 20 Nov '18 - 15:28 by teq »

teq

  • Posts: 26
Re: Set a stream priority
« Reply #4 on: 21 Nov '18 - 15:13 »
By the way is BASS_ChannelSetAttribute apply instantly or with delay ? I can't sync metronome with tempo, cause seems that i set both, metronome applies instantly but tempo fx is not

Ian @ un4seen

  • Administrator
  • Posts: 21370
Re: Set a stream priority
« Reply #5 on: 21 Nov '18 - 16:22 »
What attribute are you changing? BASS_ATTRIB_FREQ/PAN/VOL changes will be instant on normal playback channels, ie. those without the BASS_STREAM_DECODE flag set. In this case, that means changes will be instant on the mixer (metronomeMixer) but probably not on the metronome (metronomeStream) due to buffering. Most other attribute changes will generally be delayed in both cases (again due to buffering).

teq

  • Posts: 26
Re: Set a stream priority
« Reply #6 on: 21 Nov '18 - 17:54 »
What attribute are you changing? BASS_ATTRIB_FREQ/PAN/VOL changes will be instant on normal playback channels, ie. those without the BASS_STREAM_DECODE flag set. In this case, that means changes will be instant on the mixer (metronomeMixer) but probably not on the metronome (metronomeStream) due to buffering. Most other attribute changes will generally be delayed in both cases (again due to buffering).
I mean tempo of the main track. So i change it's speed, and then metronome bpm, but seems that tempo changing produced with some delay and song becomes async regarding metronome

And i can't check when actually click starts playing. So i debug in MetronomeSyncProc method, but click play after some delay
« Last Edit: 21 Nov '18 - 18:54 by teq »

Ian @ un4seen

  • Administrator
  • Posts: 21370
Re: Set a stream priority
« Reply #7 on: 22 Nov '18 - 17:38 »
So you're using the BASS_ATTRIB_TEMPO attribute? What type of stream are you using it on? In the metronome's case, I assume you are just changing the playback/sync interval rather than using BASS_FX tempo processing on it.