-
-
Notifications
You must be signed in to change notification settings - Fork 128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resampled buffer #131
Resampled buffer #131
Conversation
and blocking or slow operators. sleep(delay=1.5,s) waits 1.5 times the duration of a frame at each get_frame. Expect catchup ahead! This is meant for testing operators (buffers in particular) and not at all for production.
This is just like buffer, excepting that the output reads the buffer at slower or faster speed in order to keep the buffer at around the same level always. For clocks a bit too slow (typically soundcard) it should help without being noticeable. For now the operator forgets about tracks boundaries and metadata (but they could come back).
And if you really want to have fun and remember old bad quality K7 (magnetic tapes) players, when battery was getting low, change ligne 2 to:
|
"", Lang.source_t k, None, None]) | ||
~kind:(Lang.Unconstrained k) | ||
~category:Lang.Liquidsoap | ||
~descr:"Create a buffer between two different clocks. The speed of the output is adapted so that no buffer underrun or overrun occur. This wonderful behavior has a cost: the pitch of the sound might be changed a little. Also, this operator drops track boundaries and metadata for now." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, can you wrap you code to like 80 chars.. 😭
Done reviewing what I could spot. Looks quite interesting to me! |
let prebuf = Frame.audio_of_seconds pre_buffer in | ||
(* let maxbuf = Frame.audio_of_seconds max_buffer in *) | ||
object (self) | ||
inherit Output.output |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could probably inherit from output.dummy
here and get rid of the output_*
methods..
Thanks @toots for comments! On a general note, you made a lot of comments about the general structure of producer/consumer, which is copied verbatim from the |
Side note: there's already one happy user:) |
Ok, so I have implemented support for metadata. I think that it is ready for merge. I would like to delay for a second PR:
@toots do you agree with that? |
method stype = Source.Fallible | ||
|
||
(* TODO *) | ||
method remaining = -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO... ^^
Some "Amount of time to sleep at each frame, the unit being the frame length."; | ||
"random", Lang.float_t, Some (Lang.float 0.), | ||
Some "Maximal random amount of time added (unit is frame length)."; | ||
"die", Lang.float_t, Some (Lang.float (-1.)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of "die", "stall" or "freeze" seem more appropriate.
Thanks for the feature Sam, adaptative resampling is a nice thing to try and I trust you did it well, at least far better than I could have. I'm fine with a quick merge as long as it does not have any impact on the rest of the code. In that respect I would be happier if the new adaptative buffer was in its own file and the experimental metadata generator was not in the main generator file. |
in | ||
|
||
let ofs = Frame.position frame in | ||
(* Yes, I've seen some cases... *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this comment mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used the following script to test new tracks:
s = playlist(id="playlist","~/Music")
s = skip_blank(max_blank=5.,threshold=0.,s)
s = sleeper(delay=1.2,s)
s = mksafe(s)
s = output.dummy(s)
s = buffer.adaptative(averaging=1.,s)
s = mksafe(s)
out(s)
And after a few tracks, I had requests to fill frames with negative Frame.position
, which I don't think is really related to our operator... So I just worked around...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If Frame.position returns a negative number, it means that someone has added a break at a negative position in that frame. I find it hard to bet that it isn't related to the new operator and generator. In any case, this really needs to be properly investigated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed...
Did you have to use a ring buffer rather than a generator? Using a generator, you could have re-used the old consumer and changed only the producer. (I don't care much for the slightly better perf that the ring buffer gets us, I prefer simple and clean code.) What is the difference between a metadata generator and a general From_frames generator for frames without any channels? I see they are not interchangeable but it may be easy to use From_frames and some operations on Frames to do what you do with your MG, and this would avoid duplicating code in Generator. |
@@ -168,6 +168,96 @@ let get g size = | |||
|
|||
end | |||
|
|||
(* TODO: use this in the following modules instead of copying the code... *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't introduce a TODO in one of our core files... Also, I'm not in favor of a rework of Generator (using Metadata as part of From_frames) now, because I'm not sure to have the time to review this carefully enough, and we don't have the time to test it enough either, with an upcoming release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm kinda weirded out by the amount of code as well.. It seems to me that there should be better path of least resistance..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I think that this TODO is really deserved:
- the code for handling metadata is duplicated in all the generators, which is really bad
- as you remark, we do not want to do this now, in order not to mess up with generators which are a very sensitive part of Liq, so the TODO will help us remember
@smimram sorry if some of my comments were nitpicking.. I just like to mark all I think of but some of it isn't to be taken too seriously.. I still think that the I put a couple of comments, the only two things standing out for me are the metadata code, which seem like there could be a shorter solution and the missing Well actually, now that I think about it, we should also document that properly.. ^^ |
@toots No problem, I like detailed comments! I have filled |
Concerning the negative offset and actually it seems that, as Brandy and Monica would say: the bug is mine. I'll handle this soon. |
Last bug corrected (tm). |
Nice. I have no more serious problem with the code, feel free to merge. On Mon, Nov 18, 2013 at 10:45 PM, Samuel Mimram notifications@gitpro.ttaallkk.topwrote:
David |
Same here! 2013/11/19 David Baelde notifications@github.com
|
Added
buffer.adaptative
, which is likebuffer
but reads the buffer at varying speed in order to keep the buffer at decent filling. For instance,simulates a source which is 1.5x slower than realtime (thus catchuping quickly). The following script however accomodates quite well of it
@dbaelde @toots I have some minor stuff to fix but could you please review already it would help much. In particular, I am no so sure I am filling and reading from frames exactly correctly... Thanks!