Older blog entries for ensonic (starting at number 136)

buzztard 0.7 is out

We started the year with a release in the beginning of January. So far only a few issues were reported. Patches for these are on the 0.7.1 branch. One last minute change in 0.7 was the departure from trying to link/unlink elements in gstreamer while playing. I sadly have to conclude that in 0.10 this only works for some cases. It was working sort of okayish for buzztard, but the were still deadlocks or internal dataflow errors from time to time. One such scenario is that when you happen to reconnect elements while the song loops. These things are not easy to sync from the application level. Lets hope this is easier in 1.0. The sticky events should help with setting up the context from new elements.

On the mainline I bumped the required library version and removed the ifdefs for the backwards compatibility. As a first bigger change, I ported the settings from gconf to dconf. We had a settings abstraction to other gconf or play keyfiles, which we now removed. Altogether I kept to use an intermediate object that exposes settings as a gobject with properties for the keys. This allows to use notify to bind to property changes instead of using a custom api.

Then I started with porting gst-buzztard & buzztard to gstreamer-1.0. I made good progress. I will report the details in the next update.

77 files changed, 5892 insertions(+), 8131 deletions(-)
buzztard

Happy new 2013!

Besides a lot of testing and little bug fixes here and there I finished of a few half ready features. One is range-randomize (press Ctrl+Shift+R). In contrast to randomize which takes the parameters min-max value as bounds, this one picks the bounds from the first and last value in the selected range. The other one is that now one can rename machines also from the sequence headers. I was afraid that swapping the GtkLabel with a GtkEntry would use too much space and look ugly, but luckily one can turn off the frame. I still get a different background color though.

During testing I noticed some inconsistencies when renaming machines and found a rather bad data corruption. Certain interaction would create songs that won't read back fully. One can manually fix them up (it is xml after all). I fixed the bug and could even make the format a bit simpler. I had to touch quite a few places:
30 files changed, 246 insertions(+), 404 deletions(-)
Old songs can still be read, but songs written with the new version, also need the new version for reading. One lesson learned, the 'id' attribute in xml is special.

Another results from testing is that the shell based test scripts can now be run standalone to check a bunch of songs (do syntax check, print stats, convert or encode songs).

Finally I entered string freeze for 0.7. I already received the first updates for the translations, thanks a lot! I am looking forward to release it soon.

I uploaded some example song snippets to soundcloud.

438 files changed, 3138 insertions(+), 2800 deletions(-)
buzztard

Finally pushed the pattern control-source: 26 files changed, 1204 insertions, 1333 deletions. It looks like only a little gain in code size, but that is not true; we added more tests and splitting up a large class always comes with some boilerplate for the new class. There are still some opportunities for optimizations, which I'll probably try some soon.

In the UI I improved the interaction controller workflow. For controllers that implement control discovery the dialog from the context menu will also bind the new controller. The settings are now finally useful, as there one can do mass-learning (tweak all knows and then go through the list and name them).

Writing synth plugins for buzztard would be quite a bit of copy and paste. I chopped simsyn into pieces as reusable objects in libgst-buzztard. We have a few oscillators, envelope objects and the svf-filter. The gst elements would proxy some properties of the synth component. Unfortunately that means copy'n'paste of the property setup. I've tried this code, but it shows no effect :/

GObjectClass * filter_klass = g_type_class_ref (GSTBT_TYPE_FILTER_SVF);
g_object_class_install_property (gobject_class, PROP_RESONANCE,
g_param_spec_override ("resonance",
g_object_class_find_property (filter_klass, "resonance")));
g_type_class_unref (filter_klass);


A full standalone example can be found at here.

We also have a new element called wavereplay. This is mainly for testing the wavetable oscillator, but also has a nice property compared to tracker elements. It only has parameters to select the wave to play and it will play it from start to finish in syn with the song. That is if you seek to 2:00, the wave will play content from 2:00. This is unlike tracker elements that would only play what gets triggered from the new time position. One practical use is doing a mixdown of the music rendering with the vocal recordings. In such a song you load two wave (song, vocals), use two wavereplay elements, add effect elements to the one for the vocals and re-render the song to create the mixdown.

I thought I knew pretty much all about gobject. This month I discovered something old I did not know about. It is supported to calls g_object_class_install_property() for a property inherited from the baseclass to e.g. narrow down the value range. This is very useful for the "children" property of polyphonic elements (where children is the number of voices). The interface does only limit the property to the full int range. With this feature elements like e.g. sidsyn can override the range to 3...3 (sid has always 3 voices).

The last bigger change this month was a refactoring cleanup in sequence and song-info. This was quite a big of code shuffling, but now all the timing info is in song-info (which already has bpm an stuff). This change helped with an optimization in the pattern control-sources.

132 files changed, 2417 insertions(+), 2138 deletions(-)
buzztard

After a discussion on IRC about tunings I looked into adding some of those to the ToneConversion class which so far only implemented the usual equal temperament. I have to say the wikipedia articles on this matter are awesome, detailed and plentiful. I added two 12tone tunings to the ToneConversion class now and implemented tuning in sidsyn and simsyn.

I also had a look at the TODO comments and planned items on the wiki. When I was writing the list model classes I did not wrote ones for the wavetable and wave-level-list. I did this now. The list models can also be tested separately from the UI (which is harder to test). I wrote basic tests for all model classes which bumps the test coverage in the ui by 10% (61% classes have tests now, 105 ui tests).

IRC was quite active this month. Another chat was on the wave-table page and wave-preview. The workflow was indeed needless complicated. Now preview is a toggle and if it is active, moving the selection in the file-browser will play sounds. Other discussion motivated me to implement audio-device selection in the settings. So far one could only select the protocol. Now for e.g. alsa or pulseaudio one can also choose to which device to play the audio. While working on the settings I started to make the interaction controller setting more useful. So far the only use of this settings-tab was to list the detected settings. I added a couple of messages to help the user to know what to do when e.g. the list of devices is empty. And I started to implement batch-learning of controls to the settings.

84 files changed, 4199 insertions(+), 1653 deletions(-)
buzztard: presets, tests & live playback

I worked a bit on preset handling in gstreamer. Now machines with variable number of parameters with save their properties correctly. One example is the parametric equalizer. I needed this for sidsyn in buzztard too. I also updated the preset handling for buzzmachines. They now store presets in user-data-dir. This avoids that those get overwritten when the plugins get updated. The preset handling logic will read user-presets first and then merge in system wide presets. One shortcoming here is that we would need a flag on each preset whether it comes from a preset file in user-data-dir (and thus is writable) or comes from a system dir (and thus is read-only). This would allow the UI to require that users pick a new uniqe name when changing a system preset.

Songs in buzztard now also store their non-dynamic settings. This will fix fluidsynth forgetting the selected patch file and is also needed for e.g. setting the chip-type in sidsyn. I refactored the code a bit and now we don't show empty properties dialogs anymore and instead gray out the menu item that would invoke them.

The build system now can show the class-coverage of the tests. As this is just a few shell commands it quickly shows untested classes. It relies on naming conventions for tests. To make that work I also cleaned up the whole UI tests. Those are now more robust and actually verify a lot more things (we went from 54 to 92 ui tests).

77 % (24/31) lib/core/
40 % ( 4/10) lib/ic
100 % ( 1/ 1) ui/cmd
51 % (27/52) ui/edit

The last thing I worked was to progress on live machine playback. And hell yes, it works! One can bind e.g. midi keyboards to machines and play them live. This includes a round-robin voice management for polyphonic generators. It is a lot of fun to play with.

Tom made good progress on the pattern control source. Most of the tests now pass. We hope to be able to merge it soon and to remove the complicated 2step controller updating code.

151 files changed, 8453 insertions(+), 6451 deletions(-)
buzztard goes retro
I started the month with some preparational work for the 2nd GSoc task - to use GstEncodeBin for recording. The first change was to streamline the recording UI. Instead of two dialog - one for setting and one for the progress - we now just show one. This causes less noise on the screen and avoids us some data passing. I also added a bunch of unit tests for sink bin to provide a means to check for regressions when switching the implementation. This also uncovered some
unimplemented code path on the gstreamer side. Those are now fixed or handled on our side.

In the mid of the month I could merge the encodebin transition. It is a very decent code simplification (68 insertions(+), 113 deletions(-)). Adding new output formats is a piece of cake now. And as a bonus, the code is now platform independent - instead of specifying the explicit elements to use, we now specify the container and audio track format. This way encodebin would pick suitable elements depending on what is available.

After the audiosynth baseclass was added, I wanted to see how well it works and started with a long time todo - a c64 sid synthesizer plugin. This wraps the rsid library - an awesome cycle based sid emulation. The library API is quite simple; basically:
  init(); update(regs[29]); clock(*buffer, num_samples); release();

I was really happy to also see a lot of technical information about the sid chip available on the net. When designing the gstreamer element API one needs to have a little understanding how the chip is use to still provide a convenient access to the parameters, but now hide important modes. That needs a bit of experiments to decide whether individual bits need to be exposed or only certain combinations make sense. In addition I implemented a couple of the typical effects. The normal timing resolution of a tracker song is not too high and thus one needs support from the element to provide things like arpeggio, portamento and vibrato.

The sidsyn is the first more complex audio synth we have in buzztard. It is also the first one that uses more of the gst-buzztard API. This was a good opportunity to review and cleanup the APIs a bit. With those cleanups I also killed the help interface, as new enough gstreamer has the required feature on the element metadata side and the feature is not crucial any way.

This month I skip the git stats, as I took the indent git commit hook into use and reformatted the buzztard code base. VoilĂ : buzztard - now with whitespace!
buzztard, testing + build speedups

I did more test cleanups and finally the libs are done. I am going to increase the coverage more, but it is quite good already. We're having more than 200 test for libbuzztard-core now. That helps making changes.

One aspect of writing tests is also to check the API for testability. While working on the wire tests I noticed that we had a disabled test to check for cycles in the machine graph. There where basics checks in the UI, which I now moved to core as new API, expanded it to actuall do a full cycle check and enabled the tests.

While updating the test suites I had a couple tests that I still did not like much. They were all iterating over an array of parameters (input files, extensions) and tested them. What is the problem? It is only a problem if things fail. In the current setup, the test would stop on the first failing parameter. If it would also run for the remaining parameters, I might get a better idea what actually wrong. Besides that, I also don't see right now for which parameter it fails (I need to log it and take a look at the log). Luckily the Check library has loop tests. They are simple to use, instead of tcase_add_test(), use tcase_add_loop_test() and pass the start/stop index to the
test. From within the test you can access '_i' to fetch the parameter set. If the tests run via CK_FORK=yes (which is the default), each loop runs in a new process.

I gave a talk at work about electronic music and used buzztard to demo a few things. While preparing the demos, I naturally found quite a few bugs. This time I also wrote more tests for these things.

build times of the buzztard module
The other big change in the repo is the migration to non-recursive make. I started on the buzztard module. The first step was to still recurse into docs, po, src and tests. That gave some nice speedup already. Then I rebased also src and test to the project root and used includes to keep the Makefile maintainable. This unfortunately made things little slower as I have to do:
SUBDIR = . po docs
The problem here is that the docs will link the libraries to introspect them, but don't depend on them :/ Adding a dependency in there does not work, as the Makefile in the docs-dir does not know the rules for how to make them. On the slow down, the config.status run is faster (two less Makefiles to make), but the '.' in SUBDIRS causes a recursive make invocation for the project root. And thats where we have the big Makefile :/ The workaround I am using now is to have own all-local, check-local, clean-local, install-data-local and uninstall-local targets. The good thing of it is, that now the rules to build the api docs have proper dependencies on the libraries they introspect. In order to see how far I can speed up things, I also trimmed the includes. The effect of this can be seen in the third group of measurements. The benchmarking was not to elaborate, but the big picture is clear.

Some general tips for how to do the change below:

  • in the Makefile.am, first set all kind of vars (so that in includes you can do VAR += ...)

  • include the per subdir rules

  • add common rules

  • targets in e.g. "lib_LTLIBRARIES = libabc.la libdef.la" have to be in dependency order, wtf!


So far, this looks good (aka 'make distcheck' passes). Will do this for the other modules next month.

Tom made good progress on the audiosynth base class. I just merged the branch. Now it writing a audio synth is a lot less code.

169 files changed, 7236 insertions(+), 6459 deletions(-)
More refactoring and unit test cleanups

In May I finished the refactoring of the sequence damage-repair code for updating the controller time-lines after pattern changes. It is a lot less code now and it is also faster. The "less code" is important as there is quite a bit of logic to handle combining events from patterns overlapping in time or on several tracks.

In the same vein, I could also refactor main-page-patterns with quite a nice code removal mount (~400 lines).

The Art of unit TestingWhile reading "The Art of Unit Testing" I decided to start cleaning up the test suite in buzztard. The changes so far result in tests that are more focused, less brittle and a lot smaller. I am writing down some of the tips on the wiki.

36 files changed, 2085 insertions(+), 2517 deletions(-)
Buzztard & Distro Versions

I started hacking on the transport settings. The idea here is to have a generic scheme for how to control playback (start, stop, seek) externally. This can be a midi-controller, but also qjackcontrol or a MPRIS applet. The setting now show the available modules and allow to enable master and slave mode as well as mode specific settings. I could remove the combobox from the toolbar again.

As a next big thing I started to refactor a big chunk of duplicated code in core. Machines have global parameters, per voice parameters and per incoming wire parameters. Now we have a parameter-group class that deals with those.

I spend the rest of the month cleaning up the test suite and the autofoo setup. On the latter I bumped the required versions. The policy now is to support the linux distributions from about the last two years. This allowed me to remove large chunks of conditional code. Unfortunately it is not easy to do that. The easy part is to check what versions we require, by looking at the pkg-config macros in configure.ac. Then we can also grep for conditional section in the code:
find . \( -name "*.c" -o -name "*.h" \) -exec egrep -o "[A-Z]*_CHECK_VERSION\(.*\)" {} \; | sort | uniq
Now the tricky part is to figure what distributions ship. It is somewhat easier for debian/ubuntu as they have pages like:
http://packages.debian.org/search?suite=all&arch=any&searchon=names&keywords=libgstreamer0.10-0 http://packages.ubuntu.com/search?suite=all&section=all&arch=any&searchon=names&keywords=libgstreamer0.10
For fedora Company suggested to look at the spec files in git and iterate over the branch names
http://pkgs.fedoraproject.org/gitweb/?p=gstreamer.git;a=blob;f=gstreamer.spec;hb=f17
For opensuse Vuntz suggested to use an osc query at which I failed misserably and in the end checked the packages in the repo and iterated over the versions:
http://download.opensuse.org/distribution/12.1/repo/oss/suse/i586/
Anyone know better tricks? Please share them!

One more motivation for doing this is upcomming gsoc. If I am lucky to get a student who will port buzztard to gstreamer 1.0. We'll release a 0.7 of buzztard before we switch to the new gstreamer api.

212 files changed, 7954 insertions(+), 7778 deletions(-)
GStreamer & Buzztard

As a big leftover promise from my talk at the GStreamer conference in 2011 I spend more time to understand latencies inside GStreamer. For plain playback the latencies are not an issue, but for anything interactive, be it entering notes or changing parameters while the song is playing, we want much lower latencies. For the talk I did some measurements by having a pipeline with two branches - src1 ! sink and src2 ! fx1 ! ... ! fxn ! sink. The fx elements where plain volume elements. The branches where panned hard left and right. For the experiment, I was pulling down the volume on the two sources down to 0 at the same time and recoding the audio on the sink. Looking at the wave, one could see the delay in the signal that went through the effect-chain. The longer the effect-chain the larger becomes the delay. Don't misunderstand this, GStreamer is properly handling A/V sync. The buffers that get mixed in front of the sink have the same time stamps, the problem is that we have a lot more buffers traveling the the effect-branch. This is because of the queue elements. In buzztard one can freely link generators to effects, effects to effects and effects to sinks. This includes diamond shaped connections. Here we need queues to not stall processing on one branch. It is sufficient for the queues to keep only 1 buffer. Still even knowing the buffer duration, I could not tell a formula to explain the measured delays.
This month I looked at the issue with a new idea. I wrote a small example that build pipelines close to what I have in buzztard, but stripped of many details. In this code I add buffer probed to all pads. The probe is comparing the time-stamp on the buffer to the pipeline clock. This tells how early the buffer is. Ideally we want buffers to be generated and processed as much in time as possible. When generating audio one needs to configure audio-buffer sizes on the source elements and two properties on the audio-sink - buffer-time and latency-time. A good scheme is to use buffer-time = 2 * latency-time. That configures the sink to have two audio-segments. Initially I also set the buffer sizes on the source elements to have a duration of latency-time. Now one problem with that is that we will have one buffer waiting on each queue. Thus if there are two queues the actual latency is (n-queues + 1) * latency-time. One way to improve that a bit is to half the buffer sizes on the sources, then the 2nd buffer is calculated when the first one is needed. As the first one won't be sufficient to fill the gap, the calculation of the 2nd buffer is scheduled right away. The disadvantage of this scheme is that one gets quite jittery latencies. In the end I settled on finishing the subtick timing in buzztard. Each tick will have n subticks, where n is setup so that we get down to the desired latency. So far I get nice low latency on all my machines (inlcuding a atom based netbook).

We also ported more buzzmachines and have 49 machines right now. When porting we often also fix bugs as gcc is quite good at warnings these days. Finally, the machines now also install docs (where available).

In the UI I got rid of the GtkRuler copy again. The analyzer window now has own code to draw the rulers. I think they look nice, a lot less noisy then the older rulers.

62 files changed, 1957 insertions(+), 1844 deletions(-)

127 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!