Header imageSkip to main content

A 30 SLOC CLI native code sound file player

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 ocaml-bjack, which buffers sound I/O and we give half a second of buffering to shield us from the GC runtime.

First lets open the soundfile using ocaml-libsndfile and query the number of channels and samplerate of the file:

let () =
    let soundfile = Sys.argv.(1) in
    let sf = Sndfile.openfile soundfile in
    let nchan = Sndfile.channels sf in
    let sfreq = Sndfile.samplerate sf in
    Printf.printf "Opened sound file %s.\n%!" soundfile ;

Next we start our Jack client and indicate a one second depth buffer (sfreq*nchan) for I/O of which we'll use half:

    Bjack.set_conversion_function Bjack.Best_quality ;
    let bjk = Bjack.open_t ~rate:sfreq ~bits_per_sample:16 ~input_channels:0 ~output_channels:nchan
        ~flags:[ Bjack.Output ] ~client_name:"sfplay" ~ringbuffer_size:(sfreq*nchan) () in
    Printf.printf "Opened JACK audio device.\n%!" ;

Now define a buffer for passing data from libsndfile to jack:

    let buflen = 1024 in (* samples per channel *)
    let inlen = buflen * nchan in
    let interleaved = Array.make inlen 0. in

More interestening, we receive data from libsndfile in a normalized to ]-1.0; +1.0] stream of floating point values, while ocaml-bjack accept samples in a stream of 16bit integers encoded in a string. The function short_from_float 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 paircat takes as input an Array of such pairs and build a string representing a flow of samples using a fold.

    let short_from_float input =
        let inint = int_of_float (32768. *. input) in
        let lower = inint land 0xff in
        let upper = (inint land 0xff00) lsr 8 in
        (upper, lower) in
    let paircat s cp =
        s ^ String.make 1 (Char.chr (snd cp)) ^ String.make 1 (Char.chr (fst cp)) in

Note that the caret means string concatenation and Char.chr 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 buflen buffer:

    let pausetime = (float_of_int buflen) /. (2. *. float_of_int sfreq) in

We start the processing loop until an indication there is nothing more to read from the soundfile:

    let read = ref 1 in
    while !read > 0 do
        if Bjack.get_bytes_stored bjk < sfreq*nchan/2 then (

Here is the main processing of this program, we read the soundfile buflen*nchan at a time, use Array.map and fold_left to convert our floats to a string, and write this string in the Jack ringbuffer:

            read := Sndfile.read sf interleaved ;
            let pairs = Array.map (fun x -> short_from_float x) interleaved in
            let shorts = Array.fold_left paircat "" pairs in
            ignore(Bjack.write bjk shorts)

When enough data is in the Jack ringbuffer, we simply idle doing nothing, for a time long enough to empty a bit over one buflen*nchan 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.

        ) else Unix.sleepf (3.*.pausetime) ;
        Printf.printf "Bjack.get_bytes_stored=%d\r%!" (Bjack.get_bytes_stored bjk)
    done ;
    Bjack.close bjk

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.

Bookmarks destocking (in frenglish)

Read more…

Crash course en (macro)économie

Voici un échange d'emails avec un amis informaticien (Daniel) ayant travaillé 18 ans dans le monde de la finance (en suisse). Il n'est pas économiste, simplement qqun cherchant à comprendre comment fonctionne l'économie et la finance. Ses opinions sont les siennes, que le rédacteur (Philippe) de ce site partage pour la plupart, ce en étant un béotien complet sur ces sujets.

Philippe: Ne serions-nous pas à nouveau dans une bulle spéculative avec twitter valant 44 milliards et VMware 61 milliards (de US$)?

Read more…

OCaml: the choice of discriminating hackers

Discriminating: in the first sense: 1a. Able to recognize or draw fine distinctions; perceptive. 1b. Showing careful judgment or fine taste :-)

Hacker: computer programming enthusiast, not security breaking fanatic.

Why OCaml?

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.

Read more…

Pure javascript HTML5 canvas bilinear image interpolation

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.

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.

Read more…

Zölzer-Boltze (ZB) peak/notch parametric EQ in C

For digital audio signal processing

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.

It has the best parameters independance of all the one I browsed through. Well, center frequency, Q factor and cut/boost gain are simply really independant in their work, contrary to a lot of such projects you will find while googling around.

Read more…

Une première approche de rationalisation concernant l'harmonie musicale

Qu'est ce qui caractérise, de manière objective, quantifiable, un accord de deux sons, deux notes, tantôt dissonantes, tantôt consonantes ? On connait la nature vibratoire du son, soit une variation rapide de la pression atmosphérique, généralement de petite amplitude. Qu'elle sont les grandeurs physiques en jeux par rapport à l'harmonie, aussi notion apparament subjective si l'en est ?

Read more…

FIR filter design experiment using the simplex method

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 ?

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.

The simplex method beeing a relatively simple optimization procedure for linear problems.

Read more…

Backing up and archiving Cisco IOS/ASA configurations live from the router without TFTP

In Python and with Subversion archiving

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.

Read more…

L'informatique et l'éducation

L'informatique, science du traitement de l'information, est un domaine jeune, semblant traverser une crise de croissance, une fuite en avant permanente depuis qu'elle existe, ou en tout cas depuis qu'elle se trouve sur le bureau de beaucoup d'entre nous.

Pourtant, lorsqu'on s'intéresse de très près à ce domaine, qu'on passe petit-à-petit du stade d'utilisateur d'applicatifs à celui d'administrateur système et/ou a celui de programmeur, on est mis en face d'un historique de l'informatique, dans le sens ou les outils de bases qui permettent de construire dans ce domaine immatériel, que ce soit les langages de programmations ou les systèmes d'exploitations, n'ont conceptuellement pas changé depuis 30 ans. Le langage C, le plus utilisé pour construire les systèmes et applicatifs que nous rencontrons quotidiennement, existe depuis le début des années 70, comme les systèmes UNIX et VMS, base des systèmes Linux et Windows NT. Ceci contraste avec le foisonnement d'avancées techniques clamées a grand renfort de publicité par les ténors industriels de l'informatique.

Pourquoi un domaine basé sur des concepts de logiques si solides, si épurés, si aisés a systématiser, se présente-t-il devant nous sous forme de systèmes aussi instables, presque vivants tant la liste de 'bugs' interagissant avec le fonctionnement attendu est longue et non maîtrisée?

C'est à force de me poser ces questions, qu'à titre personnel, j'ai voulu découvrir autre chose que DOS, Windows et Apple avec son MacOS. J'ai installé Linux, de rage, après que Windows ait réduit à néant quelques jours de travail en plantant, et corrompant un travail pratique de physique que je rédigeais sous word.

Linux

La découverte d'un tel système n'était pas aisée à l'époque (1994) et accessible aux seuls passionnés d'informatique. Ce qui attire la plupart des futurs adeptes de linux vers linux, c'est l'ouverture totale est bien concrète du système, à tous les niveaux (la grande majorité de ses applicatifs est disponible avec le code source). Beaucoup de sociétés revendiquent l'ouverture de leurs solutions logicielles, mais celle-ci est généralement très partielle, l'idée de livrer le code source d'un tel produit étant difficilement conciliable avec le fait de capitaliser dans son développement.

Quand bien même est-ce le cas, on butte sur une fermeture "en-dessous" au niveau du système d'exploitation, qui, à l'exception des systèmes d'exploitations libres (Linux, BSD) ne permettent pas un traçage détaillé de ce qu'ils font lorsque un applicatif les charge d'une tache, ou ne l'autorisent qu'après l'achat d'un kit de développement coûtant plusieurs milliers de francs par poste de travail.

Mais est-ce bien utile de bénéficier d'une ouverture jusqu'au code source dans notre cas? Pour l'utilisation de l'informatique dans les spécialisations techniques des écoles professionnelles, de techniciens, d'ingénieurs et universitaires, OUI sans aucun doute. Pour les classes de scolarité obligatoire, c'est assez clairement inutile a l'utilisateur.

Par contre, le fait de ne pas montrer une seule culture informatique, celle des géants tel que Microsoft et Apple, à des enfants, leur expliquer que l'informatique, ce monde de l'immatériel, du "virtuel", connaît comme le monde réel une diversité culturelle, c'est fondamental. Se cantonner à montrer une seule de ces cultures aurait des effets très normatifs.

En effet, l'ouverture totale de l'informatique libre ne se limite pas à être avantageuse pour le développeur, elle crée une culture informatique dans les mains du publique, sans employeur au-dessus d'eux qui pourrait limiter leur franc parler, une culture du partage de l'information, discutant de problèmes informatiques sur des forums, mélangeant simples utilisateurs et programmeurs chevronnés, une culture foisonnante, encadrée par très peu de règles, si ce n'est celles des besoins des utilisateurs et du bon vouloir de programmeurs amateurs ou professionnels de créer des logiciels libres.

Contrairement au cas des logiciels propriétaires, il circule en effet autour des logiciels libres, une information très saine, détaillée et précise, sans retenue, au sujet du dernier bug, du dernier problème d'utilisation rencontré. Cet état de fait est en accord avec l'esprit dans lequel est développé le logiciel. En effet, en livrant le code source à l'utilisateur, on abandonne l'idée de cacher ses éventuelles erreurs ou maladresses de programmations, il devient inutile d'essayer de cacher ou d'altérer l'information quand à la réalité lorsque un défaut (bug) est constaté par un utilisateur.

Cette manière de faire circuler l'information a l'avantage de structurer l'esprit face à la technologie, de devenir critique face à celle-ci, qualité ô combien indispensable désormais.

La plupart des sociétés de technologies devenues des noms de marques, exploitent de manière abusive le manque d'esprit critique de la majorité d'entre nous face à la technologie. Faisons en sorte que le fossé entre les gens bardés d'informations techniques abstraites et le commun des mortels ne continuent pas a s'étendre. Par l'ouverture des logiciels libres, par une présence même discrète a l'école, juste suffisante pour faire comprendre qu'il n'y a pas un standard en informatique, mais une diversité laissant de nombreux choix possibles, on peut faire avancer les choses dans cette direction.