From 9763831fa0f5ade2ce74d237bd0fdcb9f02b4fd7 Mon Sep 17 00:00:00 2001 From: EvanR Date: Fri, 5 Jun 2009 16:24:16 -0400 Subject: [PATCH] Initial commit. The initial state of the repo is this: core.c has functions to initialize a synth, control the synth state, schedule changes to the state, and generate stereo sound to be used by whatever. jackclient.c sets a synth as a jack client. instruments.h has the configuration for the non sampled instruments. --- README | 5 + build.sh | 1 + core.c | 546 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ instruments.h | 164 ++++++++++++++++++ jackclient.c | 110 ++++++++++++ orgux.h | 9 + 6 files changed, 835 insertions(+) create mode 100644 README create mode 100644 build.sh create mode 100644 core.c create mode 100644 instruments.h create mode 100644 jackclient.c create mode 100644 orgux.h diff --git a/README b/README new file mode 100644 index 0000000..51e14b6 --- /dev/null +++ b/README @@ -0,0 +1,5 @@ +build with this command + +sh build.sh + +edit build.sh as needed diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..aaa261f --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +gcc -o orgux -std=c99 core.c jackclient.c -lm -ljack diff --git a/core.c b/core.c new file mode 100644 index 0000000..b7f3edf --- /dev/null +++ b/core.c @@ -0,0 +1,546 @@ +/* + +cap notes + + +16 channels +stereo monophonic synth +128 interpolated oscillators +channel 10, samples, polyphonic +basic start and stop cosine envelope + +2 controllers +main volume +pan + + +*/ + + +#include +#include +#include + +#define PI2 3.141592653589*2 + +#include "orgux.h" + +#include "instruments.h" + + +#define SAMPLE_LENGTH 1<<16 +#define SAMPLE_COUNT 16 +#define SAMPLE_NOTE_ZERO 60 + +#define ANTIPOP_LENGTH 64 +#define WAVEFORM_LENGTH 256 + +#define MAX_COMMANDS 256 +#define MAX_NOTES 128 + +#define GET_ON_BIT(C,N) (S->onbits[C][N>>3] & (1 << ( N & 0x7))) +#define SET_ON_BIT(C,N) (S->onbits[C][N>>3] |= 1 << ( N & 0x7)) +#define CLEAR_ON_BIT(C,N) (S->onbits[C][N>>3] &= ~(1 << ( N & 0x7))) + + +#define RANDF() (((float)rand())/RAND_MAX) + +struct orgux_state{ + float volume[16]; + float pan_l[16]; + float pan_r[16]; + float bend[16]; + int instrument[16]; + + //float velocity[16][128]; + unsigned char onbits[16][16]; + + float waveform[128][WAVEFORM_LENGTH]; + float antipop[ANTIPOP_LENGTH]; + //float wave_ptr[16][128]; + //float wave_step[16][128]; + + //int env_ptr[16][128]; + //int env_flag[16][128]; + + //need to redo the samples + float samples[SAMPLE_COUNT][SAMPLE_LENGTH]; + //int sample_ptr[SAMPLE_COUNT]; + //int sample_on[SAMPLE_COUNT]; + //float sample_velocity[SAMPLE_COUNT]; + + int sample_rate; + + int command_queue[512][5]; /* sample type chan val1 val2 */ + int command_count; + + int note_on[MAX_NOTES]; + int note_channel[MAX_NOTES]; + int note_note[MAX_NOTES]; + float velocity[MAX_NOTES]; + int antipop_flag[MAX_NOTES]; + int antipop_ptr[MAX_NOTES]; + float wave_ptr[MAX_NOTES]; + float wave_step[MAX_NOTES]; + int sample_ptr[MAX_NOTES]; + int note_max; +}; + +void orgux_note_on(orgux_state* S, int chan, int note, int velocity){ + + for(int i=0; i < MAX_NOTES; i++){ + if(S->note_on[i] == 0){ + S->note_on[i] = 1; + S->note_channel[i] = chan; + S->note_note[i] = note; + S->velocity[i] = ((float)velocity)/127; + S->antipop_flag[i] = -1; + S->antipop_ptr[i] = 0; + S->wave_ptr[i] = 0.0f; + S->sample_ptr[i] = 0; + S->wave_step[i] = (440*pow(2,(note-57)/12.0)*WAVEFORM_LENGTH)/S->sample_rate; + if(i == S->note_max){ + S->note_max++; + } + break; + } + } + +} + +void orgux_note_off(orgux_state* S, int chan, int note){ + + for(int i=0; i < S->note_max; i++){ + if(S->note_on[i]==1 && S->note_channel[i]==chan && S->note_note[i]==note && S->antipop_flag[i]<1){ + + //S->note_on[i][1] = chan; + //S->note_on[i][2] = note; + S->antipop_flag[i] = 1; + //S->wave_ptr[i] = 0.0f; + //S->wave_step[i] = (440*pow(2,(note-57)/12.0)*WAVEFORM_LENGTH)/S->sample_rate; + //S->note_count++; + break; + } + } + +} + +void orgux_change_volume(orgux_state* S, int chan, int value){ + //printf("change volume %d %d\n", chan, value); + S->volume[chan] = ((float)value)/127; +} + +void orgux_change_pan(orgux_state* S, int chan, int value){ + //printf("change pan %d %d\n", chan, value); + float P = (((float)value)/127) * 2 - 1; + + if(P > 0){ + S->pan_l[chan] = 1.0f - P; + S->pan_r[chan] = 1.0f; + } + else{ + S->pan_l[chan] = 1.0f; + S->pan_r[chan] = P + 1.0f; + } +} + +void orgux_change_instrument(orgux_state* S, int chan, int value){ + //printf("change instrument %d %d\n", chan, value); + S->instrument[chan] = value; +} + +void orgux_pitch_bend(orgux_state* S, int chan, int bend){ + S->bend[chan] = ((((float)bend)/16383) * 2 - 1) * 1; +} + + +void orgux_process(orgux_state* S, float* lbuf, float* rbuf, int len){ + int C=0; + + /* determine on notes, dont search each time */ + int note_ons[MAX_NOTES]; + int N = 0; + for(int i=0; inote_max; i++){ + if(S->note_on[i]){ + note_ons[N] = i; + N++; + } + } + + for(int i=0; icommand_queue[C][0] && C < S->command_count){ + orgux_control(S, S->command_queue[C][1], + S->command_queue[C][2], + S->command_queue[C][3], + S->command_queue[C][4]); + C++; + } + + lbuf[i] = 0.0f; + rbuf[i] = 0.0f; + + + //render playing samples + /*for(int j = 0; jsample_on[j]) continue; + float y = S->samples[j][S->sample_ptr[j]++]; + if(S->sample_ptr[j] == SAMPLE_LENGTH){ + S->sample_on[j] = 0; + } + float V = S->volume[9]; + float A = S->sample_velocity[j]; + lbuf[i] += V*A*S->pan_l[9]*y; + rbuf[i] += V*A*S->pan_r[9]*y; + }*/ + + + int jmax = S->note_max; + for(int j=0; j < jmax; j++){ + //for(int n=0; n < N; n++){ + //int j = note_ons[n]; + + if(!S->note_on[j]) continue; + + if(S->note_channel[j] == 9){ + int index = S->note_note[j] - SAMPLE_NOTE_ZERO; + if(index < 0){index=0;} + if(index >= SAMPLE_COUNT){index=SAMPLE_COUNT-1;} + float y = S->samples[index][S->sample_ptr[j]++]; + if(S->sample_ptr[j] == SAMPLE_LENGTH){ + S->note_on[j] = 0; + } + + float V = S->volume[9]; + float A = S->velocity[j]; + lbuf[i] += V*A*S->pan_l[9]*y; + rbuf[i] += V*A*S->pan_r[9]*y; + + continue; + } +//continue; +/* hard computations */ + float x = S->wave_ptr[j]; + float x1 = floor(x); + float x2 = x1 + 1.0f; + int X1 = (int)x1; + int X2 = X1 + 1; + if(X2 == WAVEFORM_LENGTH) X2 = 0; + int I = S->instrument[S->note_channel[j]]; + float y1 = S->waveform[I][X1]; + float y2 = S->waveform[I][X2]; + float m = (y2-y1)/(x2-x1); + float y = m*(x-x1) + y1; +//float y = 0; + + switch(S->antipop_flag[j]){ + case -1: + y *= S->antipop[S->antipop_ptr[j]]; + S->antipop_ptr[j]++; + + if(S->antipop_ptr[j] == ANTIPOP_LENGTH){ + S->antipop_ptr[j] = ANTIPOP_LENGTH-1; + S->antipop_flag[j] = 0; + } + break; + case 1: + y *= S->antipop[S->antipop_ptr[j]]; + S->antipop_ptr[j]--; + if(S->antipop_ptr[j] < 0){ +//printf("note dead! j = %d, max = %d\n",j, S->note_max); + S->antipop_flag[j] = 0; + S->note_on[j] = 0; + if(j+1==S->note_max){ + S->note_max--; + } + } + break; + } + + + int chan = S->note_channel[j]; + float volume = S->volume[chan]; + float velocity = S->velocity[j]; + lbuf[i] += volume*velocity*S->pan_l[chan]*y; + rbuf[i] += volume*velocity*S->pan_r[chan]*y; + +if(lbuf[i]> 1.0 || lbuf[i] < -1.0){ +printf("ehh lbuf[%d] = %f\n",i,lbuf[i]); +printf("%f %f %f %f %f\n",y,volume, velocity, S->pan_l[chan], S->pan_r[chan]); +} + + S->wave_ptr[j] += S->wave_step[j]; + while(S->wave_ptr[j] >= WAVEFORM_LENGTH){ + S->wave_ptr[j] -= WAVEFORM_LENGTH; + } + + } + + } + + S->command_count = 0; + +} + + + + +void orgux_schedule(orgux_state* S, int sample, unsigned char midi[3]){ + //orgux_control(S, midi[0]&0xf0, midi[0]&0x0f, midi[1], midi[2]); + + if(S->command_count == MAX_COMMANDS){ + return; + } + + switch(midi[0]&0xf0){ + case 0xA0: + case 0xD0: + return; + } + /* +the queue is sorted by time (sample) +soonest times are to the beginning of the queue +queue[0] is the first element +insert: move all later events right one + */ + +//printf("schedule %d %x %x %x\n",sample,midi[0],midi[1],midi[2]); + int i; + for(i=0; icommand_count; i++){ + + if(sample < S->command_queue[i][0]){ + + for(int j=S->command_count; j>i; j--){ + S->command_queue[j][0] = S->command_queue[j-1][0]; + S->command_queue[j][1] = S->command_queue[j-1][1]; + S->command_queue[j][2] = S->command_queue[j-1][2]; + S->command_queue[j][3] = S->command_queue[j-1][3]; + S->command_queue[j][4] = S->command_queue[j-1][4]; + } + + S->command_queue[i][0] = sample; + S->command_queue[i][1] = midi[0]&0xf0; + S->command_queue[i][2] = midi[0]&0x0f; + S->command_queue[i][3] = midi[1]; + S->command_queue[i][4] = midi[2]; + + break; + } + } + + if(i==S->command_count){//end of queue + S->command_queue[i][0] = sample; + S->command_queue[i][1] = midi[0]&0xf0; + S->command_queue[i][2] = midi[0]&0x0f; + S->command_queue[i][3] = midi[1]; + S->command_queue[i][4] = midi[2]; + } + + S->command_count++; + +for(int i=0; icommand_count; i++){ +/*printf("%d %d %d %d %d\n", + S->command_queue[i][0], + S->command_queue[i][1], + S->command_queue[i][2], + S->command_queue[i][3], + S->command_queue[i][4]); +*/ +} + +} + +void orgux_control(orgux_state* S, int type, int chan, int val1, int val2){ + + int bend = (val1 << 7) + val2; + + //printf("control %d %d %d %d\n", chan, type, val1, val2); + + switch(type){ + case 0x90: + orgux_note_on(S, chan, val1, val2); + return; + case 0x80: + orgux_note_off(S, chan, val1); + return; + case 0xC0: + orgux_change_instrument(S, chan, val1); + return; + case 0xB0: + if(val1 == 7){ + orgux_change_volume(S, chan, val2); + } + else if(val1 == 10){ + orgux_change_pan(S, chan, val2); + } + return; + case 0xE0: +printf("pitch bend %d\n",bend); + orgux_pitch_bend(S, chan, bend); + return; + } +} + + + +orgux_state* orgux_init(int sample_rate){ + orgux_state* S = malloc(sizeof(orgux_state)); + if(!S) return NULL; + + /* setup oscillator states */ + + for(int i=0; i<16; i++){ + S->volume[i] = 1.0f; + S->pan_l[i] = 1.0f; + S->pan_r[i] = 1.0f; + } + + for(int i=0; iwave_ptr[i] = 0.0f; + S->antipop_ptr[i] = 0; + S->antipop_flag[i] = 0; + S->note_on[i] = 0; + S->sample_ptr[i] = 0; + } + + //for(int i=0; isample_on[i] = 0; + // S->sample_ptr[i] = 0; + //} + + S->sample_rate = sample_rate; + S->command_count = 0; + S->note_max = 0; + + /* setup wave tables */ + + for(int i=0; i<128; i++){ +float max = 0; +int N = 0; + for(int j=0; jwaveform[i][j] = 0.0f; + N = 0; + for(int k=0; kwaveform[i][j] += M * sin((j*(1<0){ S->waveform[i][j] /= N*10; } + if(S->waveform[i][j] > max){ max = S->waveform[i][j]; } + } + printf("max[%d] = %f, %d\n",i,max, N); + } + + //generate antipop cosine + for(int i=0; iantipop[i] = -cos(i*PI2/(2.0*ANTIPOP_LENGTH))/2.0+0.5; + } + + + //generate samples + + float par[16][8] = {/**/ +{50, 500, 0.5, 10000, 0, 0, 0, 0}, +{200, 200, 0.5, 10000, 0, 0, 0, 0}, +{100, 500, 0.5, 10000, 0, 0, 0, 0}, +{100, 1000, 0.5, 10000, 0, 0, 0, 0}, + +{100, 500, 0.5, 3000, 0, 0, 0, 0}, +{200, 500, 0.5, 3000, 0, 0, 0, 0}, +{300, 500, 0.5, 3000, 0, 0, 0, 0}, +{400, 500, 0.5, 3000, 0, 0, 0, 0}, + +{400, 200, 0.5, 3000, 0, 0, 0, 0}, +{400, 100, 0.5, 3000, 0, 0, 0, 0}, +{400, 50, 0.5, 3000, 0, 0, 0, 0}, +{400, 20, 0.5, 3000, 0, 0, 0, 0}, + +{100, 500, 0.5, 10000, 0, 0, 0, 0}, +{100, 500, 0.5, 10000, 0, 0, 0, 0}, +{100, 500, 0.5, 10000, 0, 0, 0, 0}, +{100, 500, 0.5, 10000, 0, 0, 0, 0} +}; + + double K = PI2 / sample_rate; + + for(int i=0; isamples[j][i] = E*A*sin(i*f*K); + } + } + + float y_l; + float y_h0=0; + float y_h1=0; + float dt = (1.0/sample_rate); + +/* +notes + +cool hit +tau2 = 0.0001 / (1 + i/50.0) +alpha2 = tau2 / (tau2 + dt) +A = 0.2 - (i/10000.0) + + + + + +*/ + + for(int i=0; isamples[15][i] = A*E*y; + + } + + return S; + +} + +void orgux_free(orgux_state* S){ + free(S); +} + diff --git a/instruments.h b/instruments.h new file mode 100644 index 0000000..f3630bf --- /dev/null +++ b/instruments.h @@ -0,0 +1,164 @@ +#define BASIS_COUNT 16 +#define COMPONENT_MAX 255 + +static const unsigned char spectra[128][BASIS_COUNT] = { +{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*0*/ +{2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{4,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{8,4,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, + +{8,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{8,2,4,1,0,0,0,0,0,0,0,0,0,0,0,0}, +{16,4,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, +{8,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{16,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0},/*8*/ +{16,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{32,4,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, +{32,2,8,1,0,0,0,0,0,0,0,0,0,0,0,0}, + +{255,128,64,32,16,8,4,2,1,0,0,0,0,0,0,0}, +{255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{255,4,7,2,1,2,0,0,0,0,0,0,0,0,0,0}, +{255,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{255,0,28,0,10,0,5,0,2,0,0,0,0,0,0,0},/*16*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*24*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*32*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*40*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*48*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*56*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*64*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*72*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*80*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*88*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*96*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*104*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*112*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},/*120*/ +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +}; \ No newline at end of file diff --git a/jackclient.c b/jackclient.c new file mode 100644 index 0000000..8df3f76 --- /dev/null +++ b/jackclient.c @@ -0,0 +1,110 @@ +/* jack test of synth */ + +#include +#include +#include + +#include "orgux.h" + +#include +#include +jack_port_t *input_port; +jack_port_t *output_port_1; +jack_port_t *output_port_2; + +orgux_state* S; + +int process (jack_nframes_t nframes, void *arg) { + int i; + void* port_buf = jack_port_get_buffer(input_port, nframes); + + jack_default_audio_sample_t *out1 = (jack_default_audio_sample_t *) +jack_port_get_buffer(output_port_1, nframes); + + jack_default_audio_sample_t *out2 = (jack_default_audio_sample_t *) +jack_port_get_buffer(output_port_2, nframes); + + jack_midi_event_t in_event; + jack_nframes_t event_count = jack_midi_get_event_count(port_buf); + + unsigned char midi[3]; + for(int i=0; i< event_count; i++){ + + jack_midi_event_get(&in_event, port_buf, i); + midi[0] = in_event.buffer[0]; + midi[1] = in_event.buffer[1]; + midi[2] = in_event.buffer[2]; + + orgux_schedule(S, in_event.time, midi); + + } + + orgux_process(S, out1, out2, nframes); + + return 0; +} + +int +srate (jack_nframes_t nframes, void *arg) + +{ + printf ("the sample rate is now %lu/sec\n", nframes); + return 0; +} + + +void +jack_shutdown (void *arg) +{ + printf("jack shutdown\n"); + exit (1); +} + +void +error (const char *desc) +{ + fprintf (stderr, "JACK error: %s\n", desc); +} + + + +int main(){ + + + + jack_client_t *client; + + jack_set_error_function (error); + + if ((client = jack_client_new ("orgux")) == 0) { + fprintf (stderr, "jack server not running?\n"); + return 1; + } + + S = orgux_init(jack_get_sample_rate(client)); + + jack_set_process_callback (client, process, 0); + jack_set_sample_rate_callback (client, srate, 0); + jack_on_shutdown (client, jack_shutdown, 0); + + input_port = jack_port_register(client, "midi-in", +JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); + output_port_1 = jack_port_register (client, "out-1", +JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + output_port_2 = jack_port_register (client, "out-2", +JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + + if (jack_activate (client)) { + fprintf (stderr, "cannot activate client"); + return 1; + } + + while(1){ + sleep(1); + } + + orgux_free(S); + + jack_client_close (client); + return 0; +} \ No newline at end of file diff --git a/orgux.h b/orgux.h new file mode 100644 index 0000000..db70352 --- /dev/null +++ b/orgux.h @@ -0,0 +1,9 @@ +/* orgux.h */ + +typedef struct orgux_state orgux_state; + +void orgux_process(orgux_state* S, float* lbuf, float* rbuf, int len); +void orgux_schedule(orgux_state* S, int sample, unsigned char midi[3]); +void orgux_control(orgux_state* S, int type, int chan, int val1, int val2); +orgux_state* orgux_init(int sample_rate); +void orgux_free(orgux_state* S); \ No newline at end of file -- 2.11.4.GIT