SMOLNET PORTAL home about changes
;;;;This file is a simple port of the libsndfile regaining example.
;;;;ie sfprocess.c
(defpackage warm (:export transform *left* *right*) )
;;;;BUFFER_LEN = 8192
;;;;CHANNELS = 2
;;;;So the transforms each act upon an 4096 length list.

(in-package warm)

(defvar *left* (list))
(defvar *right* (list))

(defvar *left-transformation* (lambda (list) (nreverse list)))
(defvar *right-transformation* (lambda (list) (nreverse list)))

;;;These middleman callbacks aren't actually so slow.
(defvar pusher* 
 (ffi:defcallback push-channels nil ((left :float) (right :float))
                 (push left *left*)
                 (push right *right*)))
(defvar popleft* (ffi:defcallback pop-left :float () (pop *left*)))
(defvar popright* (ffi:defcallback pop-right :float () (pop *right*)))
(defvar transformer* (ffi:defcallback transformer nil ()
                      (setf *left* (funcall *left-transformation* *left*)
                           *right* (funcall *right-transformation* *right*))))


;;;headers
(ffi:clines "
#include        <stdio.h>
#include        <string.h>

#include        <sndfile.h>

#define         BUFFER_LEN      8192
#define         MAX_CHANNELS    2

")

(defun transformin (infilename outfilename) "
Internal use: Applies the above lambdas.
"
 (ffi:with-cstrings ((cinfilename infilename) (coutfilename outfilename))
  (ffi:c-inline (cinfilename coutfilename pusher* transformer* 
		 popleft* popright*) 
               (:cstring :cstring :pointer-void :pointer-void :pointer-void 
                :pointer-void) :int "
//callbacks
//        float (* right)(float) = (float (*)(float))#3;
void
(* pusher)(float, float) = (void (*)(float, float))#2;
void
(* transformer)() = (void (*)())#3;
float
(* popleft)() = (float (*)())#4;
float
(* popright)() = (float (*)())#5;

///callbacks
static float data[BUFFER_LEN];

SNDFILE *infile, *outfile;

SF_INFO         sfinfo;
int             readcount;
const char      *infilename = #0;
const char      *outfilename = #1;

memset(&sfinfo, 0, sizeof(sfinfo));

if (! (infile = sf_open(infilename, SFM_READ, &sfinfo))) {
        printf(\"Not able to open input file %s.\\n\", infilename);
        puts(sf_strerror(NULL));
        @(return)=1;
}

if (sfinfo.channels > MAX_CHANNELS) {
        printf(\"Too many channels\\n\");
        @(return)=1;
}

if (! (outfile = sf_open(outfilename, SFM_WRITE, &sfinfo))) {
        printf(\"Not able to open output file %s.\\n\", outfilename);
        puts(sf_strerror(NULL));
        @(return)=1;
}

int i;
while ((readcount = sf_read_float(infile, data, BUFFER_LEN))) {
        //Send both channels to lisp-land
        for (i=0;i<readcount/2;i++) pusher(data[2*i],data[2*i+1]);
        //transform
        transformer();
        //receive each channel back, store in data
        for (i=0;i<readcount/2;i++) {
            data[2*i]=popleft();
            data[2*i+1]=popright();
        }
        //Write to outfile
        sf_write_float(outfile, data, readcount);
}

sf_close (infile) ;
sf_close (outfile) ;

@(return)=0;
")))

(defun transform (inpath outpath left-lambda right-lambda) "
(defun transform (inpath outpath left-lambda right-lambda) )
paths are strings
lambdas are like (lambda (list) (values list))
The list was made by pushing, so it's backwards.
Applied on each stride, hardcoded l 8192 : 
4096 elements in each list,
or less in the last list.
Otherwise your function can be arbitrary.
*left* *right* lists are also exported,
if you must.
"
 (setf *left-transformation* left-lambda
      *right-transformation* right-lambda)
 (transformin inpath outpath))

#|
(transform "test/glorafilia.wav" "test/foop.wav"
            *left-transformation* *right-transformation*)
(ext:quit)
|#
Response: text/plain
Original URLgopher://sdf.org/0/users/screwtape/matched-filter-lisp/wa...
Content-Typetext/plain; charset=utf-8