Author Topic: PRESCAN in the Background?  (Read 4031 times)

emiliojazz

  • Posts: 81
PRESCAN in the Background?
« on: 15 Nov '07 - 22:56 »
Hi Ian!!
I'm back from a lot of programming days, working with your wonderful BASS library!

I have a new "exciting" question: is it possible to apply prescanning (BASS_STREAM_PRESCAN)
in the background? So, for example, let the user ABORT the preloading of a stream?
I think the BASS_StreamCreateFile should be called in a separate thread, but at this point
is possible to cancel it?
I have the following situation: a scrollable playlist when the user can select the songs, and then the software
preloads it (BASS_StreamCreateFile). Obviously it will be done after a short period of time, allowing
the user to scroll the list faster without preloading. But if the user stops on a large mp3 file (and then wants to go on), it will freeze
the application...is possible to avoid this? (and so do a background stream-creation...)

thank you so much!
Emiliano Paterlini

Ian @ un4seen

  • Administrator
  • Posts: 20437
Re: PRESCAN in the Background?
« Reply #1 on: 17 Nov '07 - 13:30 »
I'm afraid there isn't any way to abort the prescanning, as you do not yet have a handle that could be used to do such a thing :)

I'll see if I can work something out for 2.4. In the meantime, what you could do is create a new thread for each BASS_StreamCreateFile call, and have the thread free the stream straight after creation if it has been cancelled.

emiliojazz

  • Posts: 81
Re: PRESCAN in the Background?
« Reply #2 on: 31 Mar '08 - 12:33 »
Hi Ian,
I've done the way you suggested in the message above.
It seemed a good solution, but after a testing period the way of creating
a new thread (with medium-low priority) for each BASS_StreamCreateFile call
proofed to be weak. The main disadvantage is that it can be a moment when
up to 8/10 stream creation are executing, so the system starts to be veeeery
sloooow! Even if the threads' priorities are set to low values.
I describe now to you the scenario that I have:
unfortunately I'm not working in a PC-Mode....or in an operating system mode
(talking about user interface).
I built a standalone system that plays/records midi and audio files.
The user can scroll up/down the playlist, but when he stops for a 300/400 milliseconds
over a song, I must preload that song in order to ensure that it starts *immediately" when
the user presses PLAY. The problem arises if the cursor stays for a period of time on the song sufficient
that preload begins. At this point, I must allow the user to change the cursor, even if a preload is in act.
So I must found an efficient and stable way to abort the preloading.
I implemented the "preload aborting" in all the software that is my own. Remains only the call to BASS_StreamCreate File to be "resolved". I think that an elegant way would be create a special function "BASS_StreamCreateFileThread", that returns immediately a temporary handle for "aborting" purposes, and internally starts a thread that do the BASS_StreamCreateFile.
At this point another function is needed: BASS_StreamFreeThread, passing it the temporary handle that BASS_StreamCreateFileThread passed. So you are able to abort your StreamCreateFile function.
Is that difficult? I realize that maybe I am the only person who asked you this feature...see you if U can solve this problem for me...

Ah, I forgot to mention...the parameters passed to BASS_StreamCreateFileThread should be the same of BASS_StreamCreateFile *plus* a pointer to a HSTREAM variable that you will use to store the return value of BASS_StreamCreateFile once it has completed.
« Last Edit: 31 Mar '08 - 12:37 by emiliojazz »

Ian @ un4seen

  • Administrator
  • Posts: 20437
Re: PRESCAN in the Background?
« Reply #3 on: 31 Mar '08 - 18:02 »
I don't really like the idea of functions just to abort prescanning of MPEG files; I prefer functions to have a wider scope than that. An alternative idea would be an "abort thread" function, which would abort the creation of any type of stream (inc. internet & user file) by a particular thread, but I'm not sure how well that would be received by add-ons. It would need some looking into, but I don't really want to delay the 2.4 release any further now; perhaps something for a future release.

Are you sure you really need to use the PRESCAN flag though, eg. are you using it for custom looping purposes?

If you're just using it for exact seeking/length, perhaps you could create a normal stream to start playback with and also create a PRESCAN one in the background (in another thread). Once the PRESCAN stream is created you can switch to that and free the original non-PRESCAN stream. You could still use your existing cancellation system but, as you only create the PRESCAN stream when the user actually plays the file (not just hovers over the playlist entry), you shouldn't end up with 8-10 at a time. In fact, you probably wouldn't have to bother with pre-creation at all, as normal stream creation is generally very quick anyway.

emiliojazz

  • Posts: 81
Re: PRESCAN in the Background?
« Reply #4 on: 31 Mar '08 - 21:33 »
Are you sure you really need to use the PRESCAN flag though, eg. are you using it for custom looping purposes?

Yes, I do custom looping in my software... Another reason that I need the PRESCAN flag is that Windows
put some data in the cache, and so the overhead when changing the pos or reading from disk (I call BASS_ChannelGetData from within an ASIOPROC with buffer size of 128 samples!) is less.

If you're just using it for exact seeking/length, perhaps you could create a normal stream to start playback with and also create a PRESCAN one in the background (in another thread). Once the PRESCAN stream is created you can switch to that and free the original non-PRESCAN stream. You could still use your existing cancellation system but, as you only create the PRESCAN stream when the user actually plays the file (not just hovers over the playlist entry), you shouldn't end up with 8-10 at a time. In fact, you probably wouldn't have to bother with pre-creation at all, as normal stream creation is generally very quick anyway.

This seems a very good idea!  :D
But I don't understand one thing...did you mean that I can create a normal stream when searching the playlist (without PRESCAN), and then when the song is played, I should create the PRESCAN stream?
And what about the switching between those 2 streams? I think I couldn't switch during play without hearing some click/pops (because I must match the position of the new "PRESCANNED" stream with the old stream that is playing).
Remember that I need also that, when the user pressed PLAY, the song starts immediately... :-\
Hope I missed something..  ::)

In the meantime, thanks for your reply!
Emiliano
« Last Edit: 31 Mar '08 - 21:37 by emiliojazz »

Ian @ un4seen

  • Administrator
  • Posts: 20437
Re: PRESCAN in the Background?
« Reply #5 on: 1 Apr '08 - 14:13 »
Another reason that I need the PRESCAN flag is that Windows
put some data in the cache, and so the overhead when changing the pos or reading from disk (I call BASS_ChannelGetData from within an ASIOPROC with buffer size of 128 samples!) is less.

I guess that would still be covered by the parallel PRESCAN stream, ie. that will read-ahead in the file and Windows will cache it.

But I don't understand one thing...did you mean that I can create a normal stream when searching the playlist (without PRESCAN), and then when the song is played, I should create the PRESCAN stream?

You could still pre-create the stream, but I don't think you need to bother as stream creation is generally very quick without the pre-scanning. You could just create the stream when you want to play the file (and then also create a PRESCAN version in the background).

And what about the switching between those 2 streams? I think I couldn't switch during play without hearing some click/pops (because I must match the position of the new "PRESCANNED" stream with the old stream that is playing).

As you're using decoding channels, the switch should be quite straightforward; you can set the PRESCAN stream to the same position as the original stream before switching. As you're using such a small ASIO buffer, to avoid breakups in the output, you will probably need to perform that seeking outside of the ASIOPROC. That should also be fairly straightforward as you know what units of data the ASIOPROC is asking for, so you know what positions the decoder will land on; you can set the PRESCAN stream slightly ahead and make the switch when the original hits that position.

Another option is to simply delay the switch until the PRESCAN version is actually needed, ie. when seeking :)

Having the extra PRESCAN stream just waiting around won't unduly increase resource (memory) usage.