Tag Archives: phonon

JuK Supports Opus Codec (sort of)

I just wanted to drop a quick note that JuK, the KDE music tagger/player component of the KDE Multimedia Software Compilation, now supports playback and limited metadata editing of Ogg Opus audio files.

This requires support from some underlying libraries:

  • The Taglib library must support Ogg Opus audio to add the track to your JuK collection at all. At this stage JuK can’t load a file to play if Taglib doesn’t support it, even if the playback system (Phonon) would otherwise support it. Taglib also provides the metadata reading/editing so our support is only as good as that provided by Taglib. For instance, the bitrates all show as 0kbps for my current encodes. Taglib only supports Opus in git as far as I can tell, so JuK uses configuration checks to see if Taglib supports Opus. JuK will still compile if Taglib doesn’t have Opus support.
  • To actually playback Opus audio, Phonon must support playback. Practically speaking this means your Phonon backend (VLC, or gstreamer, normally) must support Opus playback. Both underlying libraries already have releases (VLC 2.0.4 or later; gst-plugins-bad) supporting Opus so this shouldn’t be too hard.

One caveat is that I’m not sure what mimetype will eventually end up being used in shared-mime-data for Ogg Opus audio (probably audio/x-opus+ogg or audio/opus+ogg). At this point Ogg Opus audio gets detected as audio/ogg so I simply check for .opus extension if this fallback mimetype is identified.

In case it’s not clear from my writing “Ogg Opus” everywhere instead of just Opus, JuK currently does not support Opus audio in other container formats (such as Matroska). However the Opus standard recommends using Ogg as the container for purposes of storing audio as files so this should be how you encounter Opus files in practice.

Retro tunes with Phonon

So, in The Beginning, when I was just a young padawan on the Internet, I had been let into a glorious secret: Emulation (not of IBM System/360 machines, but of more important things like the Super NES). Some branching from there led me to zophar.net, a popular emulation site, and their message boards, and also left me with a fascination with emulation.

The attributes of some of the older systems like the NES and Super NES made it fairly easy to capture their music-producing software, since those systems used separate co-processors to handle music effects. NES music would be stored in the NSF format, and SNES music was handled with the SPC format (named after the audio chip used, the Sony SPC700). There were (and still are) specialized plugins on many systems to play these formats (they emulated only the music chip, not the rest of the system).

I’ve been involved on the periphery of some of these things for the past couple of years. (For instance I had written a KFileMetaInfo plugin for KDE 3, and had helped Chris Lee with adding playback support to GStreamer.

One problem with the previous GStreamer solution (which I’ll call gst-spc) is that the underlying playback library, libopenspc, is written in x86 assembly, and has some crash bugs associated with it as well. As well the code has long been orphaned. I’m not really any good at writing emulation code and although I could learn, it would take far too much time for me to do anything useful.

Luckily for me the state of the art has advanced and last year I was pointed to a library called game-music-emu. This library included a very good SPC emulator written in C++, which had been merged into some popular SNES emulators already. Unfortunately it didn’t really have a great build system (using it involved simply copying it into your existing program) so my initial proposal to port GStreamer to use game-music-emu by simply including the source files with GStreamer was rejected. The GStreamer devs preferred to have an external library which could be used (or not) and I couldn’t blame them since in general good OSS projects avoid copying or forking external code.

So I contacted the game-music-emu author (Blargg) asking about the possibility of adding support for building a library, and ended up with commit access and an invitation to do it myself. Hmm.

So I did, and awhile ago I had made a release of “libgme” 0.5.5, working with Blargg has he got free time. My subsequent patch to GStreamer was accepted and since gst-plugins-bad-0.10.14 it has been possible to use libgme to playback many emulated music file types (not just SNES, but others as well).

With that solved I left the issue, but I recently came back to it since I figured out that even after upgrading to gst-plugins-bad-0.10.17 the other day, that gstreamer playback was not using libgme, but the older libopenspc.

At first I thought it was simply my fault, as I’d still had gst-spc installed from years and years ago. Removing gst-spc and libopenspc (just to be double-sure) left me with no SPC playback features. Running gst-inspect confirmed I did not have any gme decoder. WTF.

I then again thought it was my fault because I had installed libgme to /usr/local instead of /usr. So I dutifully wrapped up libgme in an ebuild and installed it. And still nothing. WTF.

I dug into the Gentoo ebuild for gst-plugins-bad and it seems that for whatever reason not all possible plugins are installed. It seems the new installation method is supposed to be that each individual plugin is supposed to have its own ebuild (i.e. gst-plugins-gme), like how Gentoo has split out other packages like KDE into individual ebuilds. Fair enough.

I write another ebuild, and finally hit paydirt:

Screenshot of music player playing SPC files
The Qt example music player playing SPC files

Obviously this does require that you are using the GStreamer backend for Phonon to have this work, otherwise you can just try it in some other GStreamer-using application. (I’d show it in JuK but I’d have to add SPC support to Taglib first)

If you’re interested in the ebuilds I used you can use this Portage overlay, (SHA-512 sum c0ff9aa5413b0c0b14f7c52d5b3ee887edc4e7bf47182e58c21e9c340d8ff7e9). The overlay may or may not work for you, and I don’t even know if overlays are still the “hip” way to do things in Gentoo, but It Works For Me. ;)

Debate time

Why are you taking notes on the debate? I thought you already mailed in your vote.

This was a quote from my wife a few hours ago as the Presidential debate was getting started. She was right of course in that it wouldn’t affect my vote. I did jot notes down for the first hour or so just so I’d be able to remember the debate later should discussion ever come up. :-)

Anyways I expected better from Obama and worse from McCain. I still think Obama won but he at least at first seemed to have trouble collection his thoughts at times. I’m quite pissed at McCain trying to say that the only way for the deaths of American servicemembers in Iraq to have meaning is to “win” the war as it discounts the very real effort of many of those servicemembers. The Navy Times had an article the other day describing a Marine put up for a Medal of Honor because he died jumping on a grenade to save nearby Marines. He may not have won the war but you’d better believe what he did meant something to those Marines that he saved.

If there’s any single thing about this campaign that scares me though, it is Gov. Palin potentially becoming President if McCain wins the election. I’m impressed enough that he is doing as well as he is doing at 72 (?) years old but he has melanoma, suffered for years as a POW in Vietnam and, judging by the change in appearance of Presidents Clinton and Bush over their time in office, I’m really not convinced that Palin wouldn’t end up as President sooner rather than later. I feel that would be disastrous for the nation given her current practices for picking executive staff (i.e. nepotism instead of meritocracy). Being completely silent on the investigations going on in Alaska isn’t making me feel any better what with having just gone through Attorney General Alberto Gonzalez…

However, that’s neither here nor there and all I can do now is hope that the best candidates win the upcoming election. In more exciting news, a friend of mine coerced me into joining a fantasy football team (for points, not money, don’t worry). I didn’t really put a lot of effort into the picks and I missed the draft due to other committments so my team (“Graphitar”) is basically the best team the Yahoo! Random Number Generator could provide. Against all odds though, the team put up an incredible performance in Week 1 thanks to career days by Donovan McNabb and Michael Turner. It’s looking like the 171 points or so put up in that game may stay a season record at this rate. 6/8 teams get to the playoffs so I should at least be good for that.

On a completely unrelated topic I see the topic of Phonon and gstreamer has come up again. I documented many of the reasons why KDE needs Phonon in a letter to the LWN Editors more than 2 years ago. Suffice to say I don’t feel like going over the arguments again, but let’s just say that Phonon keep the doors open for gstreamer 0.12 to be supported in KDE when the time comes.

Finally on a more depressing note a submarine sailor was killed almost a week ago. The linked article is about all the specifics I have except that it is unlikely that the sailor was cleaning the rudder since last time I checked it had to be in the water (where the crew is not located) to work. It is likely that any cleaning he was doing was in the area of the hydraulics controlling the rudder but I don’t see how he would have been caught up in the mechanism. At least on my boat it has a shield surrounding the mechanism although Murphy’s law being what it is…

Improved crossfadiness

So I’ve made a few more changes to the crossfading code in JuK. This should hopefully fix crossfading issues completely for people. However, life is weird sometimes. phonon-gst went from being completely unusable (it would crash with JuK) to being the best option right now (perfect crossfading, at least here). phonon-xine, due to the way crossfading is now implemented sounds slightly crackly sometimes while playing music back. Even with the new crossfading routine, incoming music starts out at a high volume before fading in, although it does sound smoother.

Basically what used to happen is that JuK would pipe the music directly from the file to the Audio Output object. Phonon allows you to insert effects into that audio path, which is how crossfading works. You simply start playing the next song with a fader effect, set to fade in, and at the same time insert a fader effect into your currently playing stream set to fade out. Unfortunately phonon-gst has issues with removing effects from an audio path it looks like, which is why I was getting crashes. Even when I fixed the crashes by simply leaking the object as an experiment, the crossfading was horrid under phonon-gst as it takes seemingly forever to setup the fader and insert it into the audio path.

So what I’ve done is to simply insert the fader effect into the path from the start, and simply tell it to fade at the right time. Presto! Except that doing this seems to cause artifacts with phonon-xine output sometimes… *sigh*. But for now now it looks like phonon-gst has gone from unsupported to the best option for JuK at this point, hopefully all the backends will work equally well by KDE 4.1 though.

In other news, kdesvn-build in /trunk will allow you to build the Phonon pseudo-module. I say pseudo because there is no phonon module. It is developed in kdesupport. However I’ve been informed that the correct place for most users to build phonon from would be /branches/phonon/4.2. kdesvn-build has a couple of hacks that would support pulling it from the right location but still wouldn’t be able to build it due to the module layout. So I’ve added a bit of special support for it. I also changed the sample rc file to show how to build Phonon 4.2. If it’s important enough I’ll go ahead and make a 1.6.1 release.

Is there anyone looking forward to C++0x more than I am right now? :) The linked Wikipedia page has tons of changes, some which worry me a bit due to syntax (for example, lambda functions). Then again, I’ve never seen a good syntax for lambda functions, although I’m sure it’s just me.

But things like an auto keyword to allow for automatic type deduction? Very nice. For example, instead of doing:

for ( QList<QWidget *>::ConstIterator it = list.begin(); it != list.end(); ++it() ) {
  // use *it

you could do:

for ( auto it = list.constBegin(); it != list.constEnd(); ++it ) {
  // use *it

I did have to change begin/end to constBegin/constEnd to make sure that the non-detaching forms of the iterator are used, but this may be something that g++ is able to deduce as well someday.

Probably the biggest other feature I’m looking forward to is the “rvalue references”, which will allow for constructors that “move” data instead of having to copy them over. Qt has kind of mitigated the problem somewhat in their shared classes but you can benefit from this even in non-Qt-using code. There’s many other improvements too, I just wonder how long they’ll take to get into a g++ which we can use for KDE development. :)

Improved crossfading

I’ve been improving JuK a lot over the past week or so trying to get it into better shape for KDE 4.1 (and 4.0.5).

What I’ve worked on today was the issue with crossfading where the volume differential between the songs would go haywire initially. I think I’ve got it as good as I can get it from JuK, but now there’s something else I need.

I have posted an email to kde-multimedia detailing my problem, but basically I want to use the gstreamer phonon backend to test whether the problem lies with JuK or with phonon-xine.

The first problem was that JuK wouldn’t work with phonon-gst because JuK made some inaccurate assumptions about when Phonon would actually start playing after being told. (Hint: Not immediately, the backend has to setup first).

That is fixed in both the 4.0 and trunk branches now. But when using phonon-gst to playback a song, any time I switch to the next track JuK crashes on an assertion in phonon-gst. This happens even if I do not allow crossfading. This does *not* happen if I slow it down in gdb by single stepping. So I think it’s a timing issue.

Anyone out there use phonon-gst and could tell me what I’m doing wrong?