Skip to content
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

join forces with libgroove? #4

Open
andrewrk opened this issue Sep 24, 2014 · 3 comments
Open

join forces with libgroove? #4

andrewrk opened this issue Sep 24, 2014 · 3 comments

Comments

@andrewrk
Copy link

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:

  • open source (simplified BSD license, see License.txt)
    • check. libgroove is MIT licensed.
  • very simple interface
    • sure. I think libgroove is as simple as possible, and no simpler.
  • support of most important sound formats (MP3, Flac, Ogg Vorbis, WMA, AAC / ALAC m4a, ...)
    • check. libgroove also depends on libav/ffmpeg
  • Plays audio data via the player object. Uses FFmpeg for decoding and PortAudio for playing.
    • libgroove currently uses SDL2 for playing, but there is a branch almost complete to switch to port audio.
  • Of course, the decoding and playback is done in seperate threads.
    • of course. same in libgroove
  • Supports any sample rate via player.outSamplerate. The preferred sound device is set via player.preferredSoundDevice. Get a list of all sound devices via getSoundDevices().
  • Can modify the volume via player.volume and also song.gain
    • same in libgroove. main player has volume and each song has a gain. this makes it possible to implement perfect loudness adjustment.
  • Prevents clipping via a smooth limiting functions which still leaves most sounds unaffected and keeps the dynamic range (see smoothClip).
    • same. libgroove uses the compand audio filter from libav/ffmpeg.
  • ReplayGain (for audio volume normalization) (see pyCalcReplayGain). This is as far as I know the only other implementation of ReplayGain despite the original from mp3gain (gain_analysis.c).
    • libgroove uses EBU R128 instead. In fact the replaygain 2.0 specification is being discussed to use EBU R128.
  • AcoustId audio fingerprint (see pyCalcAcoustIdFingerprint). This one is also used by MusicBrainz. It uses the Chromaprint lib for implementation.
    • libgroove supports this as well.
  • Provides a simple way to access the song metadata.
    • check.
  • Provides a way to calculate a visual thumbnail for a song which shows the amplitude and the spectral centroid of the frequencies per time (see pyCalcBitmapThumbnail).
    • This is not supported out of the box by libgroove. However libgroove does support a "raw sink" which you could hook into your own code for calculating a thumbnail. Alternately we could talk about adding support for this thumbnail into libgroove itself.
  • Gapless playback
    • check.

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
Copy link
Owner

albertz commented Sep 25, 2014

(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
Copy link
Author

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
Copy link
Owner

albertz commented Sep 25, 2014

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants