Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: random (Read 11030 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

random

Reply #25
exactly why it should:

A,B,C,D,E,F,G,H,I,J  hmm, let's play D
A,B,C,E,F,G,H,I,J      hmm, let's play H
A,B,C,E,F,G,I,J        hmm, let's play B
A,C,E,...etc etc...

It really wouldn't be *that* hard to implement.  There's probably an easier way to do it than this, but this would be one way.  Is Shuffle on?  OK, when Play is pressed, copy playlist to invisibleplaylist2.  Randomize invisibleplaylist2.  Play invisibleplaylist2 until end is reached (in which case randomize again and start over) or stop is pressed.  If a new song is added to the playlist, simply insert it into some random slot below the currently playing song in invisibleplaylist2.

random

Reply #26
_Shorty, the whole "randomize invisible playlist" thing doesn't work, because then a new song which is added many never get played, because it might be inserted at the beginning of the "invisible playlist", which has already been passed over.  In addition, that would bump the indexes, causing the current song to played again once it's finished.

The ideal solution for that type of behavior, is to either:
Create an empty "played" list, and add every song which has already been played to that list, and to avoid playing those songs again until all songs have been played, at which point the "played" list is empties.

Or, better yet:
Create a new "invisible" list containing all the entries from the old list.  Every time the currect track is finished, a selection is randomly chosen from the list.  That selection is then removed (and played of course).  When new entries are added to the "visible" list, they are also added to the invisible list.

I'd like to see both options: Randomize (current shuffle behavior) and Shuffle (expected shuffle behavior).  However, I'm sure Peter knows how to implement a standard shuffle.  He's apparently not interested.

random

Reply #27
I think a better mem/cpu tradeoff method would be:

1. find a random song

  • 1a. if number of played songs == number of songs, clear ignore list
    1b. if
  • in ignore list go back to 1 and try again.
    2. play
  • , insert
  • into ignore list (increment number of played songs)
    3. Go to 1.

    Probability would ensure that a number of tries untill a valid song is picked isn't too hight. And this way memory usage would be lower by far. Inserting
  • can use a hash table or whatever.

random

Reply #28
Quote
simply insert it into some random slot below the currently playing song in invisibleplaylist2.

...

random

Reply #29
I may be scorned upon heavily for this, but what does winamp do? I can't remember. I seem to remember it didn't select the same track all that often in lists <100 in length.

If the invisibleplaylist method isn't that difficult to implement, couldn't it be done as a plugin if Peter doesn't want to do it? People could have the option of using "Shuffle" play (i.e. random using the mersenne twister method) or "Shuffle with no repeats" for those who want to keep their playlist in order and have "random" playback which plays all files in a shuffled manner, then re shuffles and starts again.

I wonder if Peter's about, I hope he might explain his reasons for not implementing the latter option as it seems to hold some practical viability. In the mean time I'll UTFS and see if it's been explained in any other threads.

It might be useful for parties and suchlike. One might enqueue more than enough songs of their choice in a playlist and just leave it going all night. Obviously they wouldn't want a repeated track unless specifically requested.

This is quite an interesting thread.
superdumprob
____________________________________________

"If we knew what it was we were doing, it would not be called research, would it?" - Albert Einstein

random

Reply #30
Quote
I think a better mem/cpu tradeoff method would be:

1. find a random song

  • 1a. if number of played songs == number of songs, clear ignore list
    1b. if
  • in ignore list go back to 1 and try again.
    2. play
  • , insert
  • into ignore list (increment number of played songs)
    3. Go to 1.

    Probability would ensure that a number of tries untill a valid song is picked isn't too hight. And this way memory usage would be lower by far. Inserting
  • can use a hash table or whatever.

That's pretty much the same as the 1st method I posted.  It's more CPU hungry, because it requires far more searching and random number generating.  It's no less memory hungry, because at some point, the "played/ignore" list will contain every entry (except one) in the real playlist.

edit: I think I see what you're talking about now.  Keep a list of indexes rather than playlist entries.  It wouldn't end up being any better, though, because the "invisible" list would just hold pointers to the original entries, so there'd be no significant memory use there.

_shorty, sorry, I missed that.  It's still less efficient than the second method I posted, though, because it requires re-randomizing the last part of the list every time you add a new track.

superdumprob, this can't be implemented cleanly in a plugin, because there's no way (as far as I know) to add a new entry to the "Playback" menu.

random

Reply #31
Why rerandomize? Run rand() (very efficient) -> get number -> try song. That's it, it doesn't even care about the added or removed songs (as long as total number is updated). But we are pushing water, it's useless the author probably knows how to do such simple things.

random

Reply #32
LPTB, it doesn't work quite like that.  If you generate a random number, it's going to be anything from the list (current behavior).  If you want proper shuffle behavior, you'd need to keep track of the songs already played somehow.

And rand() isn't nearly so great as you imagine.  Foobar uses (so I've heard) Mersenne Twister, which is faster, more Random, and has a much larger cycle than rand().

random

Reply #33
Quote
Quote
I've kept foobar playing that playlist for about 50hrs right now, and it has played only 136 different songs.

How do you know it?

Well I came here, I first installed foobar and added the files to the playlist  None of the files had ReplayGain status and I've put the "automatically calculate RG for played songs" on. Then, I've let it play for almost 60hrs now (there's the counter on preferences). And now when I check the list, there's 160 songs still without RG status.

random

Reply #34
@C. George
By rand() I mean the metha function (I didn't mention a specific implementation, you can use C rand(), M. Twister, or even Yarrow). To play a song in a range all you have to know is the total number of songs say N:
song number to play = (int)(N * rand() + 1)
pretty easy and painless (One mult, one add, and rand (lots of mults and adds)).

random

Reply #35
take one coin , launch it:
what is the probality to have A side ? = 50%
for example we obtain B
NOW what is the probality to have A side ? =50%
for example we obtain B
NOW what is the probality to have A side ?= 50%
for example we obtain A
NOW what is the probality to have A side ? =50%
for example we obtain B
NOW what is the probality to have A side ?= 50%
for example we obtain A
made calculation: 5 launch, 2 A, 3 B =  40%A, 60%B

morality: random launch made not random result!
we can have 50%A, 50%B only with VERY HIGH numbers of launchs.

anza: you have 20 h of music and you have played it for 50 h
it is not sufficient to have statistic distribution, try with 2000 h
Music is my first love.

random

Reply #36
Quote
superdumprob, this can't be implemented cleanly in a plugin, because there's no way (as far as I know) to add a new entry to the "Playback" menu.


well, but if you have the HWND of foobar, you could do a GetMenu(), GetSubMenu() and InsertMenu() to put your menu entry there.
I don't know the foobar plugin system, if it's easy to get WM_COMMAND messages for foobar, but otherwise you could intercept foobar's message procedure to finally respond to the selection of this menu entry.

random

Reply #37
Quote
anza: you have 20 h of music and you have played it for 50 h
it is not sufficient to have statistic distribution, try with 2000 h

Yeah I know. And I wasn't complaining about anything, I just told what had happened here. I think it's still been quite random, even though there are still a few songs in the playlist I didn't even know I had here x) The only "bad" thing I've noticed is that ONE song has been played for about 10 times but it doesn't bother me, it's a good one

random

Reply #38
Quote
@C. George
By rand() I mean the metha function (I didn't mention a specific implementation, you can use C rand(), M. Twister, or even Yarrow). To play a song in a range all you have to know is the total number of songs say N:
song number to play = (int)(N * rand() + 1)
pretty easy and painless (One mult, one add, and rand (lots of mults and adds)).

The problem is, you wouldn't be playing a song in a range.  You would be playing a song from a subset of songs within that range.  If I understand your idea correctly, it's effectively the same as the first one I posted.  Generate a random song index.  Then check to see if it's already been played.  If so, try again.  The problem is, that generates a whole lot of random numbers once you past the middle of the playlist, because then there's better than a 50% chance of an index collision.

And also, rand() returns an int, not a float, so you have to use the modulo operator to "trim" the result to size.  That's hardly a point worth discussing here, though.   

Quote
superdumprob
well, but if you have the HWND of foobar, you could do a GetMenu(), GetSubMenu() and InsertMenu() to put your menu entry there.
I don't know the foobar plugin system, if it's easy to get WM_COMMAND messages for foobar, but otherwise you could intercept foobar's message procedure to finally respond to the selection of this menu entry.

That's not actually a bad idea, but I don't kow how I could get the WM_COMMAND messages from foobar.

random

Reply #39
Quote
And also, rand() returns an int, not a float, so you have to use the modulo operator to "trim" the result to size. That's hardly a point worth discussing here, though

What rand() is that, most rands I know of return a float/double from [0,1] range. But besides, the point of random tests is mute, the main thing that's bothering people here (and me) is that when I play a list I intend it to play randomly but not repeat songs, any random generator will output collisions (the probability of no collisions on any finite list tends to 0). So vote for 'normal' random play !!

random

Reply #40
for practical purposes wouldnt some sort of 'just dont repeat last N songs in shuffle/random' play do?  (when default N around 20 could be high enough imho, also it could be the percentage like N=(number of songs on playlist / 3) or something). (i guess the 'other player' uses something like that?)
PANIC: CPU 1: Cache Error (unrecoverable - dcache data) Eframe = 0x90000000208cf3b8
NOTICE - cpu 0 didn't dump TLB, may be hung

random

Reply #41
C/C++ rand() function returns an int. 

And indeed, random number generators will produce collisions, but you can stop the problems caused by those collisions by removing the entries after they've been played. (e.g. the second method I posted)

edit:
smok3, I think most players use the second method I posted earlier.  It's simple, efficient, and works.  The "other player" adds another layer by adding a playlist "window".  i.e. it only plays song within that window, and the window slides down the playlist as tracks are played.  Keeping a "don't play last x songs" list causes the repeated searching problem.  i.e. "Select a random track" -> "check to see if track has already been played" -> "if so: repeat"

random

Reply #42
The way to do this (at least as far as I can tell) is to cross link your list of N tracks into an array of size N. Then:

- randomly generate a number between 1 and N, call it i
- play song i
- swap the pointers at position i and N
- repeat but using N-1 instead of N

I think this might be what Curi0us_George was discribing but it wasn't clear.  The advantage of this method is that your precious back button can take you to ever pervious track played (going to run into problems when you've played all the tracks once through and start again).  The disadvantage is the O(N) memory space (scales at 4 bytes per song) but I can't see a way around tracking the state of N objects without using O(N) memory, maybe some kind of fancy hashing algorithm (I can't think of anything) but that's going to increase CPU useage.

You could cut the memory space to 1 bit per track by simply flaging evey tracks's played state as true/false (you'll lose the ablitily to play the pervious songs this way), but just randomly generating numbers and only playing the track if it hasn't been played (as has been suggested) would not work (trying to play the last song is a list of 10000 tracks: average case 5000 numbers generated, worst case generating numbers all day) you'd have to use some kind of probing when you generated a number that corresponded with an already played track.  Linear probing would cause clustering and then people would be complaining that tracks that came right after each other where being played together, quadratic probing would (likely) miss some tracks and other methods require O(N) memory space anyways so you're better off with the first method.

PS: you should be listening to your music one album at a time like it was meant to be heard anyways.

random

Reply #43
Quote
PS: you should be listening to your music one album at a time like it was meant to be heard anyways.

albums like that these days are few and far between.

random

Reply #44
Quote
The way to do this (at least as far as I can tell) is to cross link your list of N tracks into an array of size N. Then:

- randomly generate a number between 1 and N, call it i
- play song i
- swap the pointers at position i and N
- repeat but using N-1 instead of N

I think this might be what Curi0us_George was discribing but it wasn't clear.  The advantage of this method is that your precious back button can take you to ever pervious track played (going to run into problems when you've played all the tracks once through and start again).  The disadvantage is the O(N) memory space (scales at 4 bytes per song) but I can't see a way around tracking the state of N objects without using O(N) memory, maybe some kind of fancy hashing algorithm (I can't think of anything) but that's going to increase CPU useage.

You could cut the memory space to 1 bit per track by simply flaging evey tracks's played state as true/false (you'll lose the ablitily to play the pervious songs this way), but just randomly generating numbers and only playing the track if it hasn't been played (as has been suggested) would not work (trying to play the last song is a list of 10000 tracks: average case 5000 numbers generated, worst case generating numbers all day) you'd have to use some kind of probing when you generated a number that corresponded with an already played track.  Linear probing would cause clustering and then people would be complaining that tracks that came right after each other where being played together, quadratic probing would (likely) miss some tracks and other methods require O(N) memory space anyways so you're better off with the first method.

PS: you should be listening to your music one album at a time like it was meant to be heard anyways.

Actually, that's not the same method I was describing, but yours works, too.   

Mine would not actually provide forward and backward, but I can't honestly say that bothers me, since it's become extremely obvious that the next/prev actions are not going ever behave in the expected manner.  (I'm actually fine with the current prev/next actions, though.)

random

Reply #45
@George
Sorry my bad about float, int; However I found this (Note the conversion to double in the proccess):
Code: [Select]
From the C FAQ:
13.16:  How can I get random integers in a certain range?

A:      The obvious way,

               rand() % N              /* POOR */

       (which tries to return numbers from 0 to N-1) is poor, because
       the low-order bits of many random number generators are
       distressingly *non*-random.  (See question 13.18.)  A better
       method is something like

               (int)((double)rand() / ((double)RAND_MAX + 1) * N)

       If you're worried about using floating point, you could use

               rand() / (RAND_MAX / N + 1)

random

Reply #46
Quote
well, but if you have the HWND of foobar, you could do a GetMenu(), GetSubMenu() and InsertMenu() to put your menu entry there.
I don't know the foobar plugin system, if it's easy to get WM_COMMAND messages for foobar, but otherwise you could intercept foobar's message procedure to finally respond to the selection of this menu entry.

I've worked on this some since I replied.  I can insert my menu item with no trouble.  I can even override the WndProc (which isn't recommended, but whatever).  I'm not recieving WM_COMMAND messages, though, so I can't do anything with my menu item.  It just sits there useless.  I've got no clue why I'm not recieving WM_COMMAND messages, because I am definitely recieving (all?) other messages.

If anyone has any suggestions, I'd love to hear them.

LPTB, useful info. 

random

Reply #47
Quote
Quote
well, but if you have the HWND of foobar, you could do a GetMenu(), GetSubMenu() and InsertMenu() to put your menu entry there.
I don't know the foobar plugin system, if it's easy to get WM_COMMAND messages for foobar, but otherwise you could intercept foobar's message procedure to finally respond to the selection of this menu entry.

I've worked on this some since I replied.  I can insert my menu item with no trouble.  I can even override the WndProc (which isn't recommended, but whatever).  I'm not recieving WM_COMMAND messages, though, so I can't do anything with my menu item.  It just sits there useless.  I've got no clue why I'm not recieving WM_COMMAND messages, because I am definitely recieving (all?) other messages.

If anyone has any suggestions, I'd love to hear them.

LPTB, useful info. 

Well, I think it is a bad idea to hack the menu, because it is not using the fb2k API (your plugin may be banned from this forum, remember the seek bar hack?).
Here is my idea what you could do with 0.6b11 sdk to get any song scheduling you like:
- enable "Stop after current"
- write a plugin with a play_callback, in on_playback_stop() use playlist_oper::play_item to start any song from the playlist you want.

I don't really know, if that will work, but you could try, if you want your own type of random/shuffle behaviour really badly. (I don't, so I'm not going to implement this.)