albertz / music-player-core

Music player core Python module
BSD 2-Clause "Simplified" License
74 stars 22 forks source link

join forces with libgroove? #4

Open andrewrk opened 9 years ago

andrewrk commented 9 years ago

libgroove is a C library that fulfills exactly the same role as music-player-core. Maybe we could think about combining effort?

Going through your feature list:

One way this could work is if music-payer-core depended on libgroove and added its python layer on top of it.

What do you think about all this?

albertz commented 9 years ago

(Earlier discussion here.)

I thought of that. The last time I looked into it, I felt that the underlying interfaces were too different and it would be too much work to unify them. But that was a while ago. Also, I feel that C++ is the better language.

I really would like to work together - because in the end, that hopefully improves the quality and means less maintenance work for both of us.

I think that there are probably things where we need to extend libgroove so that it becomes possible as a base for music-player-core. Also, for music-player-core, some outstanding items where I wanted to go in the future: Automatic BPM detection and beat matching + fading, kind of an auto DJ mode. After all, extend it all to make DJ functionality possible (borrow some ideas from Mixxx - cannot take code directly because it is GPL). This also means to be able to slow-down/speed-up a song while keeping the pitch (time stretch). And also an equalizer.

I think I also remember that libgroove could only read files from disk. It is very important in music-player-core that it does not itself do the file reading, but just gets a data stream which is provided from the higher level logic. The idea is that people could write plugins which get the data from exotic / extern resources, like e.g. directly from YouTube, etc. Also, infinite data streams (Internet radio) should be possible.

At the moment, I'm also somewhat busy to work on this. That are my thoughts on this. I will try to find some time later to look more into it.

andrewrk commented 9 years ago

I thought of that. The last time I looked into it, I felt that the underlying interfaces were too different and it would be too much work to unify them. But that was a while ago. Also, I feel that C++ is the better language.

The way I see it, music-player-core is a bit higher level than libgroove. So perhaps music-player-core could be a C++ layer (which provides a python interface) on top of libgroove.

I really would like to work together - because in the end, that hopefully improves the quality and means less maintenance work for both of us.

Same :-)

I think that there are probably things where we need to extend libgroove so that it becomes possible as a base for music-player-core.

I'm willing to work together on this. My mind is completely open to this kind of stuff.

Also, for music-player-core, some outstanding items where I wanted to go in the future: Automatic BPM detection and beat matching + fading, kind of an auto DJ mode. After all, extend it all to make DJ functionality possible (borrow some ideas from Mixxx - cannot take code directly because it is GPL). This also means to be able to slow-down/speed-up a song while keeping the pitch (time stretch). And also an equalizer.

I'll take some time to think about how all these features could work. Some of these - for example the equalizer - could be libav/ffmpeg audio filters and added to the filter graph which already exists in libgroove. an equalizer as an ffmpeg audio filter already exists.

As for time stretching, I'm not sure an existing filter exists in either project, but I've contributed patches to both; I think we could get that filter in.

Looks like we would also want some kind of fade support / ability to mix multiple streams at once. That's another issue that is not solved yet in libgroove but is planned.

I think I also remember that libgroove could only read files from disk. It is very important in music-player-core that it does not itself do the file reading, but just gets a data stream which is provided from the higher level logic. The idea is that people could write plugins which get the data from exotic / extern resources, like e.g. directly from YouTube, etc. Also, infinite data streams (Internet radio) should be possible.

This is currently true for libgroove, but it's an open issue which I intend to solve.

At the moment, I'm also somewhat busy to work on this. That are my thoughts on this. I will try to find some time later to look more into it.

Understood. I think right now I'm more interested in a "yes this is a direction I could potentially see us going with this" rather than "boom, let's merge projects tomorrow" :-)

I think that the future features music-player-core might want are compatible with libgroove's future. Let me ask this question - what does music-player-core do right now that libgroove cannot provide? (keep in mind that the visual thumbnail thing, for example, I don't see as an issue, because you can simply keep the calculation code and have it use libgroove's raw audio sink to generate it)

albertz commented 9 years ago

I think that the future features music-player-core might want are compatible with libgroove's future. Let me ask this question - what does music-player-core do right now that libgroove cannot provide? (keep in mind that the visual thumbnail thing, for example, I don't see as an issue, because you can simply keep the calculation code and have it use libgroove's raw audio sink to generate it)

The interface at the moment is already such that the core only gets the data stream (it never sees filenames). It has some clever buffering mechanism, i.e. there is another thread which sits there and every time there is too less data in the buffer, it uses a callback into the higher level logic to request more data.

This buffering mechanism also preloads the next N (e.g. 5-10) songs, M secs of audio each (e.g. 10 secs each). That is how gapless playback works. For this, it also just uses a callback to the higher level logic to request a new song object. The higher level logic notifies the core if the playlist of the next N songs has changed - in that case, it reloads them, but only those which have been changed. To identify new songs in the queue, it must have some compare-function, which again is a callback to the higher level logic. In practice, that are Python Song objects, which provide the Song.readPacket function for reading, and the Song.__eq__ function to check for equivalence. The core only stores a pointer to such Song and every song which is currently buffered (including the currently played song) has such Song object pointer, which is then used for all the callbacks. In that sense, the music-player-core is more low-level than libgroove, because it does not handle anything like that (file loading, identifying songs, managing the playlist, etc.).

Also, fading is already mostly possible. It would be quite trivial to add it right now, pretty much by replacing/extending the gapless playback code. Why do you want to do the fading via FFmpeg? Wouldn't that be more complicated?