<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Philippe Strauss website (Posts about Programming)</title><link>https://straussengineering.ch/</link><description></description><atom:link href="https://straussengineering.ch/categories/programming.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2025 &lt;a href="mailto:catseyechandra74 at gmail dot com"&gt;Philippe Strauss&lt;/a&gt; 
&lt;a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/4.0/"&gt;
&lt;img alt="Creative Commons License BY-NC-SA"
style="border-width:0; margin-bottom:12px;"
src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Thu, 11 Dec 2025 18:50:50 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>A 30 SLOC CLI native code sound file player</title><link>https://straussengineering.ch/posts/soundplayer-30-sloc.md/</link><dc:creator>Philippe Strauss</dc:creator><description>&lt;p&gt;Here is a short, approximatively 30 SLOC OCaml code to play a soundfile through Jack or Pipewire. I like tidy, simple, straight to the point code and languages, minimizing the number of SLOC to achieve a given task, but still compiled to native code with a serious, highly bug-screening compilation process. Ocaml ideally fits the bill here, but a garbage collector based language does not makes things easy regarding real-time constraints. We use &lt;code&gt;ocaml-bjack&lt;/code&gt;, which buffers sound I/O and we give half a second of buffering to shield us from the GC runtime.&lt;/p&gt;
&lt;p&gt;First lets open the soundfile using &lt;code&gt;ocaml-libsndfile&lt;/code&gt; and query the number of channels and samplerate of the file:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;soundfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="o"&gt;.(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Sndfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;openfile&lt;/span&gt; &lt;span class="n"&gt;soundfile&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;nchan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Sndfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;channels&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sfreq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Sndfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;samplerate&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="nn"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Opened sound file %s.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%!"&lt;/span&gt; &lt;span class="n"&gt;soundfile&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next we start our Jack client and indicate a one second depth buffer &lt;code&gt;(sfreq*nchan)&lt;/code&gt; for I/O of which we'll use half:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;    &lt;span class="nn"&gt;Bjack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_conversion_function&lt;/span&gt; &lt;span class="nn"&gt;Bjack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Best_quality&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bjk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Bjack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open_t&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sfreq&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;bits_per_sample&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;input_channels&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;output_channels&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;nchan&lt;/span&gt;
        &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;:[&lt;/span&gt; &lt;span class="nn"&gt;Bjack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Output&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;client_name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"sfplay"&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;ringbuffer_size&lt;/span&gt;&lt;span class="o"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;sfreq&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;nchan&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="nn"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Opened JACK audio device.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%!"&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now define a buffer for passing data from libsndfile to jack:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;buflen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="c"&gt;(* samples per channel *)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;inlen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buflen&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;nchan&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;interleaved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;inlen&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;More interestening, we receive data from &lt;code&gt;libsndfile&lt;/code&gt; in a normalized to ]-1.0; +1.0] stream of floating point values, while &lt;code&gt;ocaml-bjack&lt;/code&gt; accept samples in a stream of 16bit integers encoded in a string. The function &lt;code&gt;short_from_float&lt;/code&gt; takes a float, amplify it by 32768 and return a pair of values bounded by [0; 255], ready to be encoded as characters in a string. Next the function &lt;code&gt;paircat&lt;/code&gt; takes as input an Array of such pairs and build a string representing a flow of samples using a fold.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;short_from_float&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;inint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;int_of_float&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32768&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;*.&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inint&lt;/span&gt; &lt;span class="ow"&gt;land&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;upper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inint&lt;/span&gt; &lt;span class="ow"&gt;land&lt;/span&gt; &lt;span class="mh"&gt;0xff00&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;lsr&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;paircat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;cp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chr&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snd&lt;/span&gt; &lt;span class="n"&gt;cp&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chr&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fst&lt;/span&gt; &lt;span class="n"&gt;cp&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that the caret means string concatenation and &lt;code&gt;Char.chr&lt;/code&gt; return a character out of its integer index in the 8bit ASCII table, while fst and snd return the first and second in a pair, respectively.
We then define a pause time half the time to sink a &lt;code&gt;buflen&lt;/code&gt; buffer:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pausetime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;float_of_int&lt;/span&gt; &lt;span class="n"&gt;buflen&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/.&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;*.&lt;/span&gt; &lt;span class="n"&gt;float_of_int&lt;/span&gt; &lt;span class="n"&gt;sfreq&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We start the processing loop until an indication there is nothing more to read from the soundfile:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ref&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nn"&gt;Bjack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_bytes_stored&lt;/span&gt; &lt;span class="n"&gt;bjk&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;sfreq&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;nchan&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is the main processing of this program, we read the soundfile &lt;code&gt;buflen*nchan&lt;/code&gt; at a time, use &lt;code&gt;Array.map&lt;/code&gt; and &lt;code&gt;fold_left&lt;/code&gt; to convert our floats to a string, and write this string in the Jack ringbuffer:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;            &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nn"&gt;Sndfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt; &lt;span class="n"&gt;interleaved&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;short_from_float&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;interleaved&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;shorts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold_left&lt;/span&gt; &lt;span class="n"&gt;paircat&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
            &lt;span class="n"&gt;ignore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Bjack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="n"&gt;bjk&lt;/span&gt; &lt;span class="n"&gt;shorts&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When enough data is in the Jack ringbuffer, we simply idle doing nothing, for a time long enough to empty a bit over one &lt;code&gt;buflen*nchan&lt;/code&gt; in the Jack ringbuffer. Note that using map and fold here imply allocating and collecting arrays of memory inside the tight processing loop, this is not an ideal way of writing a soft real-time program. It can be seen by looking at the CPU usage, something suboptimal is going on (the reccuring, high frequency memory allocation of relatively large arrays). This is a short tutorial only, but shows that OCaml, even used far from its design goal (the Coq theorem prover implementation language) is still able to cope with basics multimedia requirements. It happens, computers history shows, that OCaml has ended as being a broad, expressive general purpose programming language.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;        &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nn"&gt;Unix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleepf&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.*.&lt;/span&gt;&lt;span class="n"&gt;pausetime&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nn"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Bjack.get_bytes_stored=%d&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="s2"&gt;%!"&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Bjack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_bytes_stored&lt;/span&gt; &lt;span class="n"&gt;bjk&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nn"&gt;Bjack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt; &lt;span class="n"&gt;bjk&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That's it, a little starter dish in OCaml with more than a "Hello world" or a fibonacci, for peoples having other simpler language as a background.&lt;/p&gt;</description><category>DSP</category><category>OCaml</category><category>Programming</category><guid>https://straussengineering.ch/posts/soundplayer-30-sloc.md/</guid><pubDate>Wed, 28 Aug 2024 13:14:57 GMT</pubDate></item><item><title>OCaml: the choice of discriminating hackers</title><link>https://straussengineering.ch/posts/why-ocaml/</link><dc:creator>Philippe Strauss</dc:creator><description>&lt;div&gt;&lt;p&gt;&lt;strong&gt;Discriminating:&lt;/strong&gt; in the first sense: 1a. Able to recognize or draw fine
distinctions; perceptive. 1b. Showing careful judgment or fine taste :-)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hacker:&lt;/strong&gt; computer programming enthusiast, not security breaking fanatic.&lt;/p&gt;
&lt;h3&gt;Why OCaml?&lt;/h3&gt;
&lt;p&gt;I became interested, intrigued by this langage a long while back, in
2000-2002, when seeing it score rank second or third, just behind C and
C++, on the computer language shootout hosted on alioth.debian.org. Never really invested a lot of
time learning it before 2007-2008. It's not the easiest language for
beginners, beeing a toolbox with a lot of tools, each having at least
one distinctive name and functionality on it. Most peoples tends to prefer simple things,
especially when it come to programming, where the overall picture, the
frameworks, libraries, OS surrounding your development can quickly grow
in becoming a big beast to harness.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://straussengineering.ch/posts/why-ocaml/"&gt;Read more…&lt;/a&gt; (3 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>OCaml</category><category>Programming</category><guid>https://straussengineering.ch/posts/why-ocaml/</guid><pubDate>Sat, 31 Dec 2011 23:00:00 GMT</pubDate></item><item><title>Pure javascript HTML5 canvas bilinear image interpolation</title><link>https://straussengineering.ch/posts/javascript-bilinear-image-interpolation/</link><dc:creator>Philippe Strauss</dc:creator><description>&lt;div&gt;&lt;p&gt;I've finally got my finger on a motivating javascript tryout. Never
went deep into web programming before, this is the first full day of my
life spent on JS. I wanted to test the feasibility (in term of
computation time spent by the browser) of good quality image
interpolation solely on the client side, in javascript. Even on a mac
air 1.4GHz, it turns out to be a perfectly viable solution.&lt;/p&gt;
&lt;p&gt;Googling to find some existing code, I didn't find any valuable. So
here is one, it's working for me, not just a half baked solution
computing only one pixel in the image and approximatively. The following
HTML+JS is self contained and works fine, at least on my setup.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://straussengineering.ch/posts/javascript-bilinear-image-interpolation/"&gt;Read more…&lt;/a&gt; (6 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>DSP</category><category>Javascript</category><category>Programming</category><guid>https://straussengineering.ch/posts/javascript-bilinear-image-interpolation/</guid><pubDate>Sat, 31 Dec 2011 23:00:00 GMT</pubDate></item><item><title>Zölzer-Boltze (ZB) peak/notch parametric EQ in C</title><link>https://straussengineering.ch/posts/zb-peaknotch-parametric-eq/</link><dc:creator>Philippe Strauss</dc:creator><description>&lt;div&gt;&lt;h3&gt;For digital audio signal processing&lt;/h3&gt;
&lt;p&gt;I was looking for a good implementation of parametric EQ for digital
audio, didn't find something valuable enough, so I needed to roll my
own. I retained a paper by two german guys, Mrs. Zölzer and Boltze, and
implemented it.&lt;/p&gt;
&lt;p&gt;It has the best parameters independance of all the one I browsed
through. Well, center frequency, Q factor and cut/boost gain are simply
&lt;em&gt;really&lt;/em&gt; independant in their work, contrary to a lot of such projects
you will find while googling around.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://straussengineering.ch/posts/zb-peaknotch-parametric-eq/"&gt;Read more…&lt;/a&gt; (6 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>ANSI C</category><category>Audio</category><category>Digital filters</category><category>DSP</category><category>Programming</category><guid>https://straussengineering.ch/posts/zb-peaknotch-parametric-eq/</guid><pubDate>Sun, 14 Aug 2011 22:00:00 GMT</pubDate></item><item><title>FIR filter design experiment using the simplex method</title><link>https://straussengineering.ch/posts/fir-filter-design-experiment/</link><dc:creator>Philippe Strauss</dc:creator><description>&lt;div&gt;&lt;p&gt;A starter about symetrical (linear phase) finite impulse response
digital filter design using the simplex method. Much slower than
Parks/McClellan/Remez exchange, but packaged in GLPK. 75 lines of OCaml
code to design an FIR filter, what less could you ask for ?&lt;/p&gt;
&lt;p&gt;The paper to have in hands is the "Meteor" one by Steiglitz. In short,
from a vector dot matrix multiplication, we get the frequency response.
The matrix beeing a cosine table, the vector beeing the filter
coefficients.&lt;/p&gt;
&lt;p&gt;The simplex method beeing a relatively simple optimization procedure for
linear problems.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://straussengineering.ch/posts/fir-filter-design-experiment/"&gt;Read more…&lt;/a&gt; (3 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>Digital filters</category><category>DSP</category><category>OCaml</category><category>Programming</category><guid>https://straussengineering.ch/posts/fir-filter-design-experiment/</guid><pubDate>Tue, 31 Aug 2010 23:00:00 GMT</pubDate></item><item><title>Backing up and archiving Cisco IOS/ASA configurations live from the router without TFTP</title><link>https://straussengineering.ch/posts/cisco-configs-archiving/</link><dc:creator>Philippe Strauss</dc:creator><description>&lt;div&gt;&lt;h3&gt;In Python and with Subversion archiving&lt;/h3&gt;
&lt;p&gt;At some point as a network admin, I did find easier to parse config file
using python expect and some regexp, rather than relying on the
unreliable TFTP. Here's a script which worked fine for one year or so.
It also does automate archiving in subversion. It's delibaretly in a
shape suitable for a blog page, working after tuning two paths in the
first script, but without a tarball and 12 pages of doco. Python is
simple enough to read and understand even for peoples having never
learned this language.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://straussengineering.ch/posts/cisco-configs-archiving/"&gt;Read more…&lt;/a&gt; (5 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>Cisco</category><category>Internet networking</category><category>Programming</category><category>Python</category><guid>https://straussengineering.ch/posts/cisco-configs-archiving/</guid><pubDate>Sat, 31 May 2008 23:00:00 GMT</pubDate></item></channel></rss>