I am doing a review of Vicare’s extensions implementing interfaces to foreign libraries. Having formally abandoned Sourceforge and Gitorious, the code is on Github and Bitbucket. Yes, I am procrastinating the expander’s code review I have started.
For some time Vicare’s package has included an interface to the C language library CRE2, which in turn is a C wrapper for the C++ language library re2. re2 was originally hosted at Google Code, but it is now hosted at Github.
The purpose of including this interface in the main Vicare Scheme package was twofold: to include a fast regular expressions engine; to test the viability of inclusion of foreign library interfaces in the main package:
(vicare
irregexp)
, (vicare pregexp)
, posix regular expressions in the library
(vicare glibc)
); I rarely use them, so I do not really feel the need to have
another engine there.
So, I have extracted the interface to CRE2 from the main package and it has now its own package. There is nothing new about it; the api has not changed.
This is a new package interfacing Libao: a cross–platform
audio library that allows programs to output audio using a simple api on a wide
variety of platforms (this description is straight from their web site). I doubt it
can be used for serious stuff, but, anyway, it can be used to play sounds
programmatically generated by direct computation of the waveform; it can also
generate wav
files.
Here is an example playing a chunk of Black Sabbath’s “Iron Man” song:
(import (vicare) (prefix (vicare multimedia ao) ao.) (prefix (vicare multimedia ao constants) ao.) (vicare numerics constants)) (ao.ao-initialise) (define-constant A4 440.00) (define-constant B4 493.88) (define-constant C5 523.25) (define-constant D5 587.33) (define-constant E5 659.25) (define-constant F5 698.46) (define-constant Fs5 739.995) (define-constant G5 783.99) (define-constant A5 880.00) (define-constant B5 987.77) (define-constant C6 1046.50) (define sample-format (let ((bits 16) ;how many bits per sample (rate 44100) ;how many samples per second (channels 2) (byte-format ao.AO_FMT_LITTLE) (matrix "L,R")) (ao.make-ao-sample-format bits rate channels byte-format matrix))) (define device (let ((driver-options #f)) (ao.ao-open-live (ao.ao-default-driver-id) sample-format driver-options))) (define (make-melody frm melody) ;;Build and return a samples bytevector, filled with a sinusoidal waveform. ;; (define number-of-ticks-per-second (infix inexact(ao.ao-sample-format-rate(frm)))) (define number-of-ticks-per-millisecond (infix number-of-ticks-per-second / 1000.0)) (define ticks* (map (lambda (note) (let ((msecs (cdr note))) (infix exact(floor(msecs * number-of-ticks-per-millisecond))))) melody)) (define samples.len (let ((total-number-of-ticks (fold-left + 0 ticks*))) (infix ao.ao-sample-format-bits(frm) / 8 * ao.ao-sample-format-channels(frm) * total-number-of-ticks))) (receive-and-return (samples.bv) (make-bytevector samples.len) (fold-left (lambda (i.start note ticks) (let ((freq (car note)) (msecs (cdr note))) (receive-and-return (i.end) (+ i.start ticks) (fill-tone! samples.bv i.start i.end freq number-of-ticks-per-second)))) 0 melody ticks*))) (define (fill-tone! samples.bv i.start i.end freq number-of-ticks-per-second) ;;FREQ must be the tone frequency in Hertz. ;; (define A (infix 0.75 * 32768.0)) (define omega (infix 2 * greek-pi * freq)) (define sample-max (exact (floor (* A 0.20)))) (define sample-min (- sample-max)) (do ((i i.start (fxadd1 i))) ((fx>=? i i.end)) (let* ((time (infix inexact(i / number-of-ticks-per-second))) (sample (exact (floor (infix A * sin(omega * time))))) (j (infix 4 * i))) ;;Put the same stuff in left and right channels. The bytevector is an array ;;of 32-bit slots, each with format: ;; ;; channel 1 LSB channel 2 LSB channel 1 MSB channel 2 MSB ;; |-------------|-------------|-------------|-------------| ;; ;;where LSB stands for Least Significant Byte and MSB stands for Most ;;Significant Byte. ;; (let ((sample.lsb (infix #xFF & sample))) (bytevector-u8-set! samples.bv j sample.lsb) (bytevector-u8-set! samples.bv (+ j 2) sample.lsb)) (let ((sample.msb (infix #xFF & (sample >> 8)))) (bytevector-u8-set! samples.bv (+ j 1) sample.msb) (bytevector-u8-set! samples.bv (+ j 3) sample.msb))))) (define iron-man (let ((T 1500) (pause '(0 . 100)) (pause/2 '(0 . 50))) (make-melody sample-format `((,B4 . ,(* T 1/4)) ,pause (,D5 . ,(* T 1/4)) ,pause (,D5 . ,(* T 1/8)) ,pause (,E5 . ,(* T 1/8)) ,pause (,E5 . ,(* T 1/4)) ,pause (,G5 . ,(* T 1/16)) ,pause/2 (,Fs5 . ,(* T 1/16)) ,pause/2 (,G5 . ,(* T 1/16)) ,pause/2 (,Fs5 . ,(* T 1/16)) ,pause/2 (,G5 . ,(* T 1/16)) ,pause/2 (,Fs5 . ,(* T 1/16)) ,pause/2 (,D5 . ,(* T 1/8)) ,pause (,D5 . ,(* T 1/8)) ,pause (,E5 . ,(* T 1/8)) ,pause (,E5 . ,(* T 1/4)) )))) (ao.ao-play device iron-man) (ao.ao-close device)
Libao’s documentation is very dry. In future I should dig in the code and document what is the expected format of audio samples, it is not really clear to me.
I have revamped the interface to
SQLite, the database engine. The master
branch
has a tag begin-support-for-vicare-scheme-0.4
after which Vicare Scheme
version 0.4
must be used. I did a review of the code. The current head of
Vicare/SQLite’s master
branch should work with the current head of Vicare
Scheme’s master
branch.
The current scenario is that: there is a tight dependence between the boot image and compiled libraries. First we have to compile the boot image, then we have to hierarchically compile the libraries. If we recompile a library: we have to recompile all the libraries that depend on it. If we recompile the boot image: we have to recompile everything. I hate this.
This was less a problem before, when the scenario was: we install source libraries and automatically compile them in the fasl files cache.
I want to do something about it, so that the scenario is more like the shared objects’s hell of C language libraries. “Doing something” means to implement tables of storage location gensyms referencing exported syntactic bindings.