Skip to content

Instantly share code, notes, and snippets.

@standarddeviant
Last active November 5, 2019 12:44
Show Gist options
  • Save standarddeviant/28f9a49322265097fdbd92b5754fb04d to your computer and use it in GitHub Desktop.
Save standarddeviant/28f9a49322265097fdbd92b5754fb04d to your computer and use it in GitHub Desktop.
Soundpipe ex_biquad only, embedded exercise
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifndef NO_LIBSNDFILE
#include <sndfile.h>
#endif
#include "soundpipe.h"
int sp_create(sp_data **spp)
{
*spp = (sp_data *) malloc(sizeof(sp_data));
sp_data *sp = *spp;
sprintf(sp->filename, "test.wav");
sp->nchan = 1;
SPFLOAT *out = malloc(sizeof(SPFLOAT) * sp->nchan);
*out = 0;
sp->out = out;
sp->sr = 44100;
sp->len = 5 * sp->sr;
sp->pos = 0;
sp->rand = 0;
return 0;
}
int sp_createn(sp_data **spp, int nchan)
{
*spp = (sp_data *) malloc(sizeof(sp_data));
sp_data *sp = *spp;
sprintf(sp->filename, "test.wav");
sp->nchan = nchan;
SPFLOAT *out = malloc(sizeof(SPFLOAT) * sp->nchan);
*out = 0;
sp->out = out;
sp->sr = 44100;
sp->len = 5 * sp->sr;
sp->pos = 0;
sp->rand = 0;
return 0;
}
int sp_destroy(sp_data **spp)
{
sp_data *sp = *spp;
free(sp->out);
free(*spp);
return 0;
}
#ifndef NO_LIBSNDFILE
int sp_process(sp_data *sp, void *ud, void (*callback)(sp_data *, void *))
{
SNDFILE *sf[sp->nchan];
char tmp[140];
SF_INFO info;
memset(&info, 0, sizeof(SF_INFO));
SPFLOAT buf[sp->nchan][SP_BUFSIZE];
info.samplerate = sp->sr;
info.channels = 1;
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
int numsamps, i, chan;
if(sp->nchan == 1) {
sf[0] = sf_open(sp->filename, SFM_WRITE, &info);
} else {
for(chan = 0; chan < sp->nchan; chan++) {
sprintf(tmp, "%02d_%s", chan, sp->filename);
sf[chan] = sf_open(tmp, SFM_WRITE, &info);
}
}
while(sp->len > 0){
if(sp->len < SP_BUFSIZE) {
numsamps = sp->len;
}else{
numsamps = SP_BUFSIZE;
}
for(i = 0; i < numsamps; i++){
callback(sp, ud);
for(chan = 0; chan < sp->nchan; chan++) {
buf[chan][i] = sp->out[chan];
}
sp->pos++;
}
for(chan = 0; chan < sp->nchan; chan++) {
#ifdef USE_DOUBLE
sf_write_double(sf[chan], buf[chan], numsamps);
#else
sf_write_float(sf[chan], buf[chan], numsamps);
#endif
}
sp->len -= numsamps;
}
for(i = 0; i < sp->nchan; i++) {
sf_close(sf[i]);
}
return 0;
}
#endif
int sp_process_raw(sp_data *sp, void *ud, void (*callback)(sp_data *, void *))
{
int chan;
if(sp->len == 0) {
while(1) {
callback(sp, ud);
for (chan = 0; chan < sp->nchan; chan++) {
fwrite(&sp->out[chan], sizeof(SPFLOAT), 1, stdout);
}
sp->len--;
}
} else {
while(sp->len > 0) {
callback(sp, ud);
for (chan = 0; chan < sp->nchan; chan++) {
fwrite(&sp->out[chan], sizeof(SPFLOAT), 1, stdout);
}
sp->len--;
sp->pos++;
}
}
return SP_OK;
}
int sp_process_plot(sp_data *sp, void *ud, void (*callback)(sp_data *, void *))
{
int chan;
fprintf(stdout, "sp_out = [ ... \n");
while(sp->len > 0) {
callback(sp, ud);
for (chan = 0; chan < sp->nchan; chan++) {
/* fwrite(&sp->out[chan], sizeof(SPFLOAT), 1, stdout); */
fprintf(stdout, "%g ", sp->out[chan]);
}
fprintf(stdout, "; ...\n");
sp->len--;
sp->pos++;
}
fprintf(stdout, "];\n");
fprintf(stdout, "plot(sp_out);\n");
fprintf(stdout, "title('Plot generated by Soundpipe');\n");
fprintf(stdout, "xlabel('Time (samples)');\n");
fprintf(stdout, "ylabel('Amplitude');\n");
return SP_OK;
}
int sp_auxdata_alloc(sp_auxdata *aux, size_t size)
{
aux->ptr = malloc(size);
aux->size = size;
memset(aux->ptr, 0, size);
return SP_OK;
}
int sp_auxdata_free(sp_auxdata *aux)
{
free(aux->ptr);
return SP_OK;
}
SPFLOAT sp_midi2cps(SPFLOAT nn)
{
return pow(2, (nn - 69.0) / 12.0) * 440.0;
}
int sp_set(sp_param *p, SPFLOAT val) {
p->state = 1;
p->val = val;
return SP_OK;
}
int sp_out(sp_data *sp, uint32_t chan, SPFLOAT val)
{
if(chan > sp->nchan - 1) {
fprintf(stderr, "sp_out: Invalid channel\n");
return SP_NOT_OK;
}
sp->out[chan] = val;
return SP_OK;
}
uint32_t sp_rand(sp_data *sp)
{
uint32_t val = (1103515245 * sp->rand + 12345) % SP_RANDMAX;
sp->rand = val;
return val;
}
void sp_srand(sp_data *sp, uint32_t val)
{
sp->rand = val;
}
/*
* Biquad
*
* This code has been extracted from the Csound opcode "biquad".
* It has been modified to work as a Soundpipe module.
*
* Original Author(s): Hans Mikelson
* Year: 1998
* Location: Opcodes/biquad.c
*
*/
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include "soundpipe.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
int sp_biquad_create(sp_biquad **p)
{
*p = malloc(sizeof(sp_biquad));
return SP_OK;
}
int sp_biquad_destroy(sp_biquad **p)
{
free(*p);
return SP_OK;
}
int sp_biquad_init(sp_data *sp, sp_biquad *p)
{
p->tpidsr = 2.0*M_PI / sp->sr;
p->sr = sp->sr;
p->cutoff = 500;
p->res = 0.7;
p->reinit = 0.0;
SPFLOAT fcon = p->cutoff * p->tpidsr;
SPFLOAT alpha = 1-2*p->res*cos(fcon)*cos(fcon)+p->res*p->res*cos(2*fcon);
SPFLOAT beta = p->res*p->res*sin(2*fcon)-2*p->res*cos(fcon)*sin(fcon);
SPFLOAT gamma = 1+cos(fcon);
SPFLOAT m1 = alpha*gamma+beta*sin(fcon);
SPFLOAT m2 = alpha*gamma-beta*sin(fcon);
SPFLOAT den = sqrt(m1*m1+m2*m2);
p->b0 = 1.5*(alpha*alpha+beta*beta)/den;
p->b1 = p->b0;
p->b2 = 0.0;
p->a0 = 1.0;
p->a1 = -2.0*p->res*cos(fcon);
p->a2 = p->res*p->res;
if(p->reinit == 0.0){
p->xnm1 = p->xnm2 = p->ynm1 = p->ynm2 = 0.0;
}
return SP_OK;
}
int sp_biquad_compute(sp_data *sp, sp_biquad *p, SPFLOAT *in, SPFLOAT *out)
{
SPFLOAT xn, yn;
SPFLOAT a0 = p->a0, a1 = p->a1, a2 = p->a2;
SPFLOAT b0 = p->b0, b1 = p->b1, b2 = p->b2;
SPFLOAT xnm1 = p->xnm1, xnm2 = p->xnm2, ynm1 = p->ynm1, ynm2 = p->ynm2;
xn = *in;
yn = ( b0 * xn + b1 * xnm1 + b2 * xnm2 -
a1 * ynm1 - a2 * ynm2) / a0;
xnm2 = xnm1;
xnm1 = xn;
ynm2 = ynm1;
ynm1 = yn;
*out = yn;
p->xnm1 = xnm1; p->xnm2 = xnm2; p->ynm1 = ynm1; p->ynm2 = ynm2;
return SP_OK;
}
typedef struct{
SPFLOAT b0, b1, b2, a0, a1, a2, reinit, xnm1, xnm2, ynm1, ynm2, cutoff, res;
SPFLOAT sr;
SPFLOAT tpidsr;
}sp_biquad;
int sp_biquad_create(sp_biquad **p);
int sp_biquad_destroy(sp_biquad **p);
int sp_biquad_init(sp_data *sp, sp_biquad *p);
int sp_biquad_compute(sp_data *sp, sp_biquad *p, SPFLOAT *in, SPFLOAT *out);
gcc base.c biquad.c noise.c ex_biquad.c -D NO_LIBSNDFILE -lm
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "soundpipe.h"
typedef struct {
sp_noise *ns;
sp_biquad *tn;
} UserData;
void write_noise(sp_data *sp, void *udata) {
UserData *ud = udata;
SPFLOAT in = 0;
SPFLOAT out = 0;
sp_noise_compute(sp, ud->ns, NULL, &in);
sp_biquad_compute(sp, ud->tn, &in, &sp->out[0]);
}
int main() {
srand(time(NULL));
UserData ud;
sp_data *sp;
sp_create(&sp);
sp_noise_create(&ud.ns);
sp_biquad_create(&ud.tn);
sp_noise_init(sp, ud.ns);
sp_biquad_init(sp, ud.tn);
sp->len = 44100 * 5;
sp_process_raw(sp, &ud, write_noise);
sp_noise_destroy(&ud.ns);
sp_biquad_destroy(&ud.tn);
sp_destroy(&sp);
return 0;
}
#include <math.h>
#include <stdlib.h>
#include "soundpipe.h"
int sp_noise_create(sp_noise **ns)
{
*ns = malloc(sizeof(sp_noise));
return SP_OK;
}
int sp_noise_init(sp_data *sp, sp_noise *ns)
{
ns->amp = 1.0;
return SP_OK;
}
int sp_noise_compute(sp_data *sp, sp_noise *ns, SPFLOAT *in, SPFLOAT *out)
{
*out = ((sp_rand(sp) % SP_RANDMAX) / (SP_RANDMAX * 1.0));
*out = (*out * 2) - 1;
*out *= ns->amp;
return SP_OK;
}
int sp_noise_destroy(sp_noise **ns)
{
free(*ns);
return SP_OK;
}
typedef struct{
SPFLOAT amp;
}sp_noise;
int sp_noise_create(sp_noise **ns);
int sp_noise_init(sp_data *sp, sp_noise *ns);
int sp_noise_compute(sp_data *sp, sp_noise *ns, SPFLOAT *in, SPFLOAT *out);
int sp_noise_destroy(sp_noise **ns);
#ifndef SOUNDPIPE_H
#define SOUNDPIPE_H
#include <stdint.h>
#include <stdio.h>
#define SP_BUFSIZE 4096
#ifndef SPFLOAT
#define SPFLOAT float
#endif
#define SP_OK 1
#define SP_NOT_OK 0
#define SP_RANDMAX 2147483648
typedef unsigned long sp_frame;
typedef struct sp_auxdata {
size_t size;
void *ptr;
} sp_auxdata;
typedef struct sp_data {
SPFLOAT *out;
int sr;
int nchan;
unsigned long len;
unsigned long pos;
char filename[200];
uint32_t rand;
} sp_data;
typedef struct {
char state;
SPFLOAT val;
} sp_param;
int sp_auxdata_alloc(sp_auxdata *aux, size_t size);
int sp_auxdata_free(sp_auxdata *aux);
int sp_create(sp_data **spp);
int sp_createn(sp_data **spp, int nchan);
int sp_destroy(sp_data **spp);
int sp_process(sp_data *sp, void *ud, void (*callback)(sp_data *, void *));
int sp_process_raw(sp_data *sp, void *ud, void (*callback)(sp_data *, void *));
int sp_process_plot(sp_data *sp, void *ud, void (*callback)(sp_data *, void *));
int sp_process_spa(sp_data *sp, void *ud, void (*callback)(sp_data *, void *));
SPFLOAT sp_midi2cps(SPFLOAT nn);
int sp_set(sp_param *p, SPFLOAT val);
int sp_out(sp_data *sp, uint32_t chan, SPFLOAT val);
uint32_t sp_rand(sp_data *sp);
void sp_srand(sp_data *sp, uint32_t val);
#include "biquad.h"
#include "noise.h"
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment