;;;;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