How to catch finishing of playing of hsample,hchannel and/or hmusic

Started by sashakozlovskiy,

sashakozlovskiy

Thank you very mutch for your replies. Yes,i understand,what  BASS_MUSIC_FT2MOD| BASS_MUSIC_FT2PAN flags not improve quality of sound,but improve sound panning for .xm and .mod files. So to improve quality it enough use BASS_SAMPLE_FLOAT|BASS_MUSIC_SINCINTER flags,and for sample only BASS_SAMPLE_FLOAT,or i can do anything else to improve sound quality of playing .xm files? I not noticed problems with sound quality,but my friend said,what open mpt play .xm files more better,than bass,i.e bass have not so clear sound in .xm music,and he ask to me rewrite sound part,using open mpt,but i dont want to do this and hope,what in bass exists features how to improve sound quality for .xm and .mod files . As i understand,BASS_MUSIC_SINCINTER flag not improve sound quality for my friend (i not add BASS_SAMPLE_FLOAT flag,because i not sure,whether it will works ok if,for example,we have 16 bits sound,because according to documentation this flag works with 32 bits and if we wil try increase bitrate of sound,we can get distortion of sound). Also you not reply about BASS_MUSIC_SURROUND and BASS_MUSIC_SURROUND2 flags. What this modes do. What is the ramping of tracks? Also in some xm files first part of track playing with looping,but it should play also second part of track,after silence.

Ian @ un4seen

I would generally recommend using the BASS_MUSIC_SINCINTER + BASS_MUSIC_RAMPS + BASS_SAMPLE_FLOAT flags. But note that old tracker software didn't have sinc interpolation, so if you want it to sound closer to the original then you would remove the BASS_MUSIC_SINCINTER flag. For really old .MOD files (not .XM), you may want to use BASS_MUSIC_NONINTER for no interpolation at all.

BASS_MUSIC_SURROUND and BASS_MUSIC_SURROUND2 apply the surround sound effects from XMPlay. You can try them to see if you may want to use them.

Regarding ramping, from the BASS_MusicLoad documentation:

Quote"Ramping" does not take a lot of extra processing and improves the sound quality by removing clicks, by ramping/smoothing volume and pan changes. The start of a sample may also be ramped-in. That is always the case with XM files (or MOD files in FT2 mode) when using normal ramping, and possibly with all formats when using sensitive ramping; senstitive ramping will only ramp-in when necessary to avoid a click. Generally, normal ramping is recommended for XM files, and sensitive ramping for the other formats, but some XM files may also sound better using sensitive ramping.

sashakozlovskiy

Ok,please,how to play this file with the best quality via bass (change extension on .xm,because page not allow to load this type of files). I also send this file,because i have more serious issue: when i try play it with looping,it play only first part of this file. But we have pause and the second part of this file. How to fix it? Thanks.

Ian @ un4seen

Personally, I would use BASS_MUSIC_SINCINTER + BASS_MUSIC_RAMPS + BASS_SAMPLE_FLOAT flags. But BASS_MUSIC_RAMP alone may be closer to the original FT2 sound.

Regarding the "play only first part of this file" issue, that file contains an "F00" command which means to stop. So BASS will end it at that point (and restart if BASS_SAMPLE_LOOP is set). You can make it jump to the next "order" instead with a mixtime BASS_SYNC_END sync, like this:

BASS_ChannelSetSync(hmusic, BASS_SYNC_END | BASS_SYNC_MIXTIME, 0, EndSyncProc, 0); // set mixtime END sync

...

void CALLBACK EndSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
DWORD order = LOWORD(BASS_ChannelGetPosition(channel, BASS_POS_MUSIC_ORDER | BASS_POS_DECODE)); // get current order position
BASS_ChannelSetPosition(channel, order + 1, BASS_POS_MUSIC_ORDER); // try jumping to the next order
}

If the BASS_ChannelSetPosition call succeeds then playback will continue from that position. Otherwise it will remain ended.

sashakozlovskiy

O thank you very much. May God bless to you and may Saint Xenia of St. Petersburg always  prays for you. Now all works wonderful,i mean now it plays two parts of file. Can you please add this details in some parts of bass documentation and add flag,which allow bass play files while it will be end of file. But i not understand why for getting of position we should use BASS_POS_DECODE,and for setting we not should use this or similar flag and why it not works without BASS_SYNC_MIXTIME flag? Why you not recomended include ft2pan flag to do sound more similar to original? Thank you very much

Ian @ un4seen

The BASS_SYNC_MIXTIME flag means the sync is called immediately when its triggered, instead of it being delayed until its position is heard (which is later due to buffering). Similarly, the BASS_POS_DECODE flag tells BASS_ChannelGetPosition to give the decoder's position instead of the playback/heard position. They are needed in this case so that the position change happens as soon as the end is reached.

Regarding the BASS_MUSIC_FT2PAN flag, you can certainly use it if you want to get closer to the original FT2 sound.

sashakozlovskiy

Hello. In this year i noticed,what bass call crash of my app when i call bass_samplefree or bass_channelfree. This happens,when audio ducking finish callback was called,i.e when ducking was finished and if ducking ms more then track length (because it exists some cases and i not check this situation). Here is my parts of example on c++.
```
#include "bass.h"
static    HSAMPLE h;
static HCHANNEL c;
static void CALLBACK finishCallback(HSYNC handle, DWORD channel, DWORD data, void* user) {
//If we have ducking,if any of this lines will be executed,we will have crash.
   BASS_SampleFree(h);
   BASS_ChannelFree(c);
}
//init and play content
//some function
static void play() {
   if (BASS_Init(-1, 48000, BASS_DEVICE_FREQ, 0, NULL) == 0) {
//error
   }
   //Подключение плагинов
   BASS_PluginLoad("bassmidi.dll", 0);
   //Шрифт для миди
   HSOUNDFONT newfont = BASS_MIDI_FontInit("chorium.sf2", 0);
   if (newfont) {
      BASS_MIDI_FONT sf;
      sf.font = newfont;
      sf.preset = -1; // use all presets
      sf.bank = 0; // use default bank(s)
      BASS_MIDI_StreamSetFonts(0, &sf, 1);    // set default soundfont
      //BASS_MIDI_FontFree(font);             // free old soundfont
   }
   h = BASS_SampleLoad(FALSE, "title.ogg", 0, 0, 1, BASS_SAMPLE_FLOAT);
   c = BASS_SampleGetChannel(h, BASS_SAMCHAN_STREAM | BASS_SAMCHAN_NEW);
   BASS_ChannelSetAttribute(c, BASS_ATTRIB_VOL, 1.0f);
   BASS_ChannelSetSync(c, /*BASS_SYNC_ONETIME |*/ BASS_SYNC_MIXTIME | BASS_SYNC_END, 0, finishCallback, 0);
   BASS_ChannelSetSync(c, BASS_SYNC_SLIDE, 0, finishCallback, 0);
   BASS_ChannelSlideAttribute(c, BASS_ATTRIB_VOL, -1.0f, 7000);
   BASS_ChannelPlay(c, false);
}
```

In fact if playing was finished,i not free channel/hsample,but i created it as sample. When firstly playing is finished,and callback call first time,there is no crash,but at the second time,when ducking was finished,we have this crash. It also strange,when if i delete two lines,connected with callbacks and write :
```
ASS_ChannelSetSync(c, BASS_SYNC_MIXTIME | BASS_SYNC_END| BASS_SYNC_SLIDE, 0, finishCallback, 0);
```
There is no callback executed.
I have crash on windows 11 in mfc c++ application with visual studio. You can upload file,which i play,at https://disk.yandex.com/d/pJCJfnKyaW_pdw. Thank you very much for your help.

Ian @ un4seen

Quote from: sashakozlovskiystatic void CALLBACK finishCallback(HSYNC handle, DWORD channel, DWORD data, void* user) {
//If we have ducking,if any of this lines will be executed,we will have crash.
   BASS_SampleFree(h);
   BASS_ChannelFree(c);
}
...
   BASS_ChannelSetSync(c, /*BASS_SYNC_ONETIME |*/ BASS_SYNC_MIXTIME | BASS_SYNC_END, 0, finishCallback, 0);

It isn't safe to free a BASS channel within its own mixtime SYNCPROC callback. Removing the BASS_SYNC_MIXTIME flag from the BASS_ChannelSetSync call should prevent the crash.

Quote from: sashakozlovskiyIt also strange,when if i delete two lines,connected with callbacks and write :
```
ASS_ChannelSetSync(c, BASS_SYNC_MIXTIME | BASS_SYNC_END| BASS_SYNC_SLIDE, 0, finishCallback, 0);
```
There is no callback executed.

It isn't possible to have a single sync apply to multiple sync types, eg. BASS_SYNC_END and BASS_SYNC_SLIDE. A separate BASS_ChannelSetSync call is needed for each one.

sashakozlovskiy

But,as you remember,i can't avoid using mixtime flag. Also before track,which i wrote,all was ok. Why crash hapens only when ducking callback used,i.e without ducking all ok. Also it's ok,if ducking in ms less  (probably and equal) than track length-current_position_in_ms. I think,it's a bass issue,because before it wass ok. Whether this crash reproduceable with my file and example of code (you can insert this code in any c++ application and use this track). How i can report this issue to bass,because,as i wrote,it happens only when we use callback,which allow to us catch end of audio ducking and it actual not for all tracks. Also it very strange,what bass_channelfree call crash even if it was called before for this channel. Also bass_samplefree flag cal crash in this case.

Ian @ un4seen

As noted in the SYNCPROC documentation, a mixtime SYNCPROC has similar restrictions in what functions are safe to call within it as a STREAMPROC does, and BASS_ChannelFree (on the same handle) is one of the unsafe functions. BASS_SampleFree too in this case because that frees all of the sample's channels.

Are you sure you need the BASS_SYNC_END sync to be mixtime? Note that a mixtime BASS_SYNC_END sync is called before the end is heard (due to buffering), so you won't hear the whole file if you free the channel then. But if you're certain that you want to free it then, you can add the BASS_SYNC_THREAD flag to allow that.

sashakozlovskiy

Yes,i need in it (please see previous posts,in whiich i wrote about issue,when file played partially,and you wrote,what it connected with some command 0ff (https://www.un4seen.com/forum/?topic=20037.msg140533#msg140533)). Also i need catch callback for each loop. Yes,i can use autofree flag,but i dont want to free it always,so do it inside callback - best solution for me. line             BASS_ChannelSetSync(back_channel, /*BASS_SYNC_ONETIME |*/ BASS_SYNC_MIXTIME | BASS_SYNC_THREAD|BASS_SYNC_END, 0, finishCallback, 0); helps me,but i not sure,what it will works for all cases. In my opinion it bass issue,which should be fixed because:
1. This happends,when we use callback for end of playing and for ducking (if we use callback only for end of playing,it seems we haven't this crash).
2. This happens only for track,which i send or,probably,for tracks,which have ducking interval more (or equals too,not sure) than trackLengthInMs-currentPositionInMs. In other cases,it seems,crash not happens,except,probably,some cases,because i am not sure,but it seems,what sometimes crash happens too,but this cases,about which i wrote before,it cases,in which with almost 100 percent probability i have crash.
3. This happens,even if hchannel/hsample was freed before (at least in my tests i noticed this). So,if you have explanation,why in this three cases we have crash,i want to know it. Because before,when i havent this cases,i havent any crashes.

Chris

Another possible Option can be in the Syncproc to do only a a PostMessage
and then in the MessageHandler to free the Channels.

sashakozlovskiy

Ok. So you haven't explanation,why this crash happens only for specific cases? Can you please provide example,how to use PostMessage and catch end of playing/end of ducking at the same time. For now i use BASS_SYNC_THREAD flag inside callback,as i wrote before,and it seems,what it works ok,but whether it guaranty behaviour,i.e whether it will be no crash. Also please look at my example to know,whether it possible fix something in bass,because crash happens,as i wrote before,only in several conditions. Also please fix issue,about which you reply to me at https://www.un4seen.com/forum/?topic=20037.msg140533#msg140533,because,in my opinion,it should work without any trick or please add this example in bass documentation/basss examples,to any person,who have this or similar problems,can solve this problems,because if you wasn't help to me,i probably not fixed this issue or rewrote my code to use other library,instead of bass,but thanks to your help i solved partially playing issue and now all ok,so it should be documented,if bass not play all files fully without any tricks. If you have already added it in bass documentation,thank you very much for this.

Ian @ un4seen

The code you posted above will crash because it's freeing a BASS channel within its own mixtime SYNCPROC. BASS_SYNC_THREAD (and PostMessage) will move the sync code to a different thread, which makes it safe to free the channel in it. This is noted in the SYNCPROC documentation, so I don't think there's any great mystery here. If you're getting an unexplained crash in another case (without that SYNCPROC) then please post that code.

sashakozlovskiy

Yes,i understand,and now with BASS_SYNC_THREAD flag it seems i haven't this crash. But,as i wrote before,it crash only in several cases,but it should crash always without BASS_SYNC_THREAD flag.

sashakozlovskiy

Yes,i noticed,what with bass_mixtime flag bass behaviour is sometimes incorrect,e.g file plays partially,etc. But if i delete this flag,i will have problems with some files,which played partially (see messages above)? Whether i should create two separate callbacks for this (one with mixtime,and second without it),or it exists more better solution? This solution should works for loops too,i.e for each loop callback should call too,if we have loops,as it works now. If not,whether function for callback with mixtime will call guaranty first? Thanks.

Ian @ un4seen

If you're using the mixtime BASS_SYNC_END sync for looping and would like to stop looping at some point, then you can simply have the SYNCPROC do nothing at that point:

void CALLBACK EndSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
if (loop_enabled) BASS_ChannelSetPosition(channel, loop_start, BASS_POS_BYTE);
}

Make sure you don't have the BASS_SAMPLE_LOOP flag set, otherwise it'll loop even if you don't call BASS_ChannelSetPosition there. If you want to free the stream at the end then use the BASS_STREAM_AUTOFREE flag for that (don't call BASS_ChannelFree in the SYNCPROC).

sashakozlovskiy

Ok,i mean if file have continuation we should use mixtime flag,to catch end of buffering of it,but if this file haven't continuation,or second and other parts of this file was played,it stops,because i free resources. But in this case,as you wrote before,and i noticed it too,file can play not fully,because with mixtime flag finish_callback calls when buffering was finished,but not playing. So i asked you,how to solve this problem,i.e should i create separate syncprocs with mixtime flag,and without it,to catch firstly end of buffering,to continue playing,or it can be solved more simpler. To you can understand what i mean,you can read your explanation of situation at https://www.un4seen.com/forum/?topic=20037.msg140533#msg140533. Thanks.

Ian @ un4seen

The code in that linked post should work fine with the code/info in my last post, only the BASS_ChannelSetPosition call is different. Note you should not use BASS_SYNC_THREAD (or PostMessage) when looping in the SYNCPROC (that was just to allow you to free the channel in the SYNCPROC).

sashakozlovskiy

Ok,but why when i use mixtime flag,my file play not fully (i mean situation without looping). You confirmed before,what i will have problems with this flag (https://www.un4seen.com/forum/?topic=20037.msg142377#msg142377).