<?xml 
version="1.0" encoding="utf-8"?>
<rss version="2.0" 
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
>

<channel xml:lang="en">
	<title>blog.rastageeks.org</title>
	<link>http://blog.rastageeks.org/</link>
	
	<language>en</language>
	<generator>SPIP - www.spip.net</generator>

	<image>
		<title>blog.rastageeks.org</title>
		<url>http://blog.rastageeks.org/local/cache-vignettes/L100xH99/siteon0-cb303.png</url>
		<link>http://blog.rastageeks.org/</link>
		<height>99</height>
		<width>100</width>
	</image>



<item xml:lang="en">
		<title>Mingw32-ocaml 3.12.0</title>
		<link>http://blog.rastageeks.org/debian/article/mingw32-ocaml-3-12-0</link>
		<guid isPermaLink="true">http://blog.rastageeks.org/debian/article/mingw32-ocaml-3-12-0</guid>
		<dc:date>2010-08-11T23:02:54Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>Toots</dc:creator>


		<dc:subject>debian</dc:subject>
		<dc:subject>ocaml</dc:subject>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;An updated version of the &lt;a href='http://packages.qa.debian.org/m/mingw32-ocaml.html' class='spip_out' rel='external'&gt;ocaml cross-compiler package&lt;/a&gt;, based on ocaml 3.12.0, has just been uploaded to Debian experimental !&lt;/p&gt; &lt;p&gt;Any report and test on the package would be very welcome ! I have personally tested it with &lt;a href='http://savonet.sf.net/' class='spip_out' rel='external'&gt;Liquidsoap&lt;/a&gt; and built a &lt;a href='http://www.rastageeks.org/~toots/liq-win32/' class='spip_out' rel='external'&gt;win32 version&lt;/a&gt; of the software.&lt;/p&gt; &lt;p&gt;Since this build implies many external modules as well as C objects, I am pretty confident in the cross-compiler uploaded to experimental..&lt;/p&gt; &lt;p&gt;&lt;strong&gt;About the cross-compiler:&lt;/strong&gt; the ocaml cross-compiler is the result of the hard work done by &lt;a href='http://rwmj.wordpress.com/' class='spip_out' rel='external'&gt;Richard Jones&lt;/a&gt; for &lt;a href='https://fedoraproject.org/wiki/Features/Windows_cross_compiler' class='spip_out' rel='external'&gt;Fedora&lt;/a&gt;. The Debian package is merely a backport (and adaptation to ocaml 3.12.0) of his patches.&lt;/p&gt; &lt;p&gt;If you care about the future of the cross-compiler, the best you can do is work with upstream to find how to push the needed changes there in order to have a plain support for it.&lt;/p&gt; &lt;p&gt;I have personally no time for starting this process but I could try to describe the patches to an intereste contributor. Warning: some are REALLY hacky :-)&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>I have a dream...</title>
		<link>http://blog.rastageeks.org/other/article/i-have-a-dream</link>
		<guid isPermaLink="true">http://blog.rastageeks.org/other/article/i-have-a-dream</guid>
		<dc:date>2010-06-21T21:22:49Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>Toots</dc:creator>


		<dc:subject>debian</dc:subject>
		<dc:subject>ocaml</dc:subject>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;I have a dream that one day, serious programming language theoriticians, which would gather and realize that LaTeX has done a great job but is basically just a pile of rewriting rules built on top of postscript.&lt;/p&gt; &lt;p&gt;I have a dream that one day, one would get the fundings and rewrite from scratch a new &lt;strong&gt;language&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;A language with a clear syntax for describing the beautification constraints.&lt;/p&gt; &lt;p&gt;A language which would also be flexible enough to be able to override those constraints.&lt;/p&gt; &lt;p&gt;A language that would allow to write mathematic formula, macros and other tools without arcane tricks and hacks to obtain the required rending....&lt;/p&gt; &lt;p&gt;And much more...&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>Private records in OCaml</title>
		<link>http://blog.rastageeks.org/liquidsoap/article/private-records-in-ocaml</link>
		<guid isPermaLink="true">http://blog.rastageeks.org/liquidsoap/article/private-records-in-ocaml</guid>
		<dc:date>2010-06-15T00:23:43Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>Toots</dc:creator>


		<dc:subject>ocaml</dc:subject>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;In &lt;a href='http://ocaml.janestreet.com/?q=node/59' class='spip_out' rel='external'&gt;Private type abbreviations, what are they good for?&lt;/a&gt; [&lt;a href='#nb1' class='spip_note' rel='footnote' title='http://ocaml.janestreet.com/?q=node/59' id='nh1'&gt;1&lt;/a&gt;] and then in &lt;a href='http://ocaml.janestreet.com/?q=node/77' class='spip_out' rel='external'&gt;Another use for private type abbreviations&lt;/a&gt; [&lt;a href='#nb2' class='spip_note' rel='footnote' title='http://ocaml.janestreet.com/?q=node/77' id='nh2'&gt;2&lt;/a&gt;], yminsky wrote about the use of private type in OCaml.&lt;/p&gt; &lt;p&gt;Among the various proposed examples, the idea of read-only value was mentioned in the second post. I may have not followed the whole discussion after this, but I came on to an example in ocaml-ao today.&lt;/p&gt; &lt;p&gt;In ao, a driver is handled with an int, its id. It also has several read-only values, name, short_name etc..&lt;/p&gt; &lt;p&gt;Using a private record, it is possible to create a driver type this way:&lt;/p&gt;
&lt;div style='text-align: left;' class='spip_code' dir='ltr'&gt;&lt;code&gt;(** Driver type (private). *)&lt;br /&gt;
type driver_t = private&lt;br /&gt; { id : int ;&lt;br /&gt; kind : driver_kind_t ;&lt;br /&gt; short_name : string ;&lt;br /&gt; name : string ;&lt;br /&gt; comment : string ;&lt;br /&gt; author : string ;&lt;br /&gt; priority : int ;&lt;br /&gt; preferred_byte_format : byte_format_t ;&lt;br /&gt; options : string list&lt;br /&gt; }&lt;/code&gt;&lt;/div&gt;
&lt;p&gt;That way, one can access directly the fields of the record without being able to write a fresh one. In our case for instance, we then make sure that the id field, used when opening a device, is always a valid entry.&lt;/p&gt; &lt;p&gt;Another suggested use was, for bindings, when you have an extra internal field, like a state represented by a C void pointer. In this case, you may declare an object with n+1 element in the C function an only export the n first one as a private record type.. Its a bit hacky but it may be useful as well...&lt;/p&gt;&lt;/div&gt;
		&lt;hr /&gt;
		&lt;div class='rss_notes'&gt;&lt;p&gt;[&lt;a href='#nh1' id='nb1' class='spip_note' title='Footnotes 1' rev='footnote'&gt;1&lt;/a&gt;] &lt;a href='http://ocaml.janestreet.com/?q=node/59' class='spip_out' rel='nofollow external'&gt;http://ocaml.janestreet.com/?q=node/59&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh2' id='nb2' class='spip_note' title='Footnotes 2' rev='footnote'&gt;2&lt;/a&gt;] &lt;a href='http://ocaml.janestreet.com/?q=node/77' class='spip_out' rel='nofollow external'&gt;http://ocaml.janestreet.com/?q=node/77&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>Liquidsoap-full 0.9.2-2 and ocaml-cry 0.1.2</title>
		<link>http://blog.rastageeks.org/liquidsoap/article/liquidsoap-full-0-9-2-2-and-ocaml</link>
		<guid isPermaLink="true">http://blog.rastageeks.org/liquidsoap/article/liquidsoap-full-0-9-2-2-and-ocaml</guid>
		<dc:date>2010-03-08T23:13:43Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>Toots</dc:creator>


		<dc:subject>debian</dc:subject>
		<dc:subject>ocaml</dc:subject>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;An issue with the new ocaml-cry module that replaces the shout library has been recently discovered.&lt;/p&gt; &lt;p&gt;This issue was related to the data sent to the icecast server and could result in a higher load and loss of data when sending data to the server.&lt;/p&gt; &lt;p&gt;We have released a new version of ocaml-cry that fixes this issue, numbered 0.1.2.&lt;/p&gt; &lt;p&gt;We have also released a new liquidsoap-full tarball, numbered 0.9.2-2 and now available in the download section on &lt;a href='http://sourceforge.net/projects/savonet/files/' class='spip_out' rel='external'&gt;sourceforge.net&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Additionally, our custom stable packages have been rebuild against this new version, both for the i386 and the amd64 architecture.&lt;/p&gt; &lt;p&gt;The package available in Debian sid/unstable is now built against the fixed ocaml-cry as well.&lt;/p&gt; &lt;p&gt;We recommend that any user that uses liquidsoap 0.9.2 updates its liquidsoap to make sure it uses ocaml-cry 0.1.2.&lt;/p&gt; &lt;p&gt;Please note that ocaml modules are not dynamically loaded, so you need to rebuild liquidsoap against the new ocaml-cry if you are building from source.&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>OCaml cross compiler for win32 in Debian !</title>
		<link>http://blog.rastageeks.org/debian/article/ocaml-cross-compiler-for-win32-in</link>
		<guid isPermaLink="true">http://blog.rastageeks.org/debian/article/ocaml-cross-compiler-for-win32-in</guid>
		<dc:date>2010-02-11T16:01:20Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>Toots</dc:creator>


		<dc:subject>debian</dc:subject>
		<dc:subject>ocaml</dc:subject>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;Thanks to the great work from &lt;a href='http://rwmj.wordpress.com/' class='spip_out' rel='external'&gt;Richard Jones&lt;/a&gt; on building a &lt;a href='https://fedoraproject.org/wiki/Features/Windows_cross_compiler' class='spip_out' rel='external'&gt;OCaml cross-compiler for windows&lt;/a&gt;, we now have a similar package in Debian !&lt;/p&gt; &lt;p&gt;The package is called &lt;a href='http://packages.qa.debian.org/m/mingw32-ocaml.html' class='spip_out' rel='external'&gt;mingw32-ocaml&lt;/a&gt; and has just been accepted yesterday.&lt;/p&gt; &lt;p&gt;We have already used it to &lt;a href='http://www.mail-archive.com/savonet-users@lists.sourceforge.net/msg01947.html' class='spip_out' rel='external'&gt;build a win32 version&lt;/a&gt; of &lt;a href='http://savonet.sf.net/' class='spip_out' rel='external'&gt;liquidsoap&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;I hope that this cross-compiler will be useful to OCaml developers, in particular in porting their application to the world of windows and fences, in order to spread the word about how great OCaml is :-)&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>Liquidsoap 0.9.2 is out !</title>
		<link>http://blog.rastageeks.org/liquidsoap/article/liquidsoap-0-9-2-is-out</link>
		<guid isPermaLink="true">http://blog.rastageeks.org/liquidsoap/article/liquidsoap-0-9-2-is-out</guid>
		<dc:date>2009-10-31T03:45:23Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>Toots</dc:creator>


		<dc:subject>debian</dc:subject>
		<dc:subject>ocaml</dc:subject>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;The savonet team is proud to announce the release of &lt;a href='http://savonet.sourceforge.net/' class='spip_out' rel='external'&gt;liquidsoap&lt;/a&gt; [&lt;a href='#nb1' class='spip_note' rel='footnote' title='http://savonet.sourceforge.net/' id='nh1'&gt;1&lt;/a&gt;] 0.9.2.
This release is a snapshot of upcoming features, but it also brings
several important bugfixes. As a snapshot, it contains experimental
and unpolished features, and also slightly breaks compatibility with
previous 0.9.x versions.&lt;/p&gt; &lt;p&gt;The interesting features in this release are:&lt;/p&gt; &lt;ul&gt;
&lt;li&gt; Switched to a custom implementation of the shout protocols. This allows in particular AAC+ output support, using either the external &lt;a href='http://teknoraver.net/software/mp4tools/' class='spip_out' rel='external'&gt;aacpluenc&lt;/a&gt; [&lt;a href='#nb2' class='spip_note' rel='footnote' title='http://teknoraver.net/software/mp4tools/' id='nh2'&gt;2&lt;/a&gt;] binary or the native &lt;a href='http://tipok.org.ua/ru/taxonomy/term/36' class='spip_out' rel='external'&gt;libaacplus&lt;/a&gt; [&lt;a href='#nb3' class='spip_note' rel='footnote' title='http://tipok.org.ua/ru/taxonomy/term/36' id='nh3'&gt;3&lt;/a&gt;] [&lt;a href='#nb4' class='spip_note' rel='footnote' title='Output using libaacplus is still experimental and bug prone and both (...)' id='nh4'&gt;4&lt;/a&gt;].
&lt;li&gt;New scheduling algorithm for request-based sources which avoids queueing multiple songs at once.
&lt;li&gt;Support for &lt;a href='http://libre.fm/' class='spip_out' rel='external'&gt;libre.fm&lt;/a&gt; [&lt;a href='#nb5' class='spip_note' rel='footnote' title='http://libre.fm/' id='nh5'&gt;5&lt;/a&gt;].
&lt;li&gt;Built-in support for extracting &lt;a href='http://en.wikipedia.org/wiki/Replay_Gain' class='spip_out' rel='external'&gt;replay gain&lt;/a&gt; [&lt;a href='#nb6' class='spip_note' rel='footnote' title='http://en.wikipedia.org/wiki/Replay_Gain' id='nh6'&gt;6&lt;/a&gt;] metadata.
&lt;li&gt;Supports for fallible outputs.
&lt;li&gt;MANY bugfixes !
&lt;/ul&gt;
&lt;p&gt;You can read a detailed changelog &lt;a href='http://savonet.rastageeks.org/browser/tags/liquidsoap/0.9.2/CHANGES' class='spip_out' rel='external'&gt;there&lt;/a&gt; [&lt;a href='#nb7' class='spip_note' rel='footnote' title='http://savonet.rastageeks.org/brows...' id='nh7'&gt;7&lt;/a&gt;].&lt;/p&gt; &lt;p&gt;This release is a milestone on our way to liquidsoap 1.0.0. Major
changes are going to be merged into the main development branch now.
We keep getting closer!&lt;/p&gt; &lt;p&gt;The Debian package for sid/unstable will soon be available too.&lt;/p&gt; &lt;p&gt;Additionally, a stable debian backport should be available anytime soon.&lt;/p&gt;&lt;/div&gt;
		&lt;hr /&gt;
		&lt;div class='rss_notes'&gt;&lt;p&gt;[&lt;a href='#nh1' id='nb1' class='spip_note' title='Footnotes 1' rev='footnote'&gt;1&lt;/a&gt;] &lt;a href='http://savonet.sourceforge.net/' class='spip_out' rel='nofollow external'&gt;http://savonet.sourceforge.net/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh2' id='nb2' class='spip_note' title='Footnotes 2' rev='footnote'&gt;2&lt;/a&gt;] &lt;a href='http://teknoraver.net/software/mp4tools/' class='spip_out' rel='nofollow external'&gt;http://teknoraver.net/software/mp4tools/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh3' id='nb3' class='spip_note' title='Footnotes 3' rev='footnote'&gt;3&lt;/a&gt;] &lt;a href='http://tipok.org.ua/ru/taxonomy/term/36' class='spip_out' rel='nofollow external'&gt;http://tipok.org.ua/ru/taxonomy/term/36&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh4' id='nb4' class='spip_note' title='Footnotes 4' rev='footnote'&gt;4&lt;/a&gt;] Output using libaacplus is still experimental and bug prone and both outputs suffer from the limitations of the same codebase, in particlar when streaming at low bitrate such as 32Kbps..&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh5' id='nb5' class='spip_note' title='Footnotes 5' rev='footnote'&gt;5&lt;/a&gt;] &lt;a href='http://libre.fm/' class='spip_out' rel='nofollow external'&gt;http://libre.fm/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh6' id='nb6' class='spip_note' title='Footnotes 6' rev='footnote'&gt;6&lt;/a&gt;] &lt;a href='http://en.wikipedia.org/wiki/Replay_Gain' class='spip_out' rel='nofollow external'&gt;http://en.wikipedia.org/wiki/Replay_Gain&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh7' id='nb7' class='spip_note' title='Footnotes 7' rev='footnote'&gt;7&lt;/a&gt;] &lt;a href='http://savonet.rastageeks.org/browser/tags/liquidsoap/0.9.2/CHANGES' class='spip_out' rel='nofollow external'&gt;http://savonet.rastageeks.org/brows...&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>Ocaml-cry</title>
		<link>http://blog.rastageeks.org/liquidsoap/article/ocaml-cry</link>
		<guid isPermaLink="true">http://blog.rastageeks.org/liquidsoap/article/ocaml-cry</guid>
		<dc:date>2009-10-15T05:42:15Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>Toots</dc:creator>


		<dc:subject>debian</dc:subject>
		<dc:subject>ocaml</dc:subject>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;Coming along with the next release of liquidsoap, we have just released a new module for ocaml, namely ocaml-cry.&lt;/p&gt; &lt;p&gt;Ocaml-cry is a native implementation of the protocols used for sending source data to icecast and shoutcast servers.&lt;/p&gt; &lt;p&gt;The main difference with the famous libshout implementation is about flexibility. This module allows to set any source header, which in particular allows to use any custom format which is compatible with the servers.&lt;/p&gt; &lt;p&gt;However, contrary to libshout, ocaml-cry does not handle the synchronisation of the audio data sent to the servers. Hence, the task of controling the rate of the data sent is up to the programmer.&lt;/p&gt; &lt;p&gt;You can find more informations on this module there:&lt;/p&gt; &lt;p&gt; &lt;a href='http://www.rastageeks.org/cry.html' class='spip_out' rel='external'&gt;http://www.rastageeks.org/cry.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Debian packages are available there [&lt;a href='#nb1' class='spip_note' rel='footnote' title='Many thanks to the ftp-masters for dealing with the NEW package so fast (...)' id='nh1'&gt;1&lt;/a&gt;]:&lt;/p&gt; &lt;p&gt; &lt;a href='http://packages.debian.org/libcry-ocaml-dev' class='spip_out' rel='external'&gt;http://packages.debian.org/libcry-ocaml-dev&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
		&lt;hr /&gt;
		&lt;div class='rss_notes'&gt;&lt;p&gt;[&lt;a href='#nh1' id='nb1' class='spip_note' title='Footnotes 1' rev='footnote'&gt;1&lt;/a&gt;] Many thanks to the ftp-masters for dealing with the NEW package so fast !&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>DJ mix using liquidsoap</title>
		<link>http://blog.rastageeks.org/liquidsoap/article/dj-mix-using-liquidsoap</link>
		<guid isPermaLink="true">http://blog.rastageeks.org/liquidsoap/article/dj-mix-using-liquidsoap</guid>
		<dc:date>2009-06-08T16:26:48Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>Toots</dc:creator>


		<dc:subject>debian</dc:subject>
		<dc:subject>ocaml</dc:subject>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;&lt;span class='spip_document_62 spip_documents spip_documents_center'&gt;
&lt;a href=&quot;http://www.flickr.com/photos/12tribu/475919417/&quot;&gt;&lt;img src='http://blog.rastageeks.org/local/cache-vignettes/L320xH238/DJ-17ece.jpg' width='320' height='238' alt=&quot;&quot; style='height:238px;width:320px;' /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;Recently, I wanted to generate a single audio file containing the mix of several others, in order to publish it as a podcast.&lt;/p&gt; &lt;p&gt;The purpose of this is, based on an playlist of songs, to generate a single audio file containing an enhanced sequence of these songs. We would also like to normalize the volumes between the songs and have nice crossfaded transitions.&lt;/p&gt; &lt;p&gt;As you can imagine, I used my tool of choice for that purpose: liquidsoap !&lt;/p&gt; &lt;p&gt;In the following is presented the script that performs that. It takes a playlist, located at &lt;code class='spip_code' dir='ltr'&gt;./playlist.m3u&lt;/code&gt;, and introductory jingle, located at &lt;code class='spip_code' dir='ltr'&gt;./intro.mp3&lt;/code&gt; and generates &lt;code class='spip_code' dir='ltr'&gt;mix.mp3&lt;/code&gt;, &lt;code class='spip_code' dir='ltr'&gt;mix.ogg&lt;/code&gt; and &lt;code class='spip_code' dir='ltr'&gt;mix.aac&lt;/code&gt;.&lt;/p&gt; &lt;p&gt;The script is commented. There were minor issues with the playlist parsing not preserving the ordering, so it should be run with a recent SVN code.&lt;/p&gt; &lt;p&gt;Also, the script uses a perl handler to extract replay gain information. This script is:&lt;/p&gt; &lt;div style='text-align: left;' class='spip_code' dir='ltr'&gt;&lt;code&gt;#!/usr/bin/perl -w&lt;br /&gt; # A perl script that get the replay gain&lt;br /&gt; # from either a vorbis or an mp3 file&lt;br /&gt; # and returns it.&lt;br /&gt; &lt;br /&gt; use strict ;&lt;br /&gt; &lt;br /&gt; my $file = $ARGV[0] || die ;&lt;br /&gt; &lt;br /&gt; if ($file =~ /\.mp3$/i) {&lt;br /&gt; &lt;br /&gt; my $out = `nice -n 20 mp3gain &quot;$file&quot; 2&gt; /dev/null` ;&lt;br /&gt; $out =~ /Recommended &quot;Track&quot; dB change: (.*)$/m || die ;&lt;br /&gt; print &quot;$1 dB\n&quot; ;&lt;br /&gt; &lt;br /&gt; } elsif ($file =~ /\.ogg$/i) {&lt;br /&gt; &lt;br /&gt; system(&quot;nice -n 20 vorbisgain -f \&quot;$file\&quot; \&lt;br /&gt; 2&gt;/dev/null &gt;/dev/null&quot;) ;&lt;br /&gt; my $info = `ogginfo &quot;$file&quot;` ;&lt;br /&gt; $info =~ /REPLAYGAIN_TRACK_GAIN=(.*) dB/ || die ;&lt;br /&gt; print &quot;$1 dB\n&quot; ;&lt;br /&gt; &lt;br /&gt; }&lt;/code&gt;&lt;/div&gt;
&lt;p&gt;Eventually, the final script is:&lt;/p&gt; &lt;div style='text-align: left;' class='spip_code' dir='ltr'&gt;&lt;code&gt;# Liquidsoap script that generates the mix of a playlist&lt;br /&gt; # in a single audio file, with normalization using&lt;br /&gt; # replay gain, and smart crossfading.&lt;br /&gt; # Author: Romain Beauxis &lt;toots@rastageeks.org&gt;&lt;br /&gt; # License: DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE&lt;br /&gt; # License URL: http://sam.zoy.org/wtfpl/COPYING&lt;br /&gt; &lt;br /&gt; &lt;br /&gt; ########### Settings ###########&lt;br /&gt; # In this section, we declare&lt;br /&gt; # the settings for this script.&lt;br /&gt; &lt;br /&gt; # Log to stdout&lt;br /&gt; set(&quot;log.file&quot;,false)&lt;br /&gt; set(&quot;log.stdout&quot;,true)&lt;br /&gt; # Uncomment to allow verbose logging..&lt;br /&gt; #set(&quot;log.level&quot;,5)&lt;br /&gt; # Disable real-time processing, to process with the maximun speed&lt;br /&gt; set(&quot;root.sync&quot;,false)&lt;br /&gt; &lt;br /&gt; ########### Replay Gain Backend ###########&lt;br /&gt; # In this section, we register the replay &lt;br /&gt; # gain backend, to add replay gain information&lt;br /&gt; # to each resolved file.&lt;br /&gt; &lt;br /&gt; # Function to add replay_gain information &lt;br /&gt; # to the metadata&lt;br /&gt; def replaygain_metadata(~format,file)&lt;br /&gt; x = get_process_lines(&quot;./replaygain.pl #{quote(file)}&quot;)&lt;br /&gt; if list.hd(x) != &quot;&quot; then&lt;br /&gt; [(&quot;replay_gain&quot;,list.hd(x))]&lt;br /&gt; else&lt;br /&gt; []&lt;br /&gt; end&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; # We register the above function as a new metadata resolver.&lt;br /&gt; add_metadata_resolver(&quot;replay_gain&quot;,replaygain_metadata)&lt;br /&gt; &lt;br /&gt; ########### Source Declaration ###########&lt;br /&gt; # In this section, we declare the main source&lt;br /&gt; # that we want to output.&lt;br /&gt; &lt;br /&gt; # An introductory single&lt;br /&gt; intro = single(&quot;./intro.mp3&quot;)&lt;br /&gt; &lt;br /&gt; # The main playlist&lt;br /&gt; playlist = playlist.once(&quot;./playlist.m3u&quot;)&lt;br /&gt; &lt;br /&gt; # We normalize audio files, according to the&lt;br /&gt; # replay_gain information (see above).&lt;br /&gt; final = amplify(1.,override=&quot;replay_gain&quot;,sequence([intro,playlist]))&lt;br /&gt; &lt;br /&gt; # We use the smart crossfade, to crossfade between tracks, &lt;br /&gt; # paying attention to the relative volumes.&lt;br /&gt; # It is of course advised to place this operator *after* &lt;br /&gt; # the normalization !&lt;br /&gt; final = smart_crossfade(final)&lt;br /&gt; &lt;br /&gt; ########### Shutdown fallback ###########&lt;br /&gt; # In this section, we wrap the main source&lt;br /&gt; # in order to shutdown liquidsoap when&lt;br /&gt; # it has finished to play.&lt;br /&gt; &lt;br /&gt; # We define a special transition, that&lt;br /&gt; # triggers the shutdown..&lt;br /&gt; def end_trans(a,b) =&lt;br /&gt; shutdown ()&lt;br /&gt; b&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; # The default transition&lt;br /&gt; def_trans = fun (a,b) -&gt; b&lt;br /&gt; &lt;br /&gt; # The fallback source: play the whole mix, and &lt;br /&gt; # then fallback to a blank. The end_trans transition &lt;br /&gt; # makes sure that liquidsoap stops when falling back to the blank&lt;br /&gt; # source, i.e. at the end of the mixed playlist.&lt;br /&gt; final = fallback(transitions=[def_trans,end_trans], &lt;br /&gt; track_sensitive=false, [final,blank()])&lt;br /&gt; &lt;br /&gt; ########### Outputs ###########&lt;br /&gt; # In this section, we define the output&lt;br /&gt; # that we want.&lt;br /&gt; &lt;br /&gt; # Output in mp3 format&lt;br /&gt; output.file.mp3(&quot;mix.mp3&quot;,final)&lt;br /&gt; &lt;br /&gt; # Output in ogg/vorbis format&lt;br /&gt; output.file.vorbis(&quot;mix.ogg&quot;,final)&lt;br /&gt; &lt;br /&gt; # Output in AAC+ format in 64kbps &lt;br /&gt; # (needs aacplusenc in the path)&lt;br /&gt; output.pipe.external(process=fun (_) -&gt; &quot;aacplusenc - mix.aac 64&quot;,&lt;br /&gt; final)&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>Lastfm no longer free as in free beer (and some bits about xml in OCaml)</title>
		<link>http://blog.rastageeks.org/other/article/lastfm-no-longer-free-as-in-free</link>
		<guid isPermaLink="true">http://blog.rastageeks.org/other/article/lastfm-no-longer-free-as-in-free</guid>
		<dc:date>2009-04-23T07:42:34Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>Toots</dc:creator>


		<dc:subject>debian</dc:subject>
		<dc:subject>ocaml</dc:subject>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;h3 class=&quot;spip&quot;&gt; Lastfm no longer free as in free beer &lt;/h3&gt;
&lt;p&gt;&lt;span class='spip_document_58 spip_documents spip_documents_center'&gt;
&lt;a href=&quot;http://www.flickr.com/photos/lorispindler/2559724403/&quot; class=&quot;spip_out&quot;&gt;&lt;img src='http://blog.rastageeks.org/local/cache-vignettes/L400xH300/2559724403_7d5e535df1-201d1.jpg' width='400' height='300' alt=&quot;&quot; style='height:300px;width:400px;' /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;As I was trying move the code of &lt;a href='http://www.rastageeks.org/lastfm.html' class='spip_out' rel='external'&gt;ocaml-lastfm&lt;/a&gt; [&lt;a href='#nb1' class='spip_note' rel='footnote' title='Ocaml-lastfm: http://www.rastageeks.org/lastfm.html' id='nh1'&gt;1&lt;/a&gt;] from the unmaintained &lt;a href='http://tech.motion-twin.com/xmllight.html' class='spip_out' rel='external'&gt;xml-light&lt;/a&gt; [&lt;a href='#nb2' class='spip_note' rel='footnote' title='Xml-light: http://tech.motion-twin.com/xmlligh...' id='nh2'&gt;2&lt;/a&gt;] to &lt;a href='http://erratique.ch/software/xmlm' class='spip_out' rel='external'&gt;xmlm&lt;/a&gt; [&lt;a href='#nb3' class='spip_note' rel='footnote' title='Xmlm: http://erratique.ch/software/xmlm' id='nh3'&gt;3&lt;/a&gt;], I discovered that it now fails to request track in anonymous mode.&lt;/p&gt; &lt;p&gt;Then, I went on the &lt;a href='http://www.last.fm/' class='spip_out' rel='external'&gt;lastfm&lt;/a&gt; [&lt;a href='#nb4' class='spip_note' rel='footnote' title='Lastfm: http://www.last.fm/' id='nh4'&gt;4&lt;/a&gt;] site, and discovered that now I cannot find any full content available for anonymous users. Some more researches and I found &lt;a href='http://blog.last.fm/2009/04/22/radio-subscriptions' class='spip_out' rel='external'&gt;this&lt;/a&gt; [&lt;a href='#nb5' class='spip_note' rel='footnote' title='&quot;Radio Subscriptions&quot;: http://blog.last.fm/2009/04/22/radi...' id='nh5'&gt;5&lt;/a&gt;]:&lt;/p&gt; &lt;blockquote class=&quot;spip&quot;&gt;
&lt;p&gt;
Today we are making the changes to the radio that were previously announced here.&lt;/p&gt; &lt;p&gt;This means that from today, listeners to Last.fm Radio outside of the USA, UK and Germany will be asked to subscribe for &#8364;3.00 per month, after a 30 track free trial period. In the USA, UK and Germany, where it's feasible to run an ad-supported radio service, there won't be any changes. Everything else on Last.fm (scrobbling, recommendations, charts, biographies, events, videos etc.) will remain free in all countries, like it is now.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;dl class='spip_document_57 spip_documents spip_documents_center'&gt;
&lt;dt&gt;&lt;a href=&quot;http://fr.wikipedia.org/wiki/Fichier:Fr%C3%A9d%C3%A9ric_Christol_-_L%27Alcool_!_Voil%C3%A0_l%27ennemi.jpg&quot; class=&quot;spip_out&quot; title='JPEG - 42.5 kb'&gt;&lt;img src='http://blog.rastageeks.org/local/cache-vignettes/L300xH412/437px-Frederic_Christol_-_L_Alcool___Voila_l_ennemi-234b0.jpg' width='300' height='412' alt='JPEG - 42.5 kb' style='height:412px;width:300px;' /&gt;&lt;/a&gt;&lt;/dt&gt;
&lt;dt class='crayon document-titre-57 spip_doc_titre' style='width:300px;'&gt;&lt;strong&gt;Alcool ! Voil&#224; l'ennemi.&lt;/strong&gt;&lt;/dt&gt;
&lt;dd class='crayon document-descriptif-57 spip_doc_descriptif' style='width:300px;'&gt;Poster by French painter and missionary Fr&#233;d&#233;ric Christol (1850-1933) warning of the dangers of absinthe and other alcoholic drinks.
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Although I will not comment this with the same violence as in the comments of the above message, this is not a good news at all. I totally understand how it can be difficult to find financial resources for this kind of business, and how complicated it can be after few years to maintain an activity that initially was breaking new and attracting investors.&lt;/p&gt; &lt;p&gt;However, given the current &lt;a href='http://www.p2pnet.net/story/19074' class='spip_out' rel='external'&gt;global&lt;/a&gt; [&lt;a href='#nb6' class='spip_note' rel='footnote' title='&quot;New Zealand: safe from Big Music. Or is it?&quot;: http://www.p2pnet.net/story/19074' id='nh6'&gt;6&lt;/a&gt;] &lt;a href='http://www.numerama.com/magazine/12702_7-La-Quadrature-du-Net-discreditee-aupres-des-deputes-anti-Hadopi.html' class='spip_out' hreflang='fr' rel='external'&gt;propaganda&lt;/a&gt; [&lt;a href='#nb7' class='spip_note' rel='footnote' title='&quot; La Quadrature du Net discr&#233;dit&#233;e aupr&#232;s des d&#233;put&#233;s anti-Hadopi&quot;: (...)' id='nh7'&gt;7&lt;/a&gt;] &lt;a href='http://www.ecrans.fr/Faux-proces-Les-pirates-paient,7000.html' class='spip_out' hreflang='fr' rel='external'&gt;campaign&lt;/a&gt; [&lt;a href='#nb8' class='spip_note' rel='footnote' title='&quot;Faux proc&#232;s : Les pirates paient&quot;: http://www.ecrans.fr/Faux-proces-Le.... (...)' id='nh8'&gt;8&lt;/a&gt;] that is &lt;a href='http://tjmcintyre.com/2009/01/three-strikes-for-ireland-eircom-music.html' class='spip_out' rel='external'&gt;organized&lt;/a&gt; [&lt;a href='#nb9' class='spip_note' rel='footnote' title='&quot;&quot;Three strikes&quot; for Ireland - Eircom, music industry settle filtering (...)' id='nh9'&gt;9&lt;/a&gt;] by the major music companies, I do not believe this decision has only to do with lastfm's financial resources. In particular, also the legality of &lt;a href='http://www.deezer.com/' class='spip_out' rel='external'&gt;Deezer&lt;/a&gt; [&lt;a href='#nb10' class='spip_note' rel='footnote' title='Deezer: http://www.deezer.com/' id='nh10'&gt;10&lt;/a&gt;] was &lt;a href='http://french-law.net/universal-music-challenges-the-legality-of-deezer-a-free-streaming-website.html' class='spip_out' rel='external'&gt;challenged by universal&lt;/a&gt; [&lt;a href='#nb11' class='spip_note' rel='footnote' title='&quot;Universal Music challenges the legality of Deezer, a free streaming (...)' id='nh11'&gt;11&lt;/a&gt;] such that they had to &lt;a href='http://forums.techarena.in/technology-internet/1119698.htm' class='spip_out' rel='external'&gt;require registration&lt;/a&gt; [&lt;a href='#nb12' class='spip_note' rel='footnote' title='&quot;Now Deezer Required Registration&quot;: http://forums.techarena.in/technolo...' id='nh12'&gt;12&lt;/a&gt;] and also limit drastically the available titles.&lt;/p&gt; &lt;p&gt;The current situation is now really becoming worse and worse. Not only the music companies are trying to push for dangerous laws for the civil rights while pretending to fight against illegal music sharing, but also they are trying to shutdown all the new competitors that were successful in doing exactly what they refused to do during the same time.&lt;/p&gt; &lt;p&gt;&lt;span class='spip_document_60 spip_documents spip_documents_center'&gt;
&lt;a href=&quot;http://www.flickr.com/photos/dewarsrepealday/3080895020/in/photostream/&quot; class=&quot;spip_out&quot;&gt;&lt;img src='http://blog.rastageeks.org/local/cache-vignettes/L400xH305/3080059621_0282a31a52-83f02.jpg' width='400' height='305' alt=&quot;&quot; style='height:305px;width:400px;' /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;All of this is just simply pathetic, and I strongly hope there will soon be an end to this, which will surely mean for these companies adapt or perish.. Or perhaps they plan to impose their restricting and dangerous laws in any country in the world ?&lt;/p&gt; &lt;p&gt;Another remark about all this is that it clearly demonstrate the importance of having the right to copy and store for your own usage any copyrighted material. Indeed, these are not only products but also artistic productions, and for this reason it is important to be able to save them in some place in order to not loose track of it if the streaming company was to be shutdown, as it seems to be the trend now.&lt;/p&gt; &lt;dl class='spip_document_59 spip_documents spip_documents_center'&gt;
&lt;dt&gt;&lt;a href=&quot;http://de.wikipedia.org/w/index.php?title=Datei:Oliva.jpg&quot; class=&quot;spip_out&quot; title='JPEG - 71 kb'&gt;&lt;img src='http://blog.rastageeks.org/local/cache-vignettes/L400xH300/Oliva-f6fbb.jpg' width='400' height='300' alt='JPEG - 71 kb' style='height:300px;width:400px;' /&gt;&lt;/a&gt;&lt;/dt&gt;
&lt;dt class='crayon document-titre-59 spip_doc_titre' style='width:350px;'&gt;&lt;strong&gt;Viktor Oliva: The Absinthe Drinker.&lt;/strong&gt;&lt;/dt&gt;
&lt;dd class='crayon document-descriptif-59 spip_doc_descriptif' style='width:350px;'&gt;The original painting can be found in the Caf&#233; Slavia in Prague.
&lt;/dd&gt;
&lt;/dl&gt;
&lt;h3 class=&quot;spip&quot;&gt; Moving from xml-light to Xmlm &lt;/h3&gt;
&lt;p&gt;The other part of this post is about moving from xml-light to xmlm. This is in fact very easy, and should only be a matter of adding a piece of code like this:&lt;/p&gt; &lt;div style='text-align: left;' class='spip_code' dir='ltr'&gt;&lt;code&gt;type xml =&lt;br /&gt; | Element of (string * (string * string) list * xml list)&lt;br /&gt; | PCData of string&lt;br /&gt; &lt;br /&gt; let parse_string s =&lt;br /&gt; let source = `String (0,s) in&lt;br /&gt; let input = Xmlm.make_input source in&lt;br /&gt; (* Map a tag representation in xmlm to&lt;br /&gt; * (name, attributes list) where attribute = string*string. *)&lt;br /&gt; let make_tag (x,l) = &lt;br /&gt; (* Forget about the uri attribute *)&lt;br /&gt; let l = &lt;br /&gt; List.map (fun ((_,y),z) -&gt; (y,z)) l &lt;br /&gt; in&lt;br /&gt; snd x,l&lt;br /&gt; in&lt;br /&gt; let rec get_elems l =&lt;br /&gt; if Xmlm.eoi input then&lt;br /&gt; l&lt;br /&gt; else&lt;br /&gt; match Xmlm.input input with&lt;br /&gt; | `El_start tag -&gt; &lt;br /&gt; let elem = get_elems [] in&lt;br /&gt; let (name,attributes) = make_tag tag in&lt;br /&gt; get_elems ((Element (name, attributes, List.rev elem)) :: l)&lt;br /&gt; | `El_end -&gt; l&lt;br /&gt; | `Data s -&gt; &lt;br /&gt; get_elems ((PCData s) :: l)&lt;br /&gt; | `Dtd _ -&gt; get_elems l&lt;br /&gt; in&lt;br /&gt; let elems = get_elems [] in&lt;br /&gt; Element (&quot;&quot;, [], List.rev elems)&lt;/code&gt;&lt;/div&gt;
&lt;p&gt;This is a very simple code that surely needs more fixes, but starting from that, you can parse a string into an equivalent representation of the xml data, and then use it as before in your code..&lt;/p&gt;&lt;/div&gt;
		&lt;hr /&gt;
		&lt;div class='rss_notes'&gt;&lt;p&gt;[&lt;a href='#nh1' id='nb1' class='spip_note' title='Footnotes 1' rev='footnote'&gt;1&lt;/a&gt;] Ocaml-lastfm: &lt;a href='http://www.rastageeks.org/lastfm.html' class='spip_out' rel='external'&gt;http://www.rastageeks.org/lastfm.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh2' id='nb2' class='spip_note' title='Footnotes 2' rev='footnote'&gt;2&lt;/a&gt;] Xml-light: &lt;a href='http://tech.motion-twin.com/xmllight.html' class='spip_out' rel='external'&gt;http://tech.motion-twin.com/xmlligh...&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh3' id='nb3' class='spip_note' title='Footnotes 3' rev='footnote'&gt;3&lt;/a&gt;] Xmlm: &lt;a href='http://erratique.ch/software/xmlm' class='spip_out' rel='nofollow external'&gt;http://erratique.ch/software/xmlm&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh4' id='nb4' class='spip_note' title='Footnotes 4' rev='footnote'&gt;4&lt;/a&gt;] Lastfm: &lt;a href='http://www.last.fm/' class='spip_out' rel='nofollow external'&gt;http://www.last.fm/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh5' id='nb5' class='spip_note' title='Footnotes 5' rev='footnote'&gt;5&lt;/a&gt;] &quot;Radio Subscriptions&quot;: &lt;a href='http://blog.last.fm/2009/04/22/radio-subscriptions' class='spip_out' rel='nofollow external'&gt;http://blog.last.fm/2009/04/22/radi...&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh6' id='nb6' class='spip_note' title='Footnotes 6' rev='footnote'&gt;6&lt;/a&gt;] &quot;New Zealand: safe from Big Music. Or is it?&quot;: &lt;a href='http://www.p2pnet.net/story/19074' class='spip_out' rel='nofollow external'&gt;http://www.p2pnet.net/story/19074&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh7' id='nb7' class='spip_note' title='Footnotes 7' rev='footnote'&gt;7&lt;/a&gt;] &quot;
La Quadrature du Net discr&#233;dit&#233;e aupr&#232;s des d&#233;put&#233;s anti-Hadopi&quot;: &lt;a href='http://www.numerama.com/magazine/12702_7-La-Quadrature-du-Net-discreditee-aupres-des-deputes-anti-Hadopi.html' class='spip_out' rel='external'&gt;http://www.numerama.com/magazine/12...&lt;/a&gt;. Link is in french. It explains how, after filling a so-called petition with hundreds of signatures from employees presented as artists, or artists abused by the presentation of the content, these companies complain about the &quot;totalitarian methods&quot; used to verify the validity of the signature, which were simply based on the public available information on these names on the web, while they propose a system that would automatically cut the internet access to probably 1.000 people a day in France...&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh8' id='nb8' class='spip_note' title='Footnotes 8' rev='footnote'&gt;8&lt;/a&gt;] &quot;Faux proc&#232;s : Les pirates paient&quot;: &lt;a href='http://www.ecrans.fr/Faux-proces-Les-pirates-paient,7000.html' class='spip_out' rel='external'&gt;http://www.ecrans.fr/Faux-proces-Le...&lt;/a&gt;. again, in french, the article reports a Danish study that prove once again that people who tend to download a lot of music are also much more likely to spend their money in the music business, being concert, records or else..&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh9' id='nb9' class='spip_note' title='Footnotes 9' rev='footnote'&gt;9&lt;/a&gt;] &quot;&quot;Three strikes&quot; for Ireland - Eircom, music industry settle filtering case&quot;: &lt;a href='http://tjmcintyre.com/2009/01/three-strikes-for-ireland-eircom-music.html' class='spip_out' rel='external'&gt;http://tjmcintyre.com/2009/01/three...&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh10' id='nb10' class='spip_note' title='Footnotes 10' rev='footnote'&gt;10&lt;/a&gt;] Deezer: &lt;a href='http://www.deezer.com/' class='spip_out' rel='external'&gt;http://www.deezer.com/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh11' id='nb11' class='spip_note' title='Footnotes 11' rev='footnote'&gt;11&lt;/a&gt;] &quot;Universal Music challenges the legality of Deezer, a free streaming website&quot;: &lt;a href='http://french-law.net/universal-music-challenges-the-legality-of-deezer-a-free-streaming-website.html' class='spip_out' rel='external'&gt;http://french-law.net/universal-mus...&lt;/a&gt;&lt;/p&gt; &lt;p&gt;[&lt;a href='#nh12' id='nb12' class='spip_note' title='Footnotes 12' rev='footnote'&gt;12&lt;/a&gt;] &quot;Now Deezer Required Registration&quot;: &lt;a href='http://forums.techarena.in/technology-internet/1119698.htm' class='spip_out' rel='external'&gt;http://forums.techarena.in/technolo...&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="en">
		<title>Liquidsoap now supports AAC+ encoding.</title>
		<link>http://blog.rastageeks.org/liquidsoap/article/liquidsoap-now-supports-aac</link>
		<guid isPermaLink="true">http://blog.rastageeks.org/liquidsoap/article/liquidsoap-now-supports-aac</guid>
		<dc:date>2009-04-21T18:11:17Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>en</dc:language>
		<dc:creator>Toots</dc:creator>


		<dc:subject>debian</dc:subject>
		<dc:subject>ocaml</dc:subject>


 <content:encoded>&lt;div class='rss_texte'&gt;&lt;p&gt;&lt;span class='spip_document_51 spip_documents spip_documents_center'&gt;
&lt;a href=&quot;http://commons.wikimedia.org/wiki/File:Copyleft_Pirate_symbol.svg&quot; class=&quot;spip_out&quot;&gt;&lt;img src='http://blog.rastageeks.org/local/cache-vignettes/L200xH133/744px-Copyleft_Pirate_symbol-svg-79030.png' width='200' height='133' alt=&quot;&quot; style='height:133px;width:200px;' /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;h3 class=&quot;spip&quot;&gt;The plot&lt;/h3&gt;
&lt;p&gt;Following many &lt;a href='http://savonet.rastageeks.org/ticket/220' class='spip_out' rel='external'&gt;user&lt;/a&gt; &lt;a href='http://savonet.rastageeks.org/ticket/136' class='spip_out' rel='external'&gt;requests&lt;/a&gt; , we were considering adding this format to the list of supported encoders.&lt;/p&gt; &lt;p&gt;As for mp3 encoding, this support was subject to some &lt;a href='http://en.wikipedia.org/wiki/AAC%2B#Licensing_and_patents' class='spip_out' rel='external'&gt;legal issues&lt;/a&gt;. These issues were indeed the initial motivation for implementing &lt;a href='http://www.icecast.org/' class='spip_out' rel='external'&gt;icecast2&lt;/a&gt; using the patent-free ogg codecs and container for streaming data.&lt;/p&gt; &lt;p&gt;However, it seems that many users and net-radios are still asking for these formats. There can be several motivations for that, among which I can list the following major ones:&lt;/p&gt; &lt;ul&gt;
&lt;li&gt;These formats are supported by more players and, in particular, embedded devices, which are the main target for net-radios
&lt;li&gt;For the case of AAC+, the codec supports a very good audio quality for low bandwidths, such as 64 and 32kb/s.
&lt;/ul&gt;
&lt;h3 class=&quot;spip&quot;&gt;The philosophy&lt;/h3&gt;
&lt;p&gt;&lt;span class='spip_document_52 spip_documents spip_documents_right' style='float:right; width:333px;'&gt;
&lt;a href=&quot;http://www.flickr.com/photos/denismessie/3462379864/&quot; class=&quot;spip_out&quot;&gt;&lt;img src='http://blog.rastageeks.org/local/cache-vignettes/L333xH500/3462379864_b046918611-e774d.jpg' width='333' height='500' alt=&quot;&quot; style='height:500px;width:333px;' /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;There is a constant complain from the open source communities about the use of patent-encumbered formats. In particular, those formats are not allowed in the &lt;a href='http://commons.wikimedia.org/wiki/Commons:File_types' class='spip_out' rel='external'&gt;Wikimedia commons&lt;/a&gt; and the corresponding encoders, in particular mp3 encoders, are &lt;a href='http://bugs.debian.org/436894' class='spip_out' rel='external'&gt;not supported&lt;/a&gt; by for instance the Debian distribution.&lt;/p&gt; &lt;p&gt;In a similar intent to push for a wider usage of patent-free codecs, the icecast project reimplemented its streaming server in order to use the ogg container and codecs.&lt;/p&gt; &lt;p&gt;All these actions are very important. In particular, the support for ogg/theora video files in firefox, and hopefully the major HTML 5 browser is mainly the result of wikipedia refusing other video formats. Indeed, wikipedia is now a major website, and it would be insane to not support the videos there.&lt;/p&gt; &lt;p&gt;However, I for myself do not like when these actions become too restrictive to the user. For this matter, I personally prefer freedom of choice among other considerations. Also, as a matter of fact, when trying to change the situation about these issues, one has to take into account the relative importance of each actor. It is because wikipedia is already huge that it has managed to change the things.&lt;/p&gt; &lt;p&gt;Hence, in the case of net-radios, a majority of potential users are asking for AAC+ and other patent-encumbered formats. Although this is not the ideal situation we would like to see, there comes a point were either the free-software projects have something to propose, or the users will just go for a proprietary software, which is even worse to the situation.&lt;/p&gt; &lt;p&gt;For this purpose, I believed it was important to add such support into our software. However, as you will see later, we do not implement ourself the encoding algorithm, but only added support for external encoders. That way, we simply let the user choose what he wants to use, but remain a patent-free and open-source software.&lt;/p&gt; &lt;h3 class=&quot;spip&quot;&gt;The implementation&lt;/h3&gt;
&lt;p&gt;Since mp3 was, and still is, the &lt;a href='http://dir.xiph.org/' class='spip_out' rel='external'&gt;major target&lt;/a&gt; for net-radios, icecast2 still has the possibility to stream this format. In fact, this format, as well as AAC+, does not have headers, such that it is possible to decode a stream at any point in it. Hence, in this case, icecast only acts as a proxy, and the only constraint is to send it the encoded data at real rate.&lt;/p&gt; &lt;p&gt;Hence, the main library for streaming to icecast, &lt;a href='http://svn.xiph.org/icecast/trunk/libshout' class='spip_out' rel='external'&gt;libshout&lt;/a&gt;, parses the audio data that it receives, and schedules the streaming according to real rate. Additionally, it also supports a raw mechanism, for which there would be not such mangling.&lt;/p&gt; &lt;p&gt;In the case of liquidsoap, we did not need this feature of the libshout since the software is already working in real time. Furthermore, the source connection protocol provides a content-type header field, which allows icecast to display the correct mime for the data format that is streamed.&lt;/p&gt; &lt;p&gt;All in all, in order to send AAC+ data to icecast, one needs to send the correct mime-type in the source connection headers, and then send audio data at the correct rate.&lt;/p&gt; &lt;p&gt;However, the libshout did not allow to set an arbitrary content-type header. Hence, I proposed a &lt;a href='http://www.nabble.com/-libshout--Add-mime-content-type-parameter-to19584905.html' class='spip_out' rel='external'&gt;patch&lt;/a&gt;. It was proposed for an inclusion into main code, since I believe it is interesting not only for our specific need, but also for any other generic data format support. Although the patch was accepted, it was never committed.&lt;/p&gt; &lt;p&gt;So, we decided to go on: since liquidsoap need not the real rate mangling feature of the libhsout, and since the source protocol is mainly a basic HTTP, we decided it was worth a custom implementation. This implementation was quite easy, thanks to the powerful capabilities of the OCaml language, and resulted in a custom implementation, &lt;a href='http://savonet.rastageeks.org/browser/trunk/ocaml-cry' class='spip_out' rel='external'&gt;ocaml-cry&lt;/a&gt;, that does the same as libshout, except that it does not control the rate of the data flow sent to the icecast server.&lt;/p&gt; &lt;p&gt;Then, we also needed to support encoding data to the AAC format. After looking at the only available open-source encoder, &lt;a href='http://teknoraver.net/software/mp4tools/' class='spip_out' rel='external'&gt;aacplusenc&lt;/a&gt;, I tried to propose some changes in order to export a library and be able to use it in liquidsoap. However, these propositions did not make it into upstream's code, so I decided to also move on and use directly the encoder binary.&lt;/p&gt; &lt;p&gt;Hence, using only the good old unix standard input/output mechanism, it is possible to start an encoder as a child process, send it the raw PCM data to its standard input and read the encoded data from its standard output. This lead to the development of the external output operators, which include &lt;code class='spip_code' dir='ltr'&gt;output.icecast.external&lt;/code&gt;.&lt;/p&gt; &lt;p&gt;Although this implementation was not easy, it now appears to work quite well in the current SVN version. In particular, the encoder process exits correctly for the FLAC encoder, which is needed in order to stream correctly, since the ogg container needs a restart for every track. Hence, we also gained support for encoding to the FLAC audio format, which was not binded for OCaml (yet ?) because its callback-driven API makes it tricky to do.&lt;/p&gt; &lt;p&gt;Additionally, the support for external processes as encoders allows to use the lame binary for encoding mp3 data. Hence, liquidsoap can now encode mp3 data without the need of a built-in support for it. And, as always, the idea of using external processes spread over several other operators, including the support for external file and stream decoders, enabling support for many audio format (in fact almost all supported in linux, using mplayer).&lt;/p&gt; &lt;p&gt;In conclusion, liquidsoap now has a fairly good support for AAC+ audio streaming, as well as a many new formats for decoding files and streams. It also support arbitrary formats and encoders using a custom variant of the &lt;code class='spip_code' dir='ltr'&gt;output.icecast.external&lt;/code&gt;. Hence, provided your format can be decoded from any point in the stream, you should be able to use liquidsoap to stream data to icecast as soon as you have a binary which is able to receive RAW or WAV PCM data to its standard input and send encoded data to its standard output.&lt;/p&gt; &lt;p&gt;As an illustration, here is an implementation of the &lt;code class='spip_code' dir='ltr'&gt;output.icecast.aacplusenc&lt;/code&gt;:&lt;/p&gt; &lt;div style='text-align: left;' class='spip_code' dir='ltr'&gt;&lt;code&gt;def output.icecast.aacplusenc(&lt;br /&gt; ~id=&quot;output.icecast.aacplusenc&quot;,&lt;br /&gt; ~start=true,&lt;br /&gt; ~restart=true,&lt;br /&gt; ~restart_delay=3,&lt;br /&gt; ~host=&quot;localhost&quot;,&lt;br /&gt; ~port=8000,&lt;br /&gt; ~user=&quot;source&quot;,&lt;br /&gt; ~password=&quot;hackme&quot;,&lt;br /&gt; ~genre=&quot;Misc&quot;,&lt;br /&gt; ~url=&quot;http://savonet.sf.net/&quot;,&lt;br /&gt; ~description=&quot;OCaml Radio!&quot;,&lt;br /&gt; ~public=true,&lt;br /&gt; ~dumpfile=&quot;&quot;,&lt;br /&gt; ~mount=&quot;Use [name]&quot;,&lt;br /&gt; ~name=&quot;Use [mount]&quot;,&lt;br /&gt; ~protocol=&quot;http&quot;,&lt;br /&gt; ~aacplusenc=&quot;aacplusenc&quot;,&lt;br /&gt; ~bitrate=64,&lt;br /&gt; ~restart_on_crash=false,&lt;br /&gt; ~restart_on_new_track=false,&lt;br /&gt; ~restart_encoder_delay=3600,&lt;br /&gt; ~headers=[],&lt;br /&gt; s)&lt;br /&gt; # Metadata update is set by ICY with icecast&lt;br /&gt; def aacplusenc_p(m)&lt;br /&gt; &quot;#{aacplusenc} - - #{bitrate}&quot;&lt;br /&gt; end&lt;br /&gt; output.icecast.external(id=id,&lt;br /&gt; process=aacplusenc_p,&lt;br /&gt; bitrate=bitrate,&lt;br /&gt; start=start,&lt;br /&gt; restart=restart,&lt;br /&gt; restart_delay=restart_delay,&lt;br /&gt; host=host,&lt;br /&gt; port=port,&lt;br /&gt; user=user,&lt;br /&gt; password=password,&lt;br /&gt; genre=genre,&lt;br /&gt; url=url,&lt;br /&gt; description=description,&lt;br /&gt; public=public,&lt;br /&gt; dumpfile=dumpfile,&lt;br /&gt; name=name,&lt;br /&gt; mount=mount,&lt;br /&gt; protocol=protocol,&lt;br /&gt; header=true,&lt;br /&gt; restart_on_crash=restart_on_crash,&lt;br /&gt; restart_on_new_track=restart_on_new_track,&lt;br /&gt; headers=headers,&lt;br /&gt; restart_encoder_delay=restart_encoder_delay,&lt;br /&gt; format=&quot;audio/aacp&quot;,&lt;br /&gt; s)&lt;br /&gt; end&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>



</channel>

</rss>
