Mx44/interface2.c0000644000076400007640000014371310242563450012502 0ustar jensjens/* * This software is released under GPL. If you don't know what that is * immediately point your webbrowser to http://www.gnu.org and read * all about it. * * The short version: You can modify the sources for your own purposes * but you must include the new sources if you distribute a derived work. * * (C) 2002, 2003, 2004, 2005 Jens M Andreasen * * * * * ( * ) * c[] * * */ //static char * widget_theme = 0; // NADA! static char * widget_theme = "/usr/share/themes/Crux/gtk-2.0/gtkrc"; //static char * widget_theme = "/home/jens/.themes/g5-ish/gtk-2.0/gtkrc"; #include #include #include #include #include //#include "interface.h" #include "mx44.h" #include // hint_t groups #define MISC 0 #define ENV1 1 /* time */ #define ENV2 2 /* level */ #define ENV3 3 /* other */ #define MOD1 4 /* phase */ #define MOD2 5 /* amplitude */ #define FREQ 6 #define BIAS 7 #define DELAY 8 #define DIST 9 #define LFO 10 extern Mx44state * mx44; extern int mx44running; extern Mx44patch * mx44patch; // Stored patches extern unsigned char* mx44patchNo;// index of patch in use extern Mx44patch* mx44tmpPatch; // copy of patch in use. static int midichannel = 0; static int group,bank,patch; typedef struct _hint { int op; int group; int index; float min; float max; char * spinlabel; }hint_t; static GtkWidget *window1; static struct mx44patch_edit { GtkWidget *pm[4][4]; // [destination] [source] GtkWidget *am[4][4]; GtkWidget *mix[4][2]; // [op] [level/balance] GtkWidget *env_level[4][8]; // [op] [stage] GtkWidget *env_time[4][8]; GtkWidget *wheelbutton[4][2]; GtkWidget *od[4][8]; GtkWidget *od_group[4]; GtkWidget *wawebutton[4]; GtkWidget *lowpassbutton[4]; GtkWidget *waweshapebutton[4]; GtkWidget *phasefollowkeybutton[4]; GtkWidget *magicbutton[4]; GtkWidget *harmonic[4]; GtkWidget *detune[4]; GtkWidget *intonation[4][2]; GtkWidget *velocityfollow[4]; // key bias GtkWidget *breakpoint[4]; // [op] GtkWidget *keybias[4][2]; // [op][hi/lo value] // env keyfollow GtkWidget *keyfollow[4][2]; // [op][attack/sustain-loop] // key velocity GtkWidget *velocity[4]; // [op] GtkWidget *phase[4][2]; // [op][offset/velocityfollow] //GtkWidget *mod_delay; // delay for am/pm //GtkWidget *mod_keyfollow; // keyfollow //GtkWidget *delay_table; //GtkWidget * //GtkWidget * //GtkWidget * // GtkWidget *spinbutton[4]; // GtkWidget *spinlabel[4]; GtkWidget *common_spinbutton; GtkWidget *common_spinlabel; GtkWidget *common_oplabel; GtkWidget *monobutton; GtkWidget *lfo[6]; GtkWidget *lfo_button[2]; GtkWidget *window; GtkWidget *table[4]; GtkWidget *canvas; int op; }ed; static int wn; static char *op_label[]={"Op 1","Op 2","Op 3","Op 4",NULL}; static int patch_change =1; static void set_value(GtkRange* range,double value) { if(range) { GtkAdjustment *adj = gtk_range_get_adjustment(range); gtk_adjustment_set_value(adj,value); } } static GtkWidget *patchname; static GtkWidget *patch_group_1; static GtkWidget *patch_group_2; static GtkComboBox *bank_entry; static GtkComboBox *patch_entry; static GtkObject *midichannel_spinner_adj; volatile struct { Mx44patch *tmp; int channel ; int number; } newpatch; static void set_widgets(Mx44patch *tmp_patch,int channel ,int patchNumber) { int i, op; patch_change = 1; if(midichannel == -1) { midichannel = channel; gtk_adjustment_set_value((GtkAdjustment*)midichannel_spinner_adj,midichannel+1); } //if(midichannel != channel) return; tmp_patch = tmp_patch + channel; if( patchNumber != -1) { group = patchNumber >= 64; bank = (patchNumber & 0x03F)>>3; patch = patchNumber & 0x07; gtk_combo_box_set_active((GtkComboBox*)bank_entry,bank); gtk_combo_box_set_active((GtkComboBox*)patch_entry,patch); if(group) g_signal_emit_by_name(patch_group_2,"clicked"); //gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (patch_group_2), TRUE); else g_signal_emit_by_name(patch_group_1,"clicked"); //gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (patch_group_1), TRUE); } //set_value((GtkRange*)ed.mod_delay , tmp_patch->mod_delay/320.0); gtk_entry_set_text (GTK_ENTRY (patchname), tmp_patch->name); //printf("name: %s\n", tmp_patch->name); for(op = 0; op < 4; ++op) { for(i=0; i < 4; ++i) { set_value((GtkRange*)ed.pm[op][i] , tmp_patch->pm[op][i]/320.0); set_value((GtkRange*)ed.am[op][i] , tmp_patch->am[op][i]/320.0); } set_value((GtkRange*)ed.mix[op][0] , tmp_patch->mix[op][0]/320.0); set_value((GtkRange*)ed.mix[op][1] , tmp_patch->mix[op][1]/177.0); for(i=0; i < 8; ++i) { set_value((GtkRange*)ed.env_level[op][i] , tmp_patch->env_level[op][i]/80.0); set_value((GtkRange*)ed.env_time[op][i] , tmp_patch->env_time[op][i]/320.0); } gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.od[op][tmp_patch->od[op]&0x07]), TRUE); set_value((GtkRange*)ed.harmonic[op] , tmp_patch->harmonic[op]/128.0); //if(tmp_patch->detune[op] <0) set_value((GtkRange*)ed.detune[op] , tmp_patch->detune[op]/100.0); //else //set_value((GtkRange*)ed.detune[op] , pow(tmp_patch->detune[op],1.0/3.0)/3.2); set_value((GtkRange*)ed.intonation[op][0] , tmp_patch->intonation[op][0]/327.6); set_value((GtkRange*)ed.intonation[op][1] , tmp_patch->intonation[op][1]/327.6); set_value((GtkRange*)ed.velocityfollow[op] , tmp_patch->velocityfollow[op]/320.0); set_value((GtkRange*)ed.breakpoint[op] , tmp_patch->breakpoint[op]); set_value((GtkRange*)ed.keybias[op][1] , -sqrt(tmp_patch->keybias[op][0])); set_value((GtkRange*)ed.keybias[op][0] , -sqrt(tmp_patch->keybias[op][1])); set_value((GtkRange*)ed.keyfollow[op][0] , tmp_patch->keyfollow[op][0]/320.0); set_value((GtkRange*)ed.keyfollow[op][1] , tmp_patch->keyfollow[op][1]/320.0); set_value((GtkRange*)ed.velocity[op] , tmp_patch->velocity[op]/320.0); set_value((GtkRange*)ed.phase[op][0] , tmp_patch->phase[op][0]/320.0); set_value((GtkRange*)ed.phase[op][1] , tmp_patch->phase[op][1]/320.0); if(tmp_patch->button[op]&WAWEBUTTON) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.wawebutton[op]), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.wawebutton[op]), FALSE); if(tmp_patch->button[op]&WHEELBUTTON) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.wheelbutton[op][0]), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.wheelbutton[op][0]), FALSE); if(tmp_patch->button[op]&LOWPASSBUTTON) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.lowpassbutton[op]), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.lowpassbutton[op]), FALSE); if(tmp_patch->button[op]&WAWESHAPEBUTTON) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.waweshapebutton[op]), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.waweshapebutton[op]), FALSE); if(tmp_patch->button[op]&PHASEFOLLOWKEYBUTTON) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.phasefollowkeybutton[op]), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.phasefollowkeybutton[op]), FALSE); if(tmp_patch->button[op]&MAGICBUTTON) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.magicbutton[op]), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.magicbutton[op]), FALSE); } for(i = 0;i<6;++i) set_value((GtkRange*)ed.lfo[i] , tmp_patch->lfo[i]/320.0); for(i = 0;i<2;++i) if(tmp_patch->lfo_button[i]) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.lfo_button[i]), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.lfo_button[i]), FALSE); if(mx44->monomode[channel]) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.monobutton), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed.monobutton), FALSE); patch_change = 0; } void setwidgets(Mx44patch *tmp_patch,int channel ,int patchNumber) { // printf("channel: %d midichannel: %d\n",channel,midichannel); if(channel == midichannel) { newpatch.tmp = tmp_patch; newpatch.channel = channel; } } static int check_patch(void* data) { if(mx44->patchNo[midichannel] != newpatch.number) { //puts("check_patch"); newpatch.number = mx44->patchNo[midichannel]; set_widgets(newpatch.tmp, newpatch.channel, newpatch.number); } return 1; } // unique widget names static char * name_n() { static int n =0; char tmp[64]; sprintf(tmp,"%s%d","widget_",n++); return strdup(tmp); } static void line(GtkWidget *table,int x,int y,int width,int height) { char*name; GtkWidget *line = gtk_hseparator_new (); name = name_n(); gtk_widget_set_name (line, name); gtk_widget_ref (line); gtk_object_set_data_full (GTK_OBJECT (ed.window), name, line, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (line); gtk_table_attach (GTK_TABLE (table), line, x, x+width, y, y+height, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL), 0, 0); } static GtkWidget *label(GtkWidget *table,int x,int y,int width,char*text) { GtkWidget *label = gtk_label_new (text); text = name_n(); gtk_widget_set_name (label, text); gtk_widget_ref (label); gtk_object_set_data_full (GTK_OBJECT (table), text, label, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (label); gtk_table_attach (GTK_TABLE (table), label, x,x+width, y, y+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_widget_set_sensitive (label, FALSE); gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); return label; } static GtkAdjustment *spin_adj; static int on_focus( GtkRange *range, GdkEvent *event, hint_t* hint) { GtkAdjustment *adj = gtk_range_get_adjustment(range); if(patch_change) return 0; if(spin_adj != adj) { spin_adj = adj; /* gtk_label_set_text((GtkLabel*)ed.spinlabel[hint->op],hint->spinlabel); gtk_spin_button_set_adjustment( (GtkSpinButton*)ed.spinbutton[hint->op], adj); gtk_spin_button_set_value ((GtkSpinButton*)ed.spinbutton[hint->op],adj->value); */ gtk_label_set_text((GtkLabel*)ed.common_spinlabel,hint->spinlabel); if(hint->op <0) gtk_label_set_text((GtkLabel*)ed.common_oplabel,"Mx44"); else gtk_label_set_text((GtkLabel*)ed.common_oplabel,op_label[hint->op]); gtk_spin_button_set_adjustment( (GtkSpinButton*)ed.common_spinbutton, adj); gtk_spin_button_set_value ((GtkSpinButton*)ed.common_spinbutton,adj->value); } return 0; } static int on_range( GtkRange *range, GdkEvent *event, hint_t* hint) { if(patch_change) return 1; on_focus(range,event,hint); gtk_widget_grab_focus((GtkWidget*)ed.common_spinbutton); return 0; } static void on_value_changed( GtkAdjustment *adj, hint_t* hint) { double value = adj->value; if(patch_change) return; if(spin_adj != adj) { spin_adj = adj; /* gtk_label_set_text((GtkLabel*)ed.spinlabel[hint->op],hint->spinlabel); gtk_spin_button_set_adjustment( (GtkSpinButton*)ed.spinbutton[hint->op], adj); */ //gtk_label_set_text((GtkLabel*)ed.common_spinlabel,hint->spinlabel); //gtk_spin_button_set_adjustment( (GtkSpinButton*)ed.common_spinbutton,adj); } switch(hint->group) { case MISC: if(hint->index == 0) // phase init { mx44tmpPatch[ midichannel ].phase[hint->op][0] = value * 320 ; } else if(hint->index == 1) // phase velocity { mx44tmpPatch[ midichannel ].phase[hint->op][1] = value * 320 ; } else if(hint->index == 2) // velocity sensitivity { mx44tmpPatch[ midichannel ].velocity[hint->op] = value * 320 ; } else if(hint->index == 3) // output volume { mx44tmpPatch[ midichannel ].mix[hint->op][0] = value * 320 ; } else if(hint->index == 4) // output balance { mx44tmpPatch[ midichannel ].mix[hint->op][1] = value * 177 ; } break; case ENV1: // envelope time { mx44tmpPatch[ midichannel ].env_time[hint->op][hint->index] = value * 320 ; break; } case ENV2: // envelope level { mx44tmpPatch[ midichannel ].env_level[hint->op][hint->index] = value * 80; break; } case ENV3: if(hint->index == 0) // attacktime velocityfollow { mx44tmpPatch[ midichannel ].velocityfollow[hint->op] = value * 320 ; } else if(hint->index == 1) // attack/release keyfollow { mx44tmpPatch[ midichannel ].keyfollow[hint->op][0] = value * 320 ; } else if(hint->index == 2) // sustainloop keyfollow { mx44tmpPatch[ midichannel ].keyfollow[hint->op][1] = value * 320 ; } break; case FREQ: if(hint->index == 0) // frequency course { mx44tmpPatch[ midichannel ].harmonic[hint->op] = value * 128 ; } else if(hint->index == 2) // frequency offset { mx44tmpPatch[ midichannel ].detune[hint->op] = value * 100; } else if(hint->index == 3) // intonation amount { mx44tmpPatch[ midichannel ].intonation[hint->op][0] = value * 327.6 ; } else if(hint->index == 4) // intonation decay { mx44tmpPatch[ midichannel ].intonation[hint->op][1] = value * 327.6 ; } break; case BIAS: if(hint->index == 0) // breakpoint { mx44tmpPatch[ midichannel ].breakpoint[hint->op] = value; } else if(hint->index == 1) // bias low { mx44tmpPatch[ midichannel ].keybias[hint->op][1] = value * value; } else if(hint->index == 2) // bias low { mx44tmpPatch[ midichannel ].keybias[hint->op][0] = value * value; } break; case MOD1: mx44tmpPatch[ midichannel ].pm[hint->op][hint->index] = value * 320; break; case MOD2: mx44tmpPatch[ midichannel ].am[hint->op][hint->index] = value * 320; break; case DELAY: puts("no delay yet"); break; case DIST: puts("no overdrive yet"); break; case LFO: mx44tmpPatch[ midichannel ].lfo[hint->index] = value * 320; //puts("no LFO yet"); //printf("index: %f\n",value * 320);//hint->index); break; } } /* static void on_delay( GtkAdjustment *adj, hint_t* hint) { double value = adj->value; printf("delay: %f\n",value); switch(((int)hint)) { case 0: mx44tmpPatch[ midichannel ].mod_delay = value * 320; break; case 1: mx44tmpPatch[ midichannel ].mod_keyfollow = value * 320; break; } } */ static GtkWidget *scale(GtkWidget *table,int x,int y,int width,int height, float min, float max,int op,int group,int groupindex,char*help) { GtkAdjustment *adj; GtkWidget *widget; hint_t *hint = malloc(sizeof(hint_t)); char*name = name_n(); hint->spinlabel=help; hint->op = op; hint->group = group; hint->index = groupindex; hint->min = min; hint->max = max; adj = (GtkAdjustment*)gtk_adjustment_new (0, min, max, 0.01, 1.0, 0.0); g_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC(on_value_changed), hint); if(width > height) { //widget = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj)); widget = gtk_hscale_new (GTK_ADJUSTMENT (adj)); } else { //widget = gtk_vscrollbar_new (GTK_ADJUSTMENT (adj)); widget = gtk_vscale_new (GTK_ADJUSTMENT (adj)); gtk_range_set_inverted ((GtkRange*)widget, 1); } //* g_signal_connect (widget, "enter_notify_event", GTK_SIGNAL_FUNC (on_range), hint); g_signal_connect (widget, "focus_in_event", GTK_SIGNAL_FUNC (on_focus), hint); g_signal_connect (widget, "button_release_event", GTK_SIGNAL_FUNC (on_range), hint); //*/ gtk_widget_set_name (widget,name); gtk_widget_ref (widget); gtk_object_set_data_full (GTK_OBJECT (ed.window),name, widget, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (widget); gtk_table_attach (GTK_TABLE (table), widget, x, x+width, y, y+height, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0); gtk_scale_set_draw_value (GTK_SCALE (widget), FALSE); return widget; } static void mk_envelope(GtkWidget *table,int x,int y,int op,char*name) { int h = 8; int w = 0; int i; int index = 0; int size = 6; char*time_help[]={" attack time 1"," attack time 2"," attack time 3"," attack time 4", " sustainloop time 1"," sustainloop time 2", " release time 1"," release time 2"}; char*level_help[]={" startlevel"," attack level 1"," attack level 2"," attack level 3", " sustainloop level 1"," sustainloop level 2", " release level 1"," release level 2"}; for(i = 0;i<4;++i,--h,++w) { //printf("index: %d\n",index); ed.env_time[op][index] = scale(table,x+i+1,y+h,size-1,1, 0,100,op,ENV1,index,time_help[index]); if(i) ed.env_level[op][index] = scale(table,x+i+size-1,y+h+1,1,size -2, 0,100,op,ENV2,index,level_help[index]); else ed.env_level[op][index] = scale(table,x,y+h,1,size -2, 0,100,op,ENV2,index,level_help[index]); index++; } label(table,h-1,i,size+3,name); while(h-->0) { ++i; //printf("index: %d\n",index); ed.env_time[op][index] = scale(table,x+i+1,y+h,size-1,1, 0,100,op,ENV1,index,time_help[index ]); if(h>1) ed.env_level[op][index] = scale(table,x+i+size-1,y+h+1,1,size -2, 0,100,op,ENV2,index,level_help[index ]); else if(h == 1) ed.env_level[op][index+1] = scale(table,x+i+size,y+h,1,size -2, 0,100,op,ENV2,index+1,level_help[index ]); index++; } //label(ed.table[wn],6+x,14+y,5," Velocity"); ed.velocityfollow[op] = scale(table, 6+x,12+y,3,1, 0,100,op,ENV3,0," attacktime velocityfollow"); label(ed.table[op],9+x,10+y,4,"Keyfollow"); ed.keyfollow[op][0] = scale(table, 9+x,9+y,3,1, 0,100,op,ENV3,1," attack/release keyfollow"); ed.keyfollow[op][1] = scale(table, 10+x,8+y,3,1, 0,100,op,ENV3,2," sustainloop keyfollow"); } /* static GtkWidget *mk_delay_table(void) { GtkAdjustment *adj; GtkWidget *widget; GtkWidget *table; table = gtk_table_new (2, 8, FALSE); gtk_widget_ref (table); gtk_object_set_data_full (GTK_OBJECT (window1), "delay_table", table, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (table); adj = (GtkAdjustment*)gtk_adjustment_new (0, 0, 100, 0.01, 1.0, 0.0); g_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC(on_delay), NULL); widget = gtk_hscale_new (GTK_ADJUSTMENT (adj)); g_signal_connect (widget, "enter_notify_event", GTK_SIGNAL_FUNC (on_delay), NULL); g_signal_connect (widget, "focus_in_event", GTK_SIGNAL_FUNC (on_delay), NULL); g_signal_connect (widget, "button_release_event", GTK_SIGNAL_FUNC (on_delay), NULL); gtk_object_set_data_full (GTK_OBJECT (ed.window),"delay", widget, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_set_name (widget,"mod_delay"); gtk_widget_ref (widget); gtk_widget_show (widget); gtk_table_attach (GTK_TABLE (table), widget, 1, 3, 1, 2, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0); gtk_scale_set_draw_value (GTK_SCALE (widget), FALSE); ed.mod_delay = widget; adj = (GtkAdjustment*)gtk_adjustment_new (0, 0, 100, 0.01, 1.0, 0.0); g_signal_connect (adj, "value_changed", GTK_SIGNAL_FUNC(on_delay), NULL+1); widget = gtk_hscale_new (GTK_ADJUSTMENT (adj)); gtk_object_set_data_full (GTK_OBJECT (ed.window),"delay", widget, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_set_name (widget,"mod_delay"); gtk_widget_ref (widget); gtk_widget_show (widget); gtk_table_attach (GTK_TABLE (table), widget, 4, 6, 1, 2, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0); gtk_scale_set_draw_value (GTK_SCALE (widget), FALSE); ed.mod_keyfollow = widget; return table; } */ static void mk_patchbay(GtkWidget *table,int x,int y,int op,char*name) { int i; char*am_help[]={" op 1 amplitude modulation"," op 2 amplitude modulation", " op 3 amplitude modulation"," op 4 amplitude modulation"}; char*pm_help[]={" op 1 phase modulation"," op 2 phase modulation", " op 3 phase modulation"," op 4 phase modulation"}; for(i = 0;i<8;++i) { int x2=0; char*name; GtkWidget *line = gtk_vseparator_new (); if(i&2) { x2 = 2; } if(i&1) { ed.am[op][i>>1] = scale(table,x+x2,y+i,4,1, -100,100,op,MOD2,i>>1,am_help[i>>1]); } else { name = name_n(); gtk_widget_set_name (line, name); gtk_widget_ref (line); gtk_object_set_data_full (GTK_OBJECT (ed.window), name, line, (GtkDestroyNotify) gtk_widget_unref); gtk_table_attach (GTK_TABLE (table), line, x+x2+1, x+x2+3, y+i-(i==0), y+2+i, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL), 0, 0); ed.pm[op][i>>1] = scale(table,x+x2,y+i,4,1, -100,100,op,MOD1,i>>1,pm_help[i>>1]); gtk_widget_show (line); } } label(table,x,y+2,2," fm"); label(table,x,y+3,2," am"); } static GtkWidget* tab_label(GtkWidget *window,char *name) { GtkWidget *label; label = gtk_label_new (name); gtk_widget_ref (label); gtk_object_set_data_full (GTK_OBJECT (window), name_n(), label, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (label); return label; } static void on_od_clicked (GtkButton *button, void* user_data) { int value = ((int)user_data)&0x0F; int op = ((int)user_data)>>4; mx44tmpPatch[ midichannel ].od[op] = value; } static void on_lfo_button_clicked (GtkToggleButton *button, void* user_data) { if(button == (GtkToggleButton*)ed.lfo_button[0]) mx44tmpPatch[ midichannel ].lfo_button[0] = gtk_toggle_button_get_active(button); else if(button == (GtkToggleButton*)ed.lfo_button[1]) mx44tmpPatch[ midichannel ].lfo_button[1] = gtk_toggle_button_get_active(button); } static void on_button_clicked (GtkToggleButton *button, void* user_data) { int op = ((int)user_data)&0x0F; int number = ((int)user_data)>>4; char b = mx44tmpPatch[ midichannel ].button[op]; if(gtk_toggle_button_get_active(button)) { mx44tmpPatch[ midichannel ].button[op] = b |number; } else { mx44tmpPatch[ midichannel ].button[op] = b &(~number); } } static int saving; static void patch_changed(void) { int midipatch = group*64+bank*8+patch; if(midipatch < 0 || midipatch > 127) return; mx44patchNo [midichannel] = midipatch; newpatch.number = midipatch; if(patch_change) return; if(!saving) if(midichannel != -1) { //puts("patch_changed"); mx44tmpPatch[midichannel] = mx44patch[midipatch]; set_widgets(mx44tmpPatch,midichannel,-1); } } static void on_patch_group_1_clicked (GtkButton *button, void* user_data) { group = 0; patch_changed(); } static void on_patch_group_2_clicked (GtkButton *button, void* user_data) { group = 1; patch_changed(); } static int on_bank_entry_changed (GtkComboBox *combo, void* user_data) { /* char* txt = gtk_editable_get_chars(editable,0,50); if(*txt) { bank = txt[1] - 'A'; patch_changed(); } */ bank = gtk_combo_box_get_active(combo); patch_changed(); return 0; } static int on_patch_entry_changed (GtkComboBox *combo, void* user_data) { /* char* txt = gtk_editable_get_chars(editable,0,50); if(*txt) { patch = txt[1] - '1'; patch_changed(); } */ patch = gtk_combo_box_get_active(combo); patch_changed(); return 0; } GtkToggleButton *savebutton; static void on_save_button_toggled (GtkToggleButton *togglebutton, void* user_data) { if(gtk_toggle_button_get_active(togglebutton)) saving = TRUE; else { if(savebutton) { printf("patch: %i channel %i\n",mx44patchNo [midichannel] ,midichannel); strcpy( mx44tmpPatch[midichannel].name,gtk_entry_get_text((GtkEntry*) patchname )); mx44patch[mx44patchNo[midichannel]] = mx44tmpPatch[midichannel]; } saving = FALSE; } savebutton = togglebutton; } static void on_esc_save_button_pressed (GtkButton *button, void* user_data) { GtkToggleButton *sb = savebutton; savebutton = 0; if(sb) gtk_toggle_button_set_active(sb,FALSE); } static void on_monobutton_toggled (GtkToggleButton *togglebutton, void* user_data) { mx44->monomode[midichannel] = gtk_toggle_button_get_active(togglebutton); } static int on_ch_combo( GtkComboBox *combo, void* user_data) { midichannel = gtk_combo_box_get_active(combo); set_widgets(mx44tmpPatch,midichannel,mx44patchNo[midichannel]); newpatch.number = mx44->patchNo[midichannel]; return 0; } static GtkWidget* create_window (int unused) { GtkWidget *frame,*basetable = 0; char *name; // char *win_label[]={"Mx44:1","Mx44:2","Mx44:3","Mx44:4",NULL}; wn = 0; name = name_n(); ed.window = gtk_window_new (GTK_WINDOW_TOPLEVEL); window1=ed.window; gtk_widget_set_name (ed.window, name); gtk_object_set_data (GTK_OBJECT (ed.window), name, ed.window); gtk_container_set_border_width (GTK_CONTAINER (ed.window), 2); gtk_window_set_title (GTK_WINDOW (ed.window), "Mx44"); g_signal_connect (ed.window, "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); { GtkWidget *patch_table,*fx_table; void *bank_combo; void *patch_combo; GtkWidget *save_button; GtkWidget *esc_save_button; GtkWidget *ch_combo; GSList *patchgroup_group = NULL; GtkTooltips *tooltips; tooltips = gtk_tooltips_new (); basetable = gtk_table_new (3, 4, FALSE); gtk_widget_ref (basetable); gtk_widget_show(basetable); patch_table = gtk_table_new (1, 67, TRUE); gtk_widget_ref (patch_table); gtk_object_set_data_full (GTK_OBJECT (window1), "patch_table", patch_table, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (patch_table); gtk_table_attach (GTK_TABLE (basetable), patch_table, 0,2, 1, 2, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_FILL), 0, 0); patch_group_1 = gtk_radio_button_new (patchgroup_group); patchgroup_group = gtk_radio_button_group (GTK_RADIO_BUTTON (patch_group_1)); gtk_widget_ref (patch_group_1); gtk_object_set_data_full (GTK_OBJECT (window1), "patch_group_1", patch_group_1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (patch_group_1); gtk_table_attach (GTK_TABLE (patch_table), patch_group_1, 1, 3, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_tooltips_set_tip (tooltips, patch_group_1, "patch group 1", NULL); patch_group_2 = gtk_radio_button_new (patchgroup_group); patchgroup_group = gtk_radio_button_group (GTK_RADIO_BUTTON (patch_group_2)); gtk_widget_ref (patch_group_2); gtk_object_set_data_full (GTK_OBJECT (window1), "patch_group_2", patch_group_2, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (patch_group_2); gtk_table_attach (GTK_TABLE (patch_table), patch_group_2, 3, 5, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_tooltips_set_tip (tooltips, patch_group_2, "patch group 2", NULL); bank_combo = gtk_combo_box_new_text (); gtk_widget_ref (bank_combo); gtk_object_set_data_full (GTK_OBJECT (window1), "bank_combo", bank_combo, (GtkDestroyNotify) gtk_widget_unref); gtk_tooltips_set_tip (tooltips, bank_combo, "bank selection", NULL); gtk_widget_show (bank_combo); gtk_table_attach (GTK_TABLE (patch_table), bank_combo, 5, 9, 0, 1, (GtkAttachOptions) (GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); //gtk_widget_set_usize (bank_combo, 45, 25); //gtk_container_set_border_width (GTK_CONTAINER (bank_combo), 5); GTK_WIDGET_SET_FLAGS (bank_combo, GTK_CAN_FOCUS); gtk_combo_box_append_text (GTK_COMBO_BOX (bank_combo), "A"); gtk_combo_box_append_text (GTK_COMBO_BOX (bank_combo), "B"); gtk_combo_box_append_text (GTK_COMBO_BOX (bank_combo), "C"); gtk_combo_box_append_text (GTK_COMBO_BOX (bank_combo), "D"); gtk_combo_box_append_text (GTK_COMBO_BOX (bank_combo), "E"); gtk_combo_box_append_text (GTK_COMBO_BOX (bank_combo), "F"); gtk_combo_box_append_text (GTK_COMBO_BOX (bank_combo), "G"); gtk_combo_box_append_text (GTK_COMBO_BOX (bank_combo), "H"); gtk_combo_box_set_active (GTK_COMBO_BOX (bank_combo), 0); bank_entry = bank_combo; patch_combo = gtk_combo_box_new_text (); gtk_widget_ref (patch_combo); gtk_object_set_data_full (GTK_OBJECT (window1), "patch_combo", patch_combo, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (patch_combo); gtk_table_attach (GTK_TABLE (patch_table), patch_combo, 9, 13, 0, 1, (GtkAttachOptions) (GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); gtk_combo_box_append_text (GTK_COMBO_BOX (patch_combo), "1"); gtk_combo_box_append_text (GTK_COMBO_BOX (patch_combo), "2"); gtk_combo_box_append_text (GTK_COMBO_BOX (patch_combo), "3"); gtk_combo_box_append_text (GTK_COMBO_BOX (patch_combo), "4"); gtk_combo_box_append_text (GTK_COMBO_BOX (patch_combo), "5"); gtk_combo_box_append_text (GTK_COMBO_BOX (patch_combo), "6"); gtk_combo_box_append_text (GTK_COMBO_BOX (patch_combo), "7"); gtk_combo_box_append_text (GTK_COMBO_BOX (patch_combo), "8"); gtk_combo_box_set_active (GTK_COMBO_BOX (patch_combo), 0); patch_entry = patch_combo; //gtk_tooltips_set_tip (tooltips, patch_combo, "patch selection", NULL); patchname = gtk_entry_new_with_max_length (31); gtk_widget_ref (patchname); gtk_object_set_data_full (GTK_OBJECT (window1), "patchname", patchname, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (patchname); gtk_table_attach (GTK_TABLE (patch_table), patchname, 13, 27, 0, 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 2, 7); save_button = gtk_toggle_button_new_with_label ("SAVE"); gtk_widget_ref (save_button); gtk_object_set_data_full (GTK_OBJECT (window1), "save_button", save_button, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (save_button); gtk_table_attach (GTK_TABLE (patch_table), save_button, 27, 31, 0, 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_tooltips_set_tip (tooltips, save_button, "select patch to save in, then release button", NULL); /* FIXME! ed.delay_table = mk_delay_table(); gtk_table_attach (GTK_TABLE (patch_table), ed.delay_table, 0, 8, 1, 2, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 2, 7); */ esc_save_button = gtk_button_new_with_label ("Esc"); gtk_widget_ref (esc_save_button); gtk_object_set_data_full (GTK_OBJECT (window1), "esc_save_button", esc_save_button, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (esc_save_button); gtk_table_attach (GTK_TABLE (patch_table), esc_save_button, 31, 34, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_tooltips_set_tip (tooltips, esc_save_button, "cancel save procedure", NULL); //-- ed.common_oplabel = tab_label(ed.window, "Mx44"); gtk_label_set_justify (GTK_LABEL (ed.common_oplabel), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment (GTK_MISC (ed.common_oplabel), 0, 0.5); gtk_widget_set_size_request (ed.common_oplabel ,20, -1); gtk_table_attach (GTK_TABLE (patch_table), ed.common_oplabel, 36,39, 0, 1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_FILL), 0, 0); gtk_widget_show(ed.common_oplabel); ed.common_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (NULL), 1, 2); gtk_widget_ref(ed.common_spinbutton); gtk_spin_button_set_numeric ((GtkSpinButton*)ed.common_spinbutton,1 ); gtk_entry_set_alignment ((GtkEntry*)ed.common_spinbutton,1 ); gtk_widget_set_size_request (ed.common_spinbutton ,50, -1); gtk_widget_show (ed.common_spinbutton); gtk_table_attach (GTK_TABLE (patch_table), ed.common_spinbutton, 39, 44, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); ed.common_spinlabel = tab_label(ed.window, " (C) Jens M Andreasen, 2005"); gtk_label_set_justify (GTK_LABEL (ed.common_spinlabel), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment (GTK_MISC (ed.common_spinlabel), 0, 0.5); gtk_widget_set_size_request (ed.common_spinlabel ,60, -1); gtk_table_attach (GTK_TABLE (patch_table), ed.common_spinlabel, 44,59, 0, 1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_FILL), 0, 0); gtk_widget_show(ed.common_spinlabel); // ---- ed.monobutton = gtk_toggle_button_new_with_label ("M"); gtk_widget_ref (ed.monobutton); gtk_object_set_data_full (GTK_OBJECT (window1), "monobutton", ed.monobutton, (GtkDestroyNotify) gtk_widget_unref); #if 0 gtk_widget_show (ed.monobutton); gtk_table_attach (GTK_TABLE (patch_table), ed.monobutton, 58, 60, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_tooltips_set_tip (tooltips, ed.monobutton, "midi mono mode", NULL); gtk_widget_modify_text(ed.monobutton,GTK_STATE_PRELIGHT,&col); #endif // ---- ch_combo = gtk_combo_box_new_text (); gtk_widget_ref (ch_combo); gtk_object_set_data_full (GTK_OBJECT (window1), "ch_combo", ch_combo, (GtkDestroyNotify) gtk_widget_unref); //gtk_tooltips_set_tip (tooltips, ch_combo, "bank selection", NULL); gtk_widget_show (ch_combo); gtk_table_attach (GTK_TABLE (patch_table), ch_combo, 61, 67, 0, 1, (GtkAttachOptions) (GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); //gtk_widget_set_usize (bank_combo, 45, 25); //gtk_container_set_border_width (GTK_CONTAINER (ch_combo), 5); GTK_WIDGET_SET_FLAGS (ch_combo, GTK_CAN_FOCUS); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch 1"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch 2"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch 3"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch 4"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch 5"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch 6"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch 7"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch 8"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch 9"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch10"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch11"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch12"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch13"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch14"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch15"); gtk_combo_box_append_text (GTK_COMBO_BOX (ch_combo), "Ch16"); gtk_combo_box_set_active (GTK_COMBO_BOX (ch_combo), 0); g_signal_connect (ch_combo, "changed", GTK_SIGNAL_FUNC (on_ch_combo),NULL); g_signal_connect (bank_combo, "changed", GTK_SIGNAL_FUNC (on_bank_entry_changed), NULL); g_signal_connect (patch_entry, "changed", GTK_SIGNAL_FUNC (on_patch_entry_changed), NULL); g_signal_connect (save_button, "toggled", GTK_SIGNAL_FUNC (on_save_button_toggled), NULL); g_signal_connect (esc_save_button, "clicked", GTK_SIGNAL_FUNC (on_esc_save_button_pressed), NULL); g_signal_connect (ed.monobutton, "toggled", GTK_SIGNAL_FUNC (on_monobutton_toggled), NULL); g_signal_connect (patch_group_1, "pressed", GTK_SIGNAL_FUNC (on_patch_group_1_clicked), NULL); g_signal_connect (patch_group_2, "pressed", GTK_SIGNAL_FUNC (on_patch_group_2_clicked), NULL); gtk_widget_grab_focus((GtkWidget*)ed.common_spinbutton); { GtkWidget *widget; widget = gtk_frame_new(NULL); gtk_frame_set_shadow_type( GTK_FRAME(widget), GTK_SHADOW_NONE); gtk_container_set_border_width (GTK_CONTAINER (widget), 2); gtk_widget_show(widget); //gtk_container_set_border_width (GTK_CONTAINER (ed.table[ed.op]), 6); fx_table = gtk_table_new (35,6, TRUE); gtk_widget_ref (fx_table); gtk_object_set_data_full (GTK_OBJECT (window1), "fx_table", fx_table, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (fx_table); gtk_container_set_border_width (GTK_CONTAINER (fx_table), 3); gtk_container_add (GTK_CONTAINER (widget), fx_table); gtk_table_attach (GTK_TABLE (basetable), widget, 2,3, 0, 3, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0); #if 0 label(fx_table,0,0,4,"Delay"); widget = scale(fx_table, 0,1,1,4, 0,100,-1,DELAY,0," // delay time"); gtk_widget_set_size_request (widget, 18, 18); scale(fx_table, 1,1,1,4, 0,100,-1,DELAY,1," // delay spread"); scale(fx_table, 2,1,1,4, 0,100,-1,DELAY,2," // delay feedback"); scale(fx_table, 3,1,1,4, 0,100,-1,DELAY,3," // delay LFO modulation"); scale(fx_table, 5,1,1,4, 0,100,-1,DELAY,4," // delay amount"); label(fx_table,0,7,4,"Overdrive"); widget=scale(fx_table, 1,8,4,1, 0,100,-1,DIST,0," // overdrive / distortion"); gtk_widget_set_size_request (widget, 18, 18); #else { int i; for (i=0;i < 7;++i) line(fx_table,1,1+i,4,1); } #endif label(fx_table,0,10,4,"LFO"); ed.lfo[0] = scale(fx_table, 2,15,1,4, 0,100,-1,LFO,0," LFO rate 1"); ed.lfo[1] = scale(fx_table, 3,15,1,4, 0,100,-1,LFO,1," LFO rate 2"); ed.lfo[2] = scale(fx_table, 4,13,1,4, 0,100,-1,LFO,2," LFO amount 1"); ed.lfo[3] = scale(fx_table, 5,12,1,4, 0,100,-1,LFO,3," LFO amount 2"); ed.lfo[4] = scale(fx_table, 0,12,5,1, 0,100,-1,LFO,4," LFO time 1"); ed.lfo[5] = scale(fx_table, 1,11,5,1, 0,100,-1,LFO,5," LFO time 2"); label(fx_table,1,13,3," Sync"); label(fx_table,1,14,3," Wheel"); //------------- widget = gtk_check_button_new(); gtk_widget_ref(widget); gtk_object_set_data_full (GTK_OBJECT (window1), "loopbutton", widget, (GtkDestroyNotify) gtk_widget_unref); g_signal_connect (widget, "clicked", GTK_SIGNAL_FUNC (on_lfo_button_clicked), NULL); gtk_widget_show(widget); gtk_table_attach (GTK_TABLE (fx_table), widget, 0, 1, 13, 14, (GtkAttachOptions) (GTK_SHRINK), (GtkAttachOptions) (GTK_SHRINK), 0, 0); gtk_widget_set_size_request (widget, 18, 18); ed.lfo_button[0] = widget; //------------- widget = gtk_check_button_new(); gtk_widget_ref(widget); gtk_object_set_data_full (GTK_OBJECT (window1), "touchbutton", widget, (GtkDestroyNotify) gtk_widget_unref); /* g_signal_connect (ed.wheelbutton[ed.op][0], "clicked", GTK_SIGNAL_FUNC (on_button_clicked), (NULL+(WHEELBUTTON<<4))+ed.op); */ g_signal_connect (widget, "clicked", GTK_SIGNAL_FUNC (on_lfo_button_clicked), NULL+1); gtk_widget_show(widget); gtk_table_attach (GTK_TABLE (fx_table), widget, 0, 1, 14, 15, (GtkAttachOptions) (GTK_SHRINK), (GtkAttachOptions) (GTK_SHRINK), 0, 0); gtk_widget_set_size_request (widget, 18, 18); ed.lfo_button[1] = widget; //--------------- #if 0 label(fx_table,0,22,4,"Arpeggio ..."); label(fx_table,0,28,4,"Key Zone ..."); #else { int i; for (i=0;i < 12;++i) line(fx_table,1,22+i,4,1); } #endif } } gtk_container_add (GTK_CONTAINER (ed.window), basetable); for(ed.op = 0;op_label[ed.op];++ed.op) { name = name_n(); ed.table[ed.op] = gtk_table_new (15, 22, TRUE); gtk_widget_set_name (ed.table[ed.op], name); gtk_widget_ref (ed.table[ed.op]); gtk_object_set_data_full (GTK_OBJECT (ed.window), name, ed.table[ed.op], (GtkDestroyNotify) gtk_widget_unref); mk_envelope(ed.table[ed.op],0,0,ed.op,"Envelope time / level"); label(ed.table[ed.op],13,7,3," Wheel"); ed.wheelbutton[ed.op][0] = gtk_check_button_new(); gtk_widget_ref(ed.wheelbutton[ed.op][0]); gtk_object_set_data_full (GTK_OBJECT (window1), "wheelbutton", ed.wheelbutton[ed.op][0] , (GtkDestroyNotify) gtk_widget_unref); g_signal_connect (ed.wheelbutton[ed.op][0], "clicked", GTK_SIGNAL_FUNC (on_button_clicked), (NULL+(WHEELBUTTON<<4))+ed.op); gtk_widget_show(ed.wheelbutton[ed.op][0]); gtk_table_attach (GTK_TABLE (ed.table[ed.op]), ed.wheelbutton[ed.op][0], 12, 13, 7, 8, (GtkAttachOptions) (GTK_SHRINK), (GtkAttachOptions) (GTK_SHRINK), 0, 0); gtk_widget_set_size_request (ed.wheelbutton[ed.op][0], 18, 18); label(ed.table[ed.op],0,1,4,"Keybias"); ed.breakpoint[ed.op] = scale(ed.table[ed.op], 0,0,5,1, 0,128,ed.op,BIAS,0, " bias breakpoint"); ed.keybias[ed.op][0] = scale(ed.table[ed.op], 0,2,1,4, -100,0,ed.op,BIAS,1," bias low"); ed.keybias[ed.op][1] = scale(ed.table[ed.op], 1,2,1,4, -100,0,ed.op,BIAS,2," bias high"); label(ed.table[ed.op],0,14,2,"Phase"); ed.phase[ed.op][0] = scale(ed.table[ed.op], 2,11,1,4, 0,100,ed.op,MISC,0," phase init"); ed.phase[ed.op][1] = scale(ed.table[ed.op], 3,11,1,4, 0,100,ed.op,MISC,1," phase velocity / keyfollow"); label(ed.table[ed.op],6,14,3,"Velocity"); line(ed.table[ed.op],4,12,2,1); ed.velocity[ed.op] = scale(ed.table[ed.op], 4,10,2,5, -100,100,ed.op,MISC,2," velocity sensitivity"); label(ed.table[ed.op],12,13,2,"Out"); ed.mix[ed.op][0] = scale(ed.table[ed.op], 13,9,2,5, 0,100,ed.op,MISC,3," output volume"); ed.mix[ed.op][1] = scale(ed.table[ed.op], 12,14,4,1, -180,180,ed.op,MISC,4," output balance"); { int x; for(x=0;x<8;++x) { ed.od[ed.op][x] = gtk_radio_button_new ((void*)ed.od_group[ed.op]); ed.od_group[ed.op] = (void*)gtk_radio_button_group (GTK_RADIO_BUTTON (ed.od[ed.op][x])); gtk_widget_ref (ed.od[ed.op][x]); gtk_object_set_data_full (GTK_OBJECT (window1), "wawe 0", ed.od[ed.op][x], (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (ed.od[ed.op][x]); if(x <4) gtk_table_attach (GTK_TABLE (ed.table[ed.op]), ed.od[ed.op][x],x+ 15, x+16, 0, 1, (GtkAttachOptions) (GTK_SHRINK), (GtkAttachOptions) (GTK_SHRINK), 0, 0); else gtk_table_attach (GTK_TABLE (ed.table[ed.op]), ed.od[ed.op][x],x+ 14, x+15, 1, 2, (GtkAttachOptions) (GTK_SHRINK), (GtkAttachOptions) (GTK_SHRINK), 0, 0); gtk_widget_set_size_request (ed.od[ed.op][x], 18, 18); g_signal_connect (ed.od[ed.op][x], "clicked", GTK_SIGNAL_FUNC (on_od_clicked), (NULL+x)+(ed.op<<4)); } ed.wawebutton[ed.op] = gtk_check_button_new(); gtk_widget_ref(ed.wawebutton[ed.op]); gtk_widget_show(ed.wawebutton[ed.op]); gtk_object_set_data_full (GTK_OBJECT (window1), "complex", ed.wawebutton[ed.op] , (GtkDestroyNotify) gtk_widget_unref); gtk_table_attach (GTK_TABLE (ed.table[ed.op]), ed.wawebutton[ed.op] ,20, 21, 0, 1, (GtkAttachOptions) (GTK_SHRINK), (GtkAttachOptions) (GTK_SHRINK), 0, 0); gtk_widget_set_size_request (ed.wawebutton[ed.op], 18, 18); g_signal_connect (ed.wawebutton[ed.op], "clicked", GTK_SIGNAL_FUNC (on_button_clicked), (NULL+(WAWEBUTTON<<4))+ed.op); ed.lowpassbutton[ed.op] = gtk_check_button_new(); gtk_widget_ref(ed.lowpassbutton[ed.op]); gtk_widget_show(ed.lowpassbutton[ed.op]); gtk_object_set_data_full (GTK_OBJECT (window1), "lowpass", ed.lowpassbutton[ed.op] , (GtkDestroyNotify) gtk_widget_unref); gtk_table_attach (GTK_TABLE (ed.table[ed.op]), ed.lowpassbutton[ed.op] ,21, 22, 0, 1, (GtkAttachOptions) (GTK_SHRINK), (GtkAttachOptions) (GTK_SHRINK), 0, 0); gtk_widget_set_size_request (ed.lowpassbutton[ed.op], 18, 18); g_signal_connect (ed.lowpassbutton[ed.op], "clicked", GTK_SIGNAL_FUNC (on_button_clicked), (NULL+(LOWPASSBUTTON<<4))+ed.op); ed.waweshapebutton[ed.op] = gtk_check_button_new(); gtk_widget_ref(ed.waweshapebutton[ed.op]); gtk_widget_show(ed.waweshapebutton[ed.op]); gtk_object_set_data_full (GTK_OBJECT (window1), "waweshape", ed.waweshapebutton[ed.op] , (GtkDestroyNotify) gtk_widget_unref); gtk_table_attach (GTK_TABLE (ed.table[ed.op]), ed.waweshapebutton[ed.op] ,14, 15, 0, 2, (GtkAttachOptions) (GTK_SHRINK), (GtkAttachOptions) (GTK_SHRINK), 0, 0); gtk_widget_set_size_request (ed.waweshapebutton[ed.op], 18, 18); g_signal_connect (ed.waweshapebutton[ed.op], "clicked", GTK_SIGNAL_FUNC (on_button_clicked), (NULL+(WAWESHAPEBUTTON<<4))+ed.op); ed.phasefollowkeybutton[ed.op] = gtk_check_button_new(); gtk_widget_ref(ed.phasefollowkeybutton[ed.op]); gtk_widget_show(ed.phasefollowkeybutton[ed.op]); gtk_object_set_data_full (GTK_OBJECT (window1), "complex", ed.phasefollowkeybutton[ed.op] , (GtkDestroyNotify) gtk_widget_unref); gtk_table_attach (GTK_TABLE (ed.table[ed.op]), ed.phasefollowkeybutton[ed.op] ,3, 4, 10, 11, (GtkAttachOptions) (GTK_SHRINK), (GtkAttachOptions) (GTK_SHRINK), 0, 0); gtk_widget_set_size_request (ed.phasefollowkeybutton[ed.op], 18, 18); g_signal_connect (ed.phasefollowkeybutton[ed.op], "clicked", GTK_SIGNAL_FUNC (on_button_clicked), (NULL+(PHASEFOLLOWKEYBUTTON<<4))+ed.op); ed.magicbutton[ed.op] = gtk_check_button_new(); gtk_widget_ref(ed.magicbutton[ed.op]); gtk_widget_show(ed.magicbutton[ed.op]); gtk_object_set_data_full (GTK_OBJECT (window1), "magic", ed.magicbutton[ed.op] , (GtkDestroyNotify) gtk_widget_unref); gtk_table_attach (GTK_TABLE (ed.table[ed.op]), ed.magicbutton[ed.op] ,21, 22, 2, 3, (GtkAttachOptions) (GTK_SHRINK), (GtkAttachOptions) (GTK_SHRINK), 0, 0); gtk_widget_set_size_request (ed.magicbutton[ed.op], 18, 18); g_signal_connect (ed.magicbutton[ed.op], "clicked", GTK_SIGNAL_FUNC (on_button_clicked), (NULL+(MAGICBUTTON<<4))+ed.op); //label(ed.table[ed.op],15,1,3," Wawe &"); label(ed.table[ed.op],16,2,4," Oscillator"); ed.harmonic[ed.op] = scale(ed.table[ed.op], 16,4,5,2, 0,100,ed.op,FREQ,0," frequency multiplyer"); line(ed.table[ed.op],21,4,1,2); ed.detune[ed.op] = scale(ed.table[ed.op], 21,3,1,4, -100,100,ed.op,FREQ,2," frequency offset"); line(ed.table[ed.op],15,3,1,2); ed.intonation[ed.op][0] = scale(ed.table[ed.op], 15,2,1,4, -100,100,ed.op,FREQ,3," intonation amount"); ed.intonation[ed.op][1] = scale(ed.table[ed.op], 16,3,4,2, 0,100,ed.op,FREQ,4," intonation decay"); } mk_patchbay(ed.table[ed.op],16,7,ed.op,"Modulation"); /* line(ed.table[ed.op],9,15,16,1); ed.spinlabel[ed.op] = label(ed.table[ed.op],13,16,12, " (C) Jens M Andreasen, 2004"); adj = (GtkAdjustment*)gtk_adjustment_new (100, 0, 100, 0.01, 1, 1); ed.spinbutton[ed.op] = gtk_spin_button_new (GTK_ADJUSTMENT ( adj ), 1, 2); gtk_spin_button_set_numeric ((GtkSpinButton*)ed.spinbutton[ed.op],1 ); gtk_entry_set_alignment ((GtkEntry*)ed.spinbutton[ed.op],1 ); name = name_n(); gtk_widget_set_name (ed.spinbutton[ed.op], name); gtk_widget_ref (ed.spinbutton[ed.op]); gtk_object_set_data_full (GTK_OBJECT (ed.window[wn]), name, ed.spinbutton[ed.op], (GtkDestroyNotify) gtk_widget_unref); gtk_widget_set_size_request (ed.spinbutton[ed.op] ,60, -1); gtk_widget_show (ed.spinbutton[ed.op]); gtk_table_attach (GTK_TABLE (ed.table[ed.op]), ed.spinbutton[ed.op], 9, 13, 15, 17, GTK_FILL, 0, 0, 0); */ /* Create a Frame */ frame = gtk_frame_new(NULL); // gtk_container_add(GTK_CONTAINER(notebook), frame); switch(ed.op) { case 0: gtk_table_attach (GTK_TABLE (basetable), frame, 0,1, 0,1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0); break; case 1: gtk_table_attach (GTK_TABLE (basetable), frame, 1,2, 0,1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0); break; case 2: gtk_table_attach (GTK_TABLE (basetable), frame, 0,1 , 2,3, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0); break; case 3: gtk_table_attach (GTK_TABLE (basetable), frame, 1,2, 2,3, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0); } /* Set the style of the frame */ gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN); gtk_container_set_border_width (GTK_CONTAINER (frame), 2); gtk_widget_show(frame); gtk_container_set_border_width (GTK_CONTAINER (ed.table[ed.op]), 6); gtk_container_add (GTK_CONTAINER (frame), ed.table[ed.op]); gtk_widget_show (ed.table[ed.op]); } //set_widgets(mx44tmpPatch,midichannel,mx44patchNo[midichannel]); gtk_widget_show(window1); return NULL; } int main_interface (int argc, char *argv[]) { gtk_set_locale (); gtk_rc_add_default_file (widget_theme); gtk_init (&argc, &argv); create_window (0); set_widgets(mx44tmpPatch,0,mx44patchNo[0]); g_timeout_add (50, check_patch, NULL); gtk_main (); return 0; } //main (int argc, char *argv[]) {return main_interface(argc,argv);} Mx44/junk.c0000644000000000000000000000052710240366130011422 0ustar rootroot#include inline static short mx41_psin(short n) { short x = n ^ 0x8000; // x is shifted 180 degrees n = (n * x) >> 13; // take the halfwawe and ... return n ^ (x >> 15); // negate the expression if x is negative } main(void) { int i; for(i= 0 ; i < 0x0FFFF; i += 256) printf("%d\n",mx41_psin(i) ); return 0; } Mx44/main.c0000644000076400007640000002654010253545334011405 0ustar jensjens/* * This software is released under GPL. If you don't know what that is * immediately point your webbrowser to http://www.gnu.org and read * all about it. * * The short version: You can modify the sources for your own purposes * but you must include the new source if you distribute a derived work. * * (C) 2002, 2003, 2004, 2005 Jens M Andreasen * * * * ( * ) * c[] * */ #define SAMPLERATE 48000 //#define SAMPLERATE 44100 #define VOICEPOOL 48 int WITH_JACK; int WITH_ALSA = 0; #include "mx44.h" #include "old/mmx4.h" // Convert from old to new format // #define cnv(element) mx44->element = mx4->element static void mx44cnv(Mx44patch *mx44,mmx4patch_t *mx4) { int i; for(i = 0;i<4;++i) { int j; /************************ int harmonic[4]; int detune[4]; short velocityfollow[4]; unsigned char od[4]; unsigned char button[4]; int velocity[4]; int breakpoint[4]; *************************/ cnv(harmonic[i]); cnv(detune[i]); cnv(velocityfollow[i]); cnv(od[i]); cnv(button[i]); cnv(velocity[i]); cnv(breakpoint[i]); for(j=0;j<4;++j) { /*************** int pm[4][4]; int am[4][4]; ****************/ cnv(pm[i][j]); cnv(am[i][j]); } for(j=0;j<8;++j) { /********************* int env_level[4][8]; int env_time[4][8]; **********************/ cnv(env_level[i][j]); cnv(env_time[i][j]); } for(j=0;j<2;++j) { /********************** int keybias[4][2]; int keyfollow[4][2]; short intonation[4][2]; int phase[4][2]; int mix[4][2]; **********************/ cnv(keybias[i][j]); cnv(keyfollow[i][j]); cnv(intonation[i][j]); cnv(phase[i][j]); cnv(mix[i][j]); } } /*************** char name[32]; ****************/ for(i=0;i<32;++i) cnv(name[i]); } #undef cnv #include #include #include #include #include #include #include #include #include #include #include #include #include int mx44running; /* Setting up audio and realtime scheduler: */ static int _argc; static char **_argv; static struct { char * path; int speed; int format; int is_stereo; int device; int bufsize; struct audio_buf_info info; }audio; static struct { char * path; int device; unsigned char buffer[128]; unsigned char data[4]; // count, status, data1, data2 }midi; int setup_audio(char *name,int jack,int oss_midi) { /** * We would like realtime performance * */ struct sched_param schp; memset(&schp, 0, sizeof(schp)); schp.sched_priority = sched_get_priority_max(SCHED_RR); // printf("AudioPriority level: %d\n",schp.sched_priority); if (sched_setscheduler(0, SCHED_RR, &schp) != 0) { fprintf(stderr, "\n Can't run in realtime! Please do (as 'root'): \n" " chown root.root %s && chmod 4711 %s\n\n",name,name); } /** * Give back ownership to the real user, so that he can read * created files, and so that we don't fuck up the machine while * posing as root. * */ setreuid(getuid(), getuid()); midi.path = "/dev/midi"; //audio.path = "/dev/dsp"; audio.path = "/dev/dsp1"; if(!jack) { /** Setting up the soundcard for CD-HiFidelity Stereo or better * */ audio.speed = SAMPLERATE; audio.format = AFMT_S16_LE; audio.is_stereo = TRUE; // 3 buffers of 256 bytes == 3 * 64 (16bit) stereo samples // 0x0002 buffers == n - 1 // 0008 bytes == log2(number of bytes in buffer), 2^8 == 256 == 64 stereo samples; audio.bufsize = 0x00010007; //audio.bufsize = 0x00030008; audio.device=open(audio.path, O_WRONLY); if (audio.device == -1) { perror("Opening audio device"); audio.path = "/dev/dsp"; audio.device=open(audio.path, O_WRONLY); if (audio.device == -1) { perror("Opening audio device"); return 1; } } else midi.path = "/dev/midi1"; if (ioctl(audio.device, SNDCTL_DSP_SETFRAGMENT, &audio.bufsize)) perror("DSP_SETFRAGMENT"); if (ioctl(audio.device, SNDCTL_DSP_SETFMT, &audio.format) == -1) { perror("DSP_SETFMT"); return 2; } if (ioctl(audio.device, SNDCTL_DSP_STEREO, &audio.is_stereo) == -1) { perror("DSP_STEREO"); return 3; } if (ioctl(audio.device, SNDCTL_DSP_SPEED, &audio.speed) == -1) { perror("DSP_SPEED"); return 4; } if (ioctl(audio.device, SNDCTL_DSP_GETOSPACE, &audio.info) == -1) { perror("DSP_GETOSPACE"); return 5; } fprintf(stderr, "Blocksize: %d\n" "Blocks : %d\n" "Bytes : %d\n" ,audio.info.fragsize,audio.info.fragstotal,audio.info.bytes); fprintf(stderr, "\nLatency : %.3f ms\n" "\nSamplerate: %d\n\n", ((1000*audio.info.bytes)/4)/(double)audio.speed,audio.speed); } if(oss_midi) { //midi.path = "/dev/sound/mx4"; if((midi.device = open(midi.path, O_RDONLY|O_NONBLOCK,0)) == -1) { perror(midi.path); //return 6; WITH_ALSA = TRUE; } } return 0; } extern void setwidgets(Mx44patch *patch,int channel,int patchNumber); extern int main_interface (int argc, char *argv[]); void * interface(void* t_arg) { setreuid(getuid(), getuid()); main_interface(_argc,_argv); mx44running = FALSE; return NULL; } Mx44state * mx44; Mx44patch *mx44patch; char *mx44patchNo; Mx44patch *mx44tmpPatch; int patch_fd; void save_state(void) { if(patch_fd > 0) { int count; lseek(patch_fd,0,SEEK_SET); count = write(patch_fd,mx44->patch, sizeof(mx44->patch)); count += write(patch_fd,mx44->tmpPatch, sizeof(mx44->tmpPatch)); count += write(patch_fd,mx44->patchNo, sizeof(mx44->patchNo)); count += write(patch_fd,mx44->monomode, sizeof(mx44->monomode)); if(count == sizeof(mx44->patch) + sizeof(mx44->tmpPatch) + sizeof(mx44->patchNo) + sizeof(mx44->monomode)) puts("\nVoice data saved\n"); else puts("\nVoice data not saved (?)\n"); } fprintf(stderr,"Thankyou for using Mx4!\n"); } int main(int argc,char **argv) { short outbuf[2][OUTBUF];// s=0; unsigned char ev[128]; // midi events pthread_t i_thread; // graphic interface pthread_attr_t i_thread_attr; unsigned int i = 0; int isGraphic = 0; int voicepool = VOICEPOOL; if(argc > 1) { voicepool = atoi(argv[argc -1]); if(voicepool == 0) voicepool = VOICEPOOL; } /* * mmx_ok() seems to be broken with gcc 3.x ? * if(mmx_ok()) puts("MMX OK!"); else puts("MMX not available."), exit(0); * */ mx44 = mx44_new(voicepool,"mx44patch"); if(!(WITH_JACK = mx44->samplerate)) mx44->samplerate=SAMPLERATE; printf("\nsizeof %d voices: %d, %d keyboards: %d, 128 patches: %d\n", voicepool, sizeof(Mx44voice) * voicepool, MIDICHANNELS, sizeof(Mx44state) - sizeof(Mx44patch) * 128, sizeof(Mx44patch) * 128); /* FIXME: Globals for the userinterface */ mx44patch = mx44->patch; mx44patchNo = mx44->patchNo; mx44tmpPatch= mx44->tmpPatch; patch_fd = open("mx41patch",O_RDWR|O_CREAT,0666); if(patch_fd > 0) { int count = read(patch_fd,mx44->patch, sizeof(mx44->patch) + sizeof(mx44->tmpPatch) + sizeof(mx44->patchNo) + sizeof(mx44->monomode)); if(count > 0) puts("\nVoice data loaded\n"); else // Try to convert old patches { mmx4patch_t legacy[128]; int tmp_fd = open("mx4patch",O_RDONLY,0666); puts("\n Voice data (mx44upper/lower) not available\n Trying to find old patches"); if(tmp_fd > 0) { int count = read(tmp_fd,legacy,sizeof(mmx4patch_t)*128); if(count > 0) { int i; puts(" Found! Converting old patches to new ...\n"); for(i=0;i<128;++i) mx44cnv(mx44->patch + i,legacy + i); for(i=0;i < MIDICHANNELS;++i) { mx44->tmpPatch[i] = mx44->patch[0]; mx44->patchNo[i] = 0; } } else puts(" Not found! Sorry :(\n"); close(tmp_fd); } } atexit(save_state); } mx44_reset(mx44,440.0, mx44->samplerate); mx44running = 1; if(setup_audio(argv[0],WITH_JACK,1)) //!(getopt(argc,argv,"o") == 'o'))) { mx44running = 0; exit(1); } if(getenv("DISPLAY")) { _argc = argc; _argv = argv; pthread_attr_init(&i_thread_attr); pthread_attr_setinheritsched(&i_thread_attr,PTHREAD_EXPLICIT_SCHED); pthread_create(&i_thread,&i_thread_attr,interface,NULL); isGraphic = mx44->isGraphic = 1; } // Running from Jack if(WITH_JACK && WITH_ALSA) { while(mx44running) sleep(1); exit(0); } // ------------- puts("running OK!"); if(!WITH_ALSA) while(read(midi.device,ev,1)>0) // flush midi in ; while(mx44running) { if(WITH_JACK) usleep(500); { int n = 0; if(!WITH_ALSA) for(n = 0; read(midi.device, ev+n, 1) > 0 && n < sizeof(ev); ++n) ; if(n) { int b = 0; while(midi.data[0] < 3 && b < n ) { switch(midi.data[0]) { case 0: if(ev[b] > 127) // new status byte midi.data[midi.data[0] = 1] = ev[b++]; else // running status, first data midi.data[midi.data[0] = 2] = ev[b++]; break; case 1: if(ev[b] < 128) // first data byte midi.data[midi.data[0] = 2] = ev[b++]; else // unexpected new status byte midi.data[midi.data[0] = 1] = ev[b++]; break; case 2: if(ev[b] < 128) // second data byte midi.data[midi.data[0] = 3] = ev[b++]; else // unexpected new status byte midi.data[midi.data[0] = 1] = ev[b++]; break; } switch(midi.data[1] & 0x0F0) { // 2byte messages case 0x0C0: // program change if(midi.data[0] == 2) { mx44_pgmchange(mx44,midi.data[1],midi.data[2]); if(isGraphic) setwidgets(mx44tmpPatch,midi.data[1] & 0x0F,midi.data[2]); midi.data[0] =0; } break; case 0x0D0: // channel pressure if(midi.data[0] == 2) { mx44_chanpress(mx44,midi.data[1],midi.data[2]); midi.data[0] =0; } break; case 0x0F0: // SysEX etc midi.data[0] = 0; // ignore data break; default: // assume 3byte message if(midi.data[0] == 3) { pthread_mutex_lock(&mx44->busy); if((midi.data[1]&0x0F0) == 0x090) mx44_noteon(mx44,midi.data[1], midi.data[2], midi.data[3]); else if((midi.data[1]&0x0F0) == 0x0E0 ) mx44_pitchbend(mx44,midi.data[1],midi.data[2] ,midi.data[3]); else if((midi.data[1]&0x0F0) == 0x080 ) mx44_noteoff(mx44,midi.data[1],midi.data[2] ,midi.data[3]); else if((midi.data[1]&0x0F0) == 0x0B0 ) mx44_control(mx44,midi.data[1],midi.data[2] ,midi.data[3]); else printf("midi: %i | %i %i %i\n", midi.data[0],midi.data[1],midi.data[2],midi.data[3]); midi.data[0] =0; pthread_mutex_unlock(&mx44->busy); sched_yield(); } } } } } if(!WITH_JACK) { bzero(outbuf[1&i], 2 * OUTBUF); mx44_play(mx44,outbuf[1&i]); write(audio.device, outbuf[1&i], sizeof(*outbuf)); } i++; } return 0; } Mx44/mx44.c0000644000076400007640000015132710254255317011257 0ustar jensjens/* mx44.c * * This software is released under GPL. If you don't know what that is * immediately point your webbrowser to http://www.gnu.org and read * all about it. * * The short version: You can modify the sources for your own purposes * but you must include the new source if you distribute a derived work. * * (C) 2002, 2003, 2004, 2005 Jens M Andreasen * * * * ( * ) * c[] * * */ #include "mx44.h" #include #include #include #include #include #include #include ////////////////////////////////////////////////////////////////// // // JACK interface adapted from jack_simple_client.c // ------------------------------------------------ // #include // jack_port_t *port_L; jack_port_t *port_R; int mx44_jack_process (jack_nframes_t nframes, void *arg) { // // The process callback for this JACK application. // It is called by JACK at the appropriate times. // static short mx44buf[SAMPLES * 2]; static int current = SAMPLES * 2; static int called = 0; Mx44state *mx44 = arg; float *left = (float *) jack_port_get_buffer (port_L, nframes); float *right = (float *) jack_port_get_buffer (port_R, nframes); float ftmp; int n = 0; while(n < nframes) { if(current == SAMPLES * 2) { bzero(mx44buf, sizeof(mx44buf)); mx44_play(mx44,mx44buf); current = 0; } ftmp = mx44buf[current++]; *right = ldexpf(ftmp,-16); ++right; ftmp = mx44buf[current++]; *left = ldexpf(ftmp,-16); ++left; ++n; } if(!called) printf("\n Jack nframes: %d\n\n",nframes); called = 1; return 0; } void mx44_jack_shutdown (void *arg) { // // This is the shutdown callback for this JACK application. // It is called by JACK if the server ever shuts down or // decides to disconnect the client. // exit (1); } int mx44_jack_init(Mx44state *mx44) { // // This is the intializer that will set up ports // and callbacks. Returns samplerate on success. // jack_client_t *client; const char **ports; int samplerate; // try to become a client of the JACK server if ((client = jack_client_new ("Mx44")) == 0) { fprintf (stderr, "JACK server NOT RUNNING?\n"); return 0; } // tell the JACK server to call `process()' whenever // there is work to be done. jack_set_process_callback (client, mx44_jack_process, mx44); // tell the JACK server to call `jack_shutdown()' if // it ever shuts down, either entirely, or if it // just decides to stop calling us. jack_on_shutdown (client, mx44_jack_shutdown, mx44); // display the current sample rate. printf ("engine sample rate: %" PRIu32 "\n", samplerate = jack_get_sample_rate (client)); // create two ports port_L = jack_port_register (client, "Mx44_L", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); port_R = jack_port_register (client, "Mx44_R", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); // tell the JACK server that we are ready to roll if (jack_activate (client)) { fprintf (stderr, "cannot activate client \n"); return 0; } else fprintf (stderr, "client activated \n"); puts("\nCapture ports:"); if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsOutput)) == NULL) { fprintf(stderr, "Cannot find any physical capture ports\n"); } else { int i; for(i=0;ports[i];++i) puts(ports[i]); free (ports); } puts("\nPlayback ports:"); if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsInput)) == NULL) { fprintf(stderr, "Cannot find any physical playback ports\n"); } else { int i; for(i=0;ports[i];++i) puts(ports[i]); if(i>0) if ( jack_connect (client, jack_port_name (port_L), ports[0])) fprintf (stderr, "cannot connect output port_L\n"); if(i>1) if (jack_connect (client, jack_port_name (port_R), ports[1])) fprintf (stderr, "cannot connect output port_R\n"); free (ports); } return samplerate; } // // // EOF JACK interface //////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // // ALSA interface adapted from seqdemo.c by Matthias Nagorni // --------------------------------------------------------- // #include // // static snd_seq_t *open_seq(char* client_name) { snd_seq_t *seq_handle; int portid; if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, 0) < 0) { fprintf(stderr, "Error opening ALSA sequencer.\n"); return NULL; } snd_seq_set_client_name(seq_handle, client_name); if ((portid = snd_seq_create_simple_port(seq_handle, client_name, SND_SEQ_PORT_CAP_WRITE |SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "Error creating sequencer port.\n"); return NULL; } return(seq_handle); } // // For some odd reason pthread_yield is not found in pthread.h, // but still exist in the library: // void pthread_yield(); // static void *mx44_midi_thread(void* thread_argument) // was main() { Mx44state *mx44 = thread_argument; struct pollfd *pfd = NULL; int npfd; snd_seq_t *seq_handle; if(!(seq_handle = open_seq("Mx44"))) exit(1); // FIXME npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN); pfd = malloc(npfd * sizeof(struct pollfd)); pthread_cleanup_push(free,pfd); snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN); for(;;) { if (poll(pfd, npfd, 100000) > 0) { snd_seq_event_t *ev; pthread_mutex_lock(&mx44->busy); do { // snd_seq_event_input(seq_handle, &ev); // //*///////////////////////////////////////////////////*// switch (ev->type) { case SND_SEQ_EVENT_CONTROLLER: mx44_control( mx44, ev->data.control.channel, ev->data.control.param, ev->data.control.value ); break; case SND_SEQ_EVENT_PITCHBEND: mx44_pitchbend( mx44, ev->data.control.channel, ev->data.control.value, 0x3F ); break; case SND_SEQ_EVENT_NOTEON: mx44_noteon( mx44, ev->data.note.channel, ev->data.note.note, ev->data.note.velocity ); break; case SND_SEQ_EVENT_NOTEOFF: mx44_noteoff( mx44, ev->data.note.channel, ev->data.note.note, ev->data.note.velocity ); break; case SND_SEQ_EVENT_PORT_SUBSCRIBED: fprintf(stderr,"Port subscribed: sender: %d:%d dest: %d:%d\n", ev->data.connect.sender.client, ev->data.connect.sender.port, ev->data.connect.dest.client, ev->data.connect.dest.port); break; case SND_SEQ_EVENT_PGMCHANGE: mx44_pgmchange( mx44, ev->data.control.channel, ev->data.control.value ); if(mx44->isGraphic) setwidgets(mx44->tmpPatch, ev->data.control.channel, ev->data.control.value); break; case SND_SEQ_EVENT_SENSING: // FIXME: // // This is apparently active sensing. // If we get it once and then loose it // we should shut up! // break; case SND_SEQ_EVENT_CHANPRESS: mx44_chanpress( mx44, ev->data.control.channel, ev->data.control.value ); break; default: fprintf(stderr,"Unknown SND_SEQ_EVENT_#%d\n",ev->type); } //*///////////////////////////////////////////////////*// // snd_seq_free_event(ev); // } while (snd_seq_event_input_pending(seq_handle, 0) > 0); pthread_mutex_unlock(&mx44->busy); sched_yield(); // Give the audio thread a go at the new state. } } pthread_cleanup_pop(pfd != NULL); // return NULL; } // // static void mx44_alsa_init(Mx44state *mx44) { int policy; pthread_attr_init(&mx44->midi_thread_attr); pthread_create(&mx44->midi_thread, &mx44->midi_thread_attr, mx44_midi_thread, mx44); // We need to have priority on par with JACK // in order to avoid priority inversion // while holding the mutex. pthread_getschedparam(mx44->midi_thread, &policy, &mx44->midi_thread_param); policy = SCHED_FIFO; mx44->midi_thread_param.sched_priority = sched_get_priority_max(SCHED_FIFO) -1; pthread_setschedparam(mx44->midi_thread, policy, &mx44->midi_thread_param); } // // // EOF ALSA interface /////////////////////////////////////////////////////////////////// #define PHASEALIGN ((0x0940<<14)) #define FIXMUL(x,y) ((x * y) >> 15) // static mmx_t dummy; static /*const*/ mmx_t high_mask = (mmx_t)0xFFFF0000FFFF0000LL; static /*const*/ mmx_t shrt_min = (mmx_t)0x8000800080008000LL; static mmx_t mmxtmp; /* 16bit integer pseudo sin for the Mx44 synthesizer ----------------------------------------------------- * Asserts 16bit short and 32bit (default) int * PI == 2^15 * * Use the sum of two mx44_psin in tandem shifted by * approx 60 degrees to cancel out most of the odd * overtones. (I use an offset of 0x14d4 in Mx44) */ inline static short mx44_psin(short n) { short x = n ^ 0x8000; // x is n shifted 180 degrees n = (n * x) >> 13; // take the halfwawe and ... return n ^ (x >> 15); // negate the expression if x is negative } // #define S(n) (((n)*((n)^0x8000))>>13)^(((short)((n)^0x8000))>>15) Mx44state * mx44_new(int maxpoly,char *patch_path) { Mx44state* mx44 = malloc(sizeof(Mx44state)); bzero(mx44,sizeof(Mx44state)); mx44->voices = malloc(sizeof(Mx44voice)*maxpoly + sizeof(mmx_t)); bzero(mx44->voices,sizeof(Mx44voice) * maxpoly + sizeof(mmx_t)); mx44->maxpoly = maxpoly; pthread_mutex_init(&mx44->busy,NULL); mx44_alsa_init(mx44); mx44->samplerate = mx44_jack_init(mx44); return mx44; } void mx44_dispose(Mx44state * mx44) { if(mx44) { pthread_mutex_lock(&mx44->busy); pthread_mutex_destroy(&mx44->busy); if(mx44->voices) free(mx44->voices); free(mx44); } } inline static void append(Mx44state * mx44,int q,Mx44voice *voice) { if(mx44->que[q]) { mx44->last[q]->next = voice; voice->previous = mx44->last[q]; voice->next = NULL; mx44->last[q] = voice; } else { mx44->que[q] = voice; mx44->last[q] = voice; voice->previous = NULL; voice->next = NULL; } } inline static void un_link(Mx44state * mx44,Mx44voice *voice) { int q; if(voice->next) voice->next->previous = voice->previous; if(voice->previous) voice->previous->next = voice->next; for(q = 0;q < 5; ++q) { if(mx44->que[q] == voice) mx44->que[q] = voice->next; if(mx44->last[q] == voice) mx44->last[q] = voice->previous; } } inline static Mx44voice *pop(Mx44state * mx44,int q) { Mx44voice *voice = mx44->que[q]; if(voice) un_link(mx44,voice); return voice; } void mx44_reset(Mx44state * mx44,double tuningfork,int samplerate) { int i; if(mx44->samplerate) samplerate = mx44->samplerate; tuningfork /= 128.0; tuningfork *= 1.05946309436 * 1.05946309436 * 1.05946309436; for(i = 0; i < 128; tuningfork *= 1.05946309436, ++i) mx44->keyTable[i] = (tuningfork)*((double)0x10000000/(double)samplerate); mx44->que[0] = NULL; mx44->que[1] = NULL; mx44->que[2] = NULL; mx44->que[3] = NULL; mx44->que[4] = NULL; for(i = 0; i < mx44->maxpoly; ++i ) append(mx44,3,&(mx44->voices[i])); for(i = 0 ; i < MIDICHANNELS;++i) { mx44->pitchbend[i] = 512; mx44->modulation[i] = mx44->mod_now[i] = 8; } } inline static void w( Mx44state * mx44, Mx44voice *voice, int dst_op, int key, int harmonic, int detune) { detune = (((FIXMUL(detune,detune)*detune)) + (detune<<5))<<1; switch(dst_op) { case 0: voice->delta02.d[0] = ((((long long)mx44->keyTable[key]*harmonic)>>5)+detune); break; case 1: voice->delta13.d[0] = ((((long long)mx44->keyTable[key]*harmonic)>>5)+detune); break; case 2: voice->delta02.d[1] = ((((long long)mx44->keyTable[key]*harmonic)>>5)+detune); break; case 3: voice->delta13.d[1] = ((((long long)mx44->keyTable[key]*harmonic)>>5)+detune); break; } } inline static void pm( Mx44voice *voice, int dst_op, int src_op, int amount ) { voice->pm[(src_op - dst_op)&0x03].w[dst_op] = amount; } inline static void am( Mx44voice *voice, int dst_op, int src_op, int amount ) { voice->am[(src_op - dst_op)&0x03].w[dst_op] = amount; } inline static void env( Mx44voice *voice, int op , int start_level, int time_0, int level_0, // attack int time_1, int level_1, int time_2, int level_2, // decay int time_3, int level_3, int time_4, int level_4, // sustain int time_5, int level_5, int time_6, int level_6, // release int time_7, int level_7 ) { Mx44env *env =&(voice->env); int *time = env->time[op]; int *delta_value = env->delta_value[op]; // Warning to self: Do not attemt simplifying this section ever again! // >:-! time_0 |= OPLOOP-1, time_0 ++; delta_value[0] = ((level_0 - start_level)<<15) / (time_0>>1); time[0] = time_0; time_1 |= OPLOOP-1, time_1 ++; delta_value[1] = ((level_1 - level_0)<<15) / (time_1>>1); time[1] = time_1; time_2 |= OPLOOP-1, time_2 ++; delta_value[2] = ((level_2 - level_1)<<15) / (time_2>>1); time[2] = time_2; time_3 |= OPLOOP-1, time_3 ++; delta_value[3] = ((level_3 - level_2)<<15) / (time_3>>1); time[3] = time_3; time_4 |= OPLOOP-1, time_4 ++; delta_value[4] = ((level_4 - level_3)<<15) / (time_4>>1); time[4] = time_4; env->sustain[op] = level_3 << 16; time_5 |= OPLOOP-1, time_5 ++; delta_value[5] = ((level_3 - level_4)<<15) / (time_5>>1); time[5] = time_5; time_6 += OPLOOP-1, time_6 ++; env->release[op] = level_6 ; delta_value[6] = ((level_6 - level_5)<<15) / (time_6>>1); time[6] = time_6; time_7 |= OPLOOP-1, time_7 ++; delta_value[7] = ((level_7 - level_6)<<15) / (time_7>>1); time[7] = time_7; start_level <<= 16; switch(op) { case 0: env->state02.d[0] = start_level; env->delta02.d[0] = delta_value[0]; break; case 1: env->state13.d[0] = start_level; env->delta13.d[0] = delta_value[0]; break; case 2: env->state02.d[1] = start_level; env->delta02.d[1] = delta_value[0]; break; case 3: env->state13.d[1] = start_level; env->delta13.d[1] = delta_value[0]; break; } } inline static void mix(Mx44state * mx44,Mx44voice *voice,int op,int volume,int balance,int key) { int left,right,b; volume = (FIXMUL(volume,volume)+volume)>>1; left = right = volume = FIXMUL(volume,(mx44->keyTable[76-(key>>2)]>>6)); b = FIXMUL(volume,balance)<<1; if(b < 0) right += b; else left -= b; voice->mixL.w[op] = left; voice->mixR.w[op] = right; } inline static void release(Mx44state * mx44,int hold,Mx44voice *voice) { un_link(mx44,voice); if(hold) append(mx44,hold,voice); else { Mx44env *env = &voice->env; //env->release[0] <<= 16; env->delta_value[0][7] = FIXMUL(env->delta_value[0][7],(env->state02.d[0]>>15)); env->release[0] *= (env->state02.d[0]>>14); env->delta_value[0][6] = ((env->release[0]>>1) - (env->state02.d[0]>>1)) / (env->time[0][6]>>1); voice->env.time_count[0] = 0x7FffFFff; voice->env.step[0] = 6; //env->release[1] <<= 16; env->delta_value[1][7] = FIXMUL(env->delta_value[1][7],(env->state13.d[0]>>15)); env->release[1] *= (env->state13.d[0]>>14); env->delta_value[1][6] = ((env->release[1]>>1) - (env->state13.d[0]>>1)) / (env->time[1][6]>>1); voice->env.time_count[1] = 0x7FffFFff; voice->env.step[1] = 6; //env->release[2] <<= 16; env->delta_value[2][7] = FIXMUL(env->delta_value[2][7],(env->state02.d[1]>>15)); env->release[2] *= (env->state02.d[1]>>14); env->delta_value[2][6] = ((env->release[2]>>1) - (env->state02.d[1]>>1)) / (env->time[2][6]>>1); voice->env.time_count[2] = 0x7FffFFff; voice->env.step[2] = 6; //env->release[3] <<= 16; env->delta_value[3][7] = FIXMUL(env->delta_value[3][7],(env->state13.d[1]>>15)); env->release[3] *= (env->state13.d[1]>>14); env->delta_value[3][6] = ((env->release[3]>>1) - (env->state13.d[1]>>1)) / (env->time[3][6]>>1); voice->env.time_count[3] = 0x7FffFFff; voice->env.step[3] = 6; append(mx44,2,voice); } } inline static Mx44voice *assign(Mx44state * mx44) { Mx44voice *voice; if((voice = pop(mx44,3))) // silent { append(mx44,0, voice); return voice; } else if((voice = pop(mx44,2))) // released { append(mx44,0, voice); return voice; } else if((voice = pop(mx44,4))) // excess hold { append(mx44,0, voice); return voice; } else if((voice = pop(mx44,1))) // on hold { append(mx44,0, voice); if( mx44->keyboard[voice->channel][voice->key][2] == voice) mx44->keyboard[voice->channel][voice->key][2] = NULL; else if( mx44->keyboard[voice->channel][voice->key][1] == voice) mx44->keyboard[voice->channel][voice->key][1] = mx44->keyboard[voice->channel][voice->key][2], mx44->keyboard[voice->channel][voice->key][2] = NULL; return voice; } else if((voice = pop(mx44,0))) // running { //fprintf(stderr,"\n Mx44: Critical voice stealing\n"); append(mx44,0, voice); mx44->keyboard[voice->channel][voice->key][0] = NULL; return voice; } return NULL; } // FIXME: state never used inline static int bias(Mx44state * mx44,int op,int key,int velocity,Mx44patch *patch) { int breakpoint,hival,loval,rval = 0; breakpoint = patch->breakpoint[op]; hival = patch->keybias[op][0]; loval = patch->keybias[op][1]; if(breakpoint < key) rval = (key - breakpoint) * hival; else if(breakpoint > key) rval = (breakpoint - key) * loval; rval = 0x7FFF - rval; if(rval < 0) rval = 0; if(rval > 0x7FFF) rval = 0x7FFF; velocity = (velocity * patch->velocity[op]) >> 7; if(velocity > 0) { int tmp = rval; rval -= FIXMUL(rval,patch->velocity[op]); rval += FIXMUL(velocity,tmp); } else { rval += FIXMUL(velocity,rval); } return rval; } void mx44_noteon(Mx44state * mx44,int channel,int key,int velocity) { static /*const*/ mmx_t off_60 = (mmx_t)0x14d414d414d414d4LL; //static /*const*/ mmx_t off_60 = (mmx_t)0x14e414e414e414e4LL; Mx44voice *voice; Mx44voice *next,*previous; int op,j; Mx44patch *patch = &mx44->tmpPatch[channel &= CHANNELMASK]; if(!velocity) { // this is actually a release mx44_noteoff(mx44,channel,key,velocity); return; } if(mx44->keyboard[channel][key][0]) mx44_noteoff(mx44,channel,key,0); voice = assign(mx44); next = voice->next; previous = voice->previous; mx44->keyboard[channel][key][0] = voice; bzero(voice,sizeof(*voice)); voice->next = next; voice->previous = previous; voice->key = key; voice->channel = channel; voice->magicnumber = off_60; voice->delay_time = ((double)patch->mod_delay/mx44->keyTable[key])*5000; if(patch->button[0]&PHASEFOLLOWKEYBUTTON) voice->state02.d[0] = (patch->phase[0][0]<<17) + (patch->phase[0][1]*(key<<12)) - (PHASEALIGN); else voice->state02.d[0] = (patch->phase[0][0]<<17) + (patch->phase[0][1]*(velocity<<11)) - (PHASEALIGN); if(patch->button[1]&PHASEFOLLOWKEYBUTTON) voice->state13.d[0] = (patch->phase[1][0]<<17) + (patch->phase[1][1]*(key<<12)) - (PHASEALIGN); else voice->state13.d[0] = (patch->phase[1][0]<<17) + (patch->phase[1][1]*(velocity<<11)) - (PHASEALIGN); if(patch->button[2]&PHASEFOLLOWKEYBUTTON) voice->state02.d[1] = (patch->phase[2][0]<<17) + (patch->phase[2][1]*(key<<12)) - (PHASEALIGN); else voice->state02.d[1] = (patch->phase[2][0]<<17) + (patch->phase[2][1]*(velocity<<11)) - (PHASEALIGN); if(patch->button[3]&PHASEFOLLOWKEYBUTTON) voice->state13.d[1] = (patch->phase[3][0]<<17) + (patch->phase[3][1]*(key<<12)) - (PHASEALIGN); else voice->state13.d[1] = (patch->phase[3][0]<<17) + (patch->phase[3][1]*(velocity<<11)) - (PHASEALIGN); for(op = 0; op < 4; ++op) { int k0,k1,k2,b; b = bias(mx44,op,key,velocity, patch)<<1; if(patch->intonation[op][0]>0) voice->intonation[op][0] = (patch->intonation[op][0]*velocity)<<7; else voice->intonation[op][0] = (patch->intonation[op][0]*(128-(velocity>>1))*(key>>3))<<4; voice->intonation[op][1] = (SHRT_MAX - patch->intonation[op][1])*(key<<1); /* voice->intonation[op][1] = (key * (SHRT_MAX - FIXMUL( FIXMUL(patch->intonation[op][1], patch->intonation[op][1] ), FIXMUL(patch->intonation[op][1], patch->intonation[op][1]) ))); */ if(patch->button[op]&WAWEBUTTON) voice->complexwawe.w[op] = 0xFFFF; if(patch->button[op]&WHEELBUTTON) voice->wheel.w[op] = 0xFFFF; if(patch->button[op]&LOWPASSBUTTON) voice->lowpass.w[op] = 0xFFFF; if(patch->button[op]&WAWESHAPEBUTTON) voice->waweshape.w[op] = 0xFFFF; if(patch->button[op]&MAGICBUTTON) { voice->magicmodulation.w[op] = patch->detune[op] & 0x0F; voice->magicmodulation2.w[op] = patch->detune[op] >> 4; switch(op) { case 0: voice->magicnumber.w[0] = voice->state02.d[0]>>12; break; case 1: voice->magicnumber.w[1] = voice->state13.d[0]>>12; break; case 2: voice->magicnumber.w[2] = voice->state02.d[1]>>12; break; case 3: voice->magicnumber.w[3] = voice->state13.d[1]>>12; break; } } k0 = 32000 - ((patch->velocityfollow[op]*velocity)>>7); k1 = 32000 - ((patch->keyfollow[op][0]*key)>>7); k2 = 32000 - ((patch->keyfollow[op][1]*key)>>7); k0 = FIXMUL(k0,k1); k0 = FIXMUL(k0,k0); k1 = FIXMUL(k1,k1); k2 = FIXMUL(k2,k2); w(mx44,voice,op,key,patch->harmonic[op],patch->detune[op]); voice->od.w[op] = patch->od[op]+1; for(j = 0; j < 4;++j) { am(voice, op, j, patch->am[op][j]); pm(voice, op, j, patch->pm[op][j]); } env(voice, op, FIXMUL(patch->env_level[op][0],b), FIXMUL(patch->env_time[op][0],k0)<<3, FIXMUL(patch->env_level[op][1],b), FIXMUL(patch->env_time[op][1],k0)<<3, FIXMUL(patch->env_level[op][2],b), FIXMUL(patch->env_time[op][2],k1)<<3, FIXMUL(patch->env_level[op][3],b), FIXMUL(patch->env_time[op][3],k1)<<3, FIXMUL(patch->env_level[op][4],b), FIXMUL(patch->env_time[op][4],k2)<<3, FIXMUL(patch->env_level[op][5],b), FIXMUL(patch->env_time[op][5],k2)<<3, FIXMUL(patch->env_level[op][6],b), FIXMUL(patch->env_time[op][6],k1)<<3, FIXMUL(patch->env_level[op][7],b), FIXMUL(patch->env_time[op][7],k1)<<3, 0); mix(mx44,voice, op, patch->mix[op][0],patch->mix[op][1],key); } voice->env.running = 0x0F; // go live! } void mx44_noteoff(Mx44state * mx44,int channel,int key,int velocity) { Mx44voice *voice; channel&=CHANNELMASK; if(mx44->holdpedal[channel]) { /**/ voice = mx44->keyboard[channel][key][2]; if(voice) release(mx44,4,voice); /**/ //mx44->keyboard[channel][key][3] = mx44->keyboard[channel][key][2]; mx44->keyboard[channel][key][2] = mx44->keyboard[channel][key][1]; mx44->keyboard[channel][key][1] = mx44->keyboard[channel][key][0]; voice = mx44->keyboard[channel][key][0]; if(voice) release(mx44,1,voice); mx44->keyboard[channel][key][0] = NULL; } else { mx44->keyboard[channel][key][1] = NULL; voice = mx44->keyboard[channel][key][0]; if(voice) release(mx44,0,voice); mx44->keyboard[channel][key][0] = NULL; } } void mx44_pgmchange(Mx44state* mx44,int channel,int patchnumber) { // short *lfo; channel &= CHANNELMASK; mx44->patchNo[channel] = patchnumber; mx44->tmpPatch[channel] = mx44->patch[patchnumber]; // lfo = mx44->tmpPatch[channel].lfo ; //mx44->lfo_rate_delta[channel] = 1;//lfo[0]; //printf("lfo %i\n",mx44->lfo_rate_delta[channel]); } void mx44_pitchbend(Mx44state * mx44,int channel, int lsb, int msb) { mx44->pitchbend[channel &= CHANNELMASK] = ((lsb) + ((msb) <<7)) >>4; } void mx44_control(Mx44state * mx44,int channel, int control, int data) { channel &= CHANNELMASK; switch(control) { /////////////////////////////////////////////////////////////////////////////////// // // CONTROL NUMBER CONTROL FUNCTION // ------------------------------------------ // (2nd Byte value) // Decimal Hex // 0 OOH GS Bank Select MSB // 1 01H Modulation wheel MSB case 1: mx44->modulation[channel] = data; break; // 2 02H Breath Controller MSB // 3 03H Undefined // 4 04H Foot controller MSB // 5 05H Portamento time MSB // 6 06H Data entry MSB // 7 07H Main volume MSB // 8 08H Balance MSB // 9 09H Undefined // 10 OAH Pan MSB // 11 OBH Expression Controller MSB // 12-15 0C-OFH Undefined (?) // 12 GS Effect Control 1 MSB // 13 GS Effect Control 2 MSB // 16-19 10-13H General Purpose Sliders 1-4 // 20-31 14-1FH Undefined // 32-63 20-3FH LSB for values 0-31 // 64 40H Damper pedal (sustain) case 64: mx44->holdpedal[channel] = data; if(!data) { Mx44voice *v,*voice = mx44->que[1]; // held voices int i = 0; do { mx44->keyboard[channel][i][1] = NULL; mx44->keyboard[channel][i][2] = NULL; }while(++i < 128); while(voice) { v = voice->next; if( voice->channel == channel) release(mx44,0,voice); voice = v; } voice = mx44->que[4]; // excess held while(voice) { v = voice->next; if( voice->channel == channel) release(mx44,0,voice); voice = v; } } break; // 65 41H Portamento // 66 42H Sostenuto // 67 43H Soft pedal // 68 44H Undefined // 69 45H Hold 2 // 70-79 46-4FH Undefined (?) // 70 GS Sound Variation // 71 GS Sound Timbre // 72 GS Sound Release Time // 73 GS Sound Attack Time // 74 GS Sound Brightness // 75 GS Sound Control 6 // 76 GS Sound Control 7 // 77 GS Sound Control 8 // 78 GS Sound Control 9 // 79 GS Sound Control 10 // 80-83 50-53H General Purpose Button (#'s 1-4) // 84-90 54-5AH Undefined // 91 5BH External Effects Depth // 92 5CH Tremelo Depth // 93 5DH Chorus Depth // 94 5EH Celeste (Detune) Depth // 95 5FH Phaser Depth // 96 60H Data increment // 97 61H Data decrement // 98 62H Non-Registered Parameter Number LSB // 99 63H Non-Registered Parameter Number MSB // 100 64H Registered Parameter Number LSB // 101 65H Registered Parameter Number MSB // 102-120 66-78H Undefined // 120 78H GS All Sound Off case 120: // All Sound Off { Mx44voice *voice; // FIXME: Not *all* channels ... bzero(mx44->keyboard,sizeof(mx44->keyboard)); bzero(mx44->holdpedal,sizeof(mx44->holdpedal)); while((voice = pop(mx44,0))) append(mx44,3,voice); while((voice = pop(mx44,1))) append(mx44,3,voice); while((voice = pop(mx44,2))) append(mx44,3,voice); } break; // 121-127 79-7FH Reserved for Channel Mode Messages (See below ...) // ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// // // CHANNEL MODE MESSAGES // --------------------- // // STATUS DATABYTES DESCRIPTION // Hex Binary // Bn 1011nnnn 0ccccccc Mode Messages // 0vvvvvvv // ccccccc = 121: Reset All Controllers // vvvvvvv = 0 // // // ccccccc = 122:Local Control // vvvvvvv = 0, Local Control Off // vvvvvvv = 127, Local Control On // // ccccccc = 123: All Notes Off // vvvvvvv = 0 // // // ccccccc = 124: Omni Mode Off (All Notes Off) // vvvvvvv = 0 // // // ccccccc = 125:Omni Mode On (All Notes Off) // vvvvvvv = 0 // // // ccccccc = 126: Mono Mode On (Poly Mode Off) // (All Notes Off) // vvvvvvv = M, where M is the number of // channels. // vvvvvvv = 0, the number of channels equals the // number of voices in the receiver. // // ccccccc = 127: Poly Mode On (Mono Mode Off) // (All Notes Off) // vvvvvvv = 0 // // Notes // 1. nnnn: Basic Channel number (1-16) // // 2. ccccccc: Controller number (121 - 127) // // 3. vvvvvvv: Controller value // ///////////////////////////////////////////////////////////////////////////////////////////// case 123: // All Notes Off case 124: // Omni Mode Off (implicit All Notes Off) case 125: // Omni Mode On ... case 126: // Mono Mode On ... case 127: // Poly Mode On ... { Mx44voice *v,*voice = mx44->que[0]; int i = 0; do { mx44->keyboard[channel][i][0] = NULL; mx44->keyboard[channel][i][1] = NULL; mx44->keyboard[channel][i][2] = NULL; } while(++i < 128); while(voice) { v = voice->next; if( voice->channel == channel) release(mx44,0,voice); voice = v; } voice = mx44->que[1]; while(voice) { v = voice->next; if( voice->channel == channel) release(mx44,0,voice); voice = v; } voice = mx44->que[4]; while(voice) { v = voice->next; if( voice->channel == channel) release(mx44,0,voice); voice = v; } } break; default: printf("control: %d data %d\n",control,data); } } void mx44_chanpress(Mx44state* mx44,int channel,int data) { // DANG! My aftertouch is broken now when I need it ... // ... and that after *only* 22 years of service. Hmphf! // // (Oh, wait ...) } inline static void mx44run(Mx44state * mx44,Mx44voice *voice,short * stereo_out,int pitchbend,int modulation, int *lfo) { Mx44env *env =&(voice->env); int *env_step = env->step; int i;//, j = ENVLOOP/2; int itmp[4]; movq_m2r(voice->out, mm1); // Get the previous output // do the intonation first itmp[0] = voice->intonation[0][0]>>15; itmp[0] *= FIXMUL(itmp[0],itmp[0]); /**/itmp[2] = voice->intonation[2][0]>>15; /**/itmp[2] *= FIXMUL(itmp[2],itmp[2]); mx44->mmxtmp[0].d[0] = (voice->delta02.d[0]) + ((voice->delta02.d[0] >>9) * (pitchbend + lfo[0])) + itmp[0]; if(voice->intonation[0][0]) { if(voice->intonation[0][0] > 0) { voice->intonation[0][0]-=(voice->intonation[0][1]); if(voice->intonation[0][0]<0) voice->intonation[0][0] = 0; } else { voice->intonation[0][0]+=(voice->intonation[0][1]); if(voice->intonation[0][0] > 0) voice->intonation[0][0]= 0; } voice->intonation[0][1] -= voice->intonation[0][1]>>14; } /**/itmp[1] = voice->intonation[1][0] >> 15; /**/itmp[1] *= FIXMUL(itmp[1],itmp[1]); mx44->mmxtmp[0].d[1] = (voice->delta02.d[1]) + ((voice->delta02.d[1] >>9) * (pitchbend + lfo[3])) + itmp[2]; if(voice->intonation[2][0]) { if(voice->intonation[2][0] > 0) { voice->intonation[2][0]-=(voice->intonation[2][1]); if(voice->intonation[2][0]<0) voice->intonation[2][0]= 0; } else { voice->intonation[2][0]+=(voice->intonation[2][1]); if(voice->intonation[2][0] > 0) voice->intonation[2][0]= 0; } voice->intonation[2][1] -= voice->intonation[2][1]>>14; } /**/itmp[3] = voice->intonation[3][0] >> 15; /**/itmp[3] *= FIXMUL(itmp[3],itmp[3]); mx44->mmxtmp[1].d[0] = (voice->delta13.d[0]) + ((voice->delta13.d[0] >>9) * (pitchbend+lfo[1])) + itmp[1]; if(voice->intonation[1][0]) { if(voice->intonation[1][0] > 0) { voice->intonation[1][0]-=(voice->intonation[1][1]); if(voice->intonation[1][0]<0) voice->intonation[1][0]= 0; } else { voice->intonation[1][0]+=(voice->intonation[1][1]); if(voice->intonation[1][0] > 0) voice->intonation[1][0]= 0; } voice->intonation[1][1] -= voice->intonation[1][1]>>14; } /**/ /**/ mx44->mmxtmp[1].d[1] = (voice->delta13.d[1]) + ((voice->delta13.d[1] >>9) * (pitchbend+lfo[2])) + itmp[3]; if(voice->intonation[3][0]) { if(voice->intonation[3][0]>0) { voice->intonation[3][0]-=(voice->intonation[3][1]); if(voice->intonation[3][0]<0) voice->intonation[3][0]= 0; } else { voice->intonation[3][0]+=(voice->intonation[3][1]); if(voice->intonation[3][0]>0) voice->intonation[3][0]= 0; } voice->intonation[3][1] -= voice->intonation[3][1]>>14; } { // Set us up the envelopes // -- -- int step = env_step[0]; // op1 int *running = &voice->env.running; *running = 0; if(step < 9) { *running = 1; // notify that this voice is still audible if(step < 6) // -- Attack/Sustain: { if(env->time[0][step] <= env->time_count[0]) { env->time_count[0] = 0; env_step[0] = ++step; if(step == 6) // -- End of sustain Loop: env_step[0] = step = 4, env->state02.d[0] = env->sustain[0]; env->delta02.d[0] = env->delta_value[0][step]; } } else // -- Release: { if(env->time[0][step-1] <= env->time_count[0]) { env->time_count[0] = 0; env_step[0] = ++step; env->delta02.d[0] = env->delta_value[0][step-1]; } } env->time_count[0] += OPLOOP; } else env->state02.d[0] = 0; // -- -- step = env_step[1]; // op2 if(step < 9) { *running|=2; if(step < 6) // attack { if(env->time[1][step] <= env->time_count[1]) { env->time_count[1] = 0; env_step[1] = ++step; if(step == 6) // sustain loop env_step[1] = step = 4, env->state13.d[0] = env->sustain[1]; env->delta13.d[0] = env->delta_value[1][step]; } } else // release { if(env->time[1][step-1] <= env->time_count[1]) { env->time_count[1] = 0; env_step[1] = ++step; env->delta13.d[0] = env->delta_value[1][step-1]; } } env->time_count[1] += OPLOOP; } else env->state13.d[0] = 0; step = env_step[2]; // op3 if(step < 9) { *running|=4; if(step < 6) // attack { if(env->time[2][step] <= env->time_count[2]) { env->time_count[2] = 0; env_step[2] = ++step; if(step == 6) // sustain loop env_step[2] = step = 4, env->state02.d[1] = env->sustain[2]; env->delta02.d[1] = env->delta_value[2][step]; } } else // release { if(env->time[2][step-1] <= env->time_count[2]) { env->time_count[2] = 0; env_step[2] = ++step; env->delta02.d[1] = env->delta_value[2][step-1]; } } env->time_count[2] += OPLOOP; } else env->state02.d[1] = 0; step = env_step[3]; // op4 if(step < 9) { *running|=8; if(step < 6) // attack { if(env->time[3][step] <= env->time_count[3]) { env->time_count[3] = 0; env_step[3] = ++step; if(step == 6) // sustain loop env_step[3] = step = 4, env->state13.d[1] = env->sustain[3]; env->delta13.d[1] = env->delta_value[3][step]; } } else // release { if(env->time[3][step-1] <= env->time_count[3]) { env->time_count[3] = 0; env_step[3] = ++step; env->delta13.d[1] = env->delta_value[3][step-1]; } } env->time_count[3] += OPLOOP; } else env->state13.d[1] = 0; if(!*running) return;//break; } i = 0; mx44->wheel.w[0] = modulation; mx44->wheel.w[1] = modulation; mx44->wheel.w[2] = modulation; mx44->wheel.w[3] = modulation; while(i++ < OPLOOP) { /* FIXME int index = (voice->delay_index + voice->delay_time) & 0x03FF ; // 1024 -1 voice->delay_index = (voice->delay_index +1 ) & 0x03FF ; // 1024 -1 */ movq_r2r(mm1,mm7); // Modulation wheel movq_m2r(mx44->wheel,mm0); pand_m2r(voice->wheel,mm0); pmulhw_r2r(mm1,mm0); psllw_i2r(1,mm0); psubw_r2r(mm0,mm1); // N.state += N.delta movq_m2r(voice->state02, mm0); // Get current state of op 0 and 2 movq_m2r(voice->state13, mm3); // Do the same for op 1 and 3 .. /**/movq_m2r(voice->pm[0], mm2); // Prefetch 1st phase modulation (feedback) ... /**/movq_m2r(voice->am[0], mm6); // Prefetch 1st am modulation (feedback) paddd_m2r(mx44->mmxtmp[0], mm0); // add the deltas for op 0 and 2 movq_r2m(mm0, voice->state02); // store the result pand_m2r(high_mask, mm0); // mask off low word psrlq_i2r(16, mm0); // shift high word from position 1 3 >> 0 2 paddd_m2r(mx44->mmxtmp[1], mm3); // add the deltas for op 1 and 3 movq_r2m(mm3, voice->state13); // store .. pand_m2r(high_mask, mm3); // mask off low word por_r2r(mm3, mm0); // Combine (as words) op 1 3 and 0 2 //----------------- op 0 (relative to 'self') pmulhw_r2r(mm1, mm2); // .. adjust pm level // Rotate previous output (part 1) /**/movq_r2r(mm1,mm5); // copy previous out /**/psrlq_i2r(16, mm5); // shift 3 elements 1 position right .. paddw_r2r(mm2, mm0); // .. and add phase modulation. paddw_r2r(mm2, mm0); // .. and add more phase modulation. movq_m2r(voice->pm[1], mm2); // Get next phase modulation .. pmulhw_r2r(mm1, mm6); // .. adjust am level movq_m2r(voice->am[1], mm4); // Get next am modulation // Rotate previous output (part 2): psllq_i2r(48, mm1); // .. rotate 1st element to the end por_r2r(mm5, mm1); // .. and combine //----------------- op 1 pmulhw_r2r(mm1, mm2); // .. adjust pm level // Rotate previous output (part 1) /**/movq_r2r(mm1,mm5); // copy previous out /**/psrlq_i2r(16, mm5); // shift 3 elements 1 position right .. paddw_r2r(mm2, mm0); // .. and add phase modulation. paddw_r2r(mm2, mm0); // .. and add more phase modulation. movq_m2r(voice->pm[2], mm2); // Get next phase modulation .. pmulhw_r2r(mm1, mm4); // .. adjust am level paddsw_r2r(mm4,mm6); // .. add saturating movq_m2r(voice->am[2], mm3); // Get next am modulation // Rotate previous output (part 2): psllq_i2r(48, mm1); // .. rotate 1st element por_r2r(mm5, mm1); // .. and combine //----------------- op 2 pmulhw_r2r(mm1, mm2); // .. adjust pm level // Rotate previous output (part 1): /**/movq_r2r(mm1,mm5); // copy previous out /**/psrlq_i2r(16, mm5); // .. shift right paddw_r2r(mm2, mm0); // .. add phase modulation. paddw_r2r(mm2, mm0); // .. add phase modulation. movq_m2r(voice->pm[3], mm2); // Get next phase modulation .. pmulhw_r2r(mm1, mm3); // .. adjust am level movq_m2r(voice->am[3], mm4); // Get next am modulation // Rotate previous output (part 2): psllq_i2r(48, mm1); // .. shift left por_r2r(mm5, mm1); // .. and combine //----------------- op 3 pmulhw_r2r(mm1, mm2); // .. adjust pm level //// Rotate previous output (part 1): ///**/movq_r2r(mm1,mm5); // copy previous out ///**/psrlq_i2r(16, mm5); // .. shift right paddw_r2r(mm2, mm0); // .. and add phase modulation. paddw_r2r(mm2, mm0); // .. and add more phase modulation. pmulhw_r2r(mm1, mm4); // .. adjust am level paddsw_r2r(mm4,mm3); // .. add am saturating //// Rotate previous output (part 2): //psllq_i2r(48, mm1); // .. shift left //por_r2r(mm5, mm1); // .. and combine //----------------- paddsw_r2r(mm6,mm3); // Sum amplitude modulations // ---------------- Take the 'pseudo sine' / 'waweshape' //movq_m2r(shrt_min,mm4); // prepare 180 degree offset /**/movq_m2r(voice->magicnumber,mm6); // prepare 60 degree offset paddw_m2r(voice->magicmodulation2,mm6); movq_r2m(mm6,voice->magicnumber); // psllw_i2r(1,mm0); // Transpose by octave (maybe not?) movq_r2r(mm0,mm5); // n is in mm0 and mm5 paddw_m2r(shrt_min,mm0); // x is in mm0, offset 180 degrees /***/movq_m2r(voice->complexwawe,mm1); // load the condition for selfmodulation pmulhw_r2r(mm5,mm0); // do halfwawes /**/paddw_r2r(mm5,mm6); // n is in mm6, offset 60 degrees psraw_i2r(15,mm5); // x is either 0xFFFF or 0 pxor_r2r(mm5,mm0); // do alternating halfwawes /***/ pand_r2r(mm0,mm1); // actually select selfmodulation and .. /***/ psubw_r2r(mm1,mm6); // .. phase modulate n by n if selected /**/pmullw_m2r(voice->od,mm6); // n is transposed to some harmonic /**/movq_r2r(mm6,mm5); // n is in mm5 and mm6 /**/paddw_m2r(shrt_min,mm6); // x is in mm6, offset 180 degrees /**/pmulhw_r2r(mm5,mm6); // do halfwawes /**/psraw_i2r(15,mm5); // x is either 0xFFFF or 0 /**/pxor_r2r(mm5,mm6); // do alternating halfwawes /****/movq_m2r(env->state02, mm5); /// Get current state of env 0 and 2 paddsw_r2r(mm6,mm0); // sum the two wawe components /****/movq_m2r(env->state13, mm6); /// Get current state of env 1 and 3 psllw_i2r(2,mm0); // normalize the waweform algorithm //----------------- Envelopes // N.env.state += N.env.delta paddd_m2r(env->delta02, mm5); // add the deltas for op 0 and 2 movq_r2m(mm5, env->state02); // store the result pand_m2r(high_mask, mm5); // mask off low word psrlq_i2r(16, mm5); // shift high word from position 3,1 >> 0,2 paddd_m2r(env->delta13, mm6); // add the deltas for op 1 and 3 movq_r2m(mm6, env->state13); // store the result pand_m2r(high_mask, mm6); // mask off low word por_r2r(mm6, mm5); // Combine env 0,2 and 1,3 psllw_i2r(1,mm5); // ... pmulhw_r2r(mm5, mm5); // square the envelope values psllw_i2r(1,mm5); // normalize after multiplication pmulhw_r2r(mm5, mm0); // Apply envelope psllw_i2r(1, mm0); // normalize after multiplication //----------------- Amplitude Modulation paddsw_r2r(mm3,mm3); // .. add saturating to self pmulhw_r2r(mm0, mm3); // Do the amplitude modulation /**/movq_m2r(voice->mixL, mm5); /// get the left mixer level paddsw_r2r(mm3,mm3); // .. add saturating to self paddsw_r2r(mm3,mm0); // .. add saturating to output /**/movq_m2r(voice->mixR, mm3); /// get the right mixer level // mm1, mm2, mm4 mm6 ... //----------------- Resonant Waweshaping /**/ movq_r2r(mm0,mm6); psllw_i2r(3,mm6); // Transpose by 3.5 octaves paddw_r2r(mm0,mm6); // /**/movq_r2r(mm6,mm1); // Transpose by 2.5 octaves /**/psubw_r2r(mm0,mm1); // movq_r2r(mm6,mm4); // n is in mm6 and mm4 paddw_m2r(shrt_min,mm6); // x is in mm6, offset 180 degrees /**/movq_r2r(mm1,mm2); // n is in mm1 and mm4 pmulhw_r2r(mm4,mm6); // do halfwawes /**/paddw_m2r(shrt_min,mm1); // x is in mm1, offset 180 degrees psraw_i2r(15,mm4); // x is either 0xFFFF or 0 /**/pmulhw_r2r(mm2,mm1); // do halfwawes pxor_r2r(mm4,mm6); // do alternating halfwawes /**/psraw_i2r(15,mm2); // x is either 0xFFFF or 0 /**/pxor_r2r(mm2,mm1); // do alternating halfwawes psubw_r2r(mm2,mm6); // difference between nx, nx movq_r2r(mm0,mm2); psraw_i2r(1,mm2); // dampen raw signal pand_m2r(voice->waweshape,mm6); // select the effect pand_m2r(voice->waweshape,mm2); psubsw_r2r(mm2,mm0); // apply effect psubsw_r2r(mm6,mm0); // //---------------- Lowpass psubw_r2r(mm0,mm7); pand_m2r(voice->lowpass,mm7); psraw_i2r(1,mm7); paddsw_r2r(mm7,mm0); psraw_i2r(1,mm7); paddsw_r2r(mm7,mm0); //-------------------- movq_r2r(mm0,mm1); // Keep value for next loop //----------------- Mixer // Left pmulhw_r2r(mm0,mm5); // apply left volume movq_r2r(mm5,mm2); psrlq_i2r(32, mm2); // .. shift 32 bits paddsw_r2r(mm5,mm2); // and sum op1+op3, op2+op4 movq_r2r(mm2,mm5); psrlq_i2r(16, mm5); // .. shift 16 bits paddsw_r2r(mm2,mm5); // and do the final sum /**/movd_m2r(*((int*)stereo_out),mm2); // get the sum of n-1 samples // Right pmulhw_r2r(mm0,mm3); // apply right volume movq_r2r(mm3,mm4); psrlq_i2r(32, mm4); // .. shift 32 bits paddsw_r2r(mm3,mm4); // and sum op1+op3, op2+op4 movq_r2r(mm4,mm3); psrlq_i2r(16, mm3); // .. shift 16 bits paddsw_r2r(mm4,mm3); // and do the final sum // Stereo punpcklwd_r2r(mm3, mm5); // combine left and right // Output paddsw_r2r(mm2,mm5); // add the n'th sample movd_r2m(mm5,*((int*)stereo_out)); // .. and store stereo_out += 2; // Next stereo sample } // Remember the final state of this voice movq_r2m(mm0,voice->out); // --: Thats all Folks! :-- // } int mx44_play(Mx44state * mx44,short *stereo_out) { int voicecount = 0; int q,i; int lfo[MIDICHANNELS][4]; pthread_mutex_lock(&mx44->busy); // LFO ----------------------------------------------------------- // for(i = 0; i < MIDICHANNELS; ++i) { int j; short offset = mx44->tmpPatch[i].lfo_button[0] ? 0 : 0x014d4;//SHRT_MAX >> 1; short lfo_env_state = mx44->tmpPatch[i].lfo_button[1] ? ( mx44->modulation[i] - 64 ) << 8 : mx44->lfo_env_state[i] >> 16; short wawe0 = (mx44_psin(lfo_env_state)>>1)+(SHRT_MIN>>1); short wawe1 = -wawe0 + SHRT_MAX; int lfo_rate = ((mx44->tmpPatch[i].lfo[0] * wawe0) >> 1) + ((mx44->tmpPatch[i].lfo[1] * wawe1) >> 1); int lfo_level = (((mx44->tmpPatch[i].lfo[2] * wawe0) >> 1) + ((mx44->tmpPatch[i].lfo[3] * wawe1) >> 1)) >> 21; int lfo_envrate = (((mx44->tmpPatch[i].lfo[4] - 32000) * wawe0) >> 1) + (((mx44->tmpPatch[i].lfo[5] - 32000) * wawe1) >> 1); for(j = 0 ; j < 4; ++j) { lfo[i][j] = -FIXMUL( mx44_psin(( mx44->lfo_rate_state[i] >> 16) + (offset*j)), lfo_level); } mx44->lfo_env_state[i] += ((lfo_envrate -1300000) >> 4); mx44->lfo_rate_state[i] += ((lfo_rate +1300000)>>2); //if(!i) printf("%d\n",lforate); } // // --------------------------------------------------------------- // Filter out noise from fast wheel motion for(i = 0;i < MIDICHANNELS;++i) if(mx44->modulation[i] > mx44->mod_now[i]) ++mx44->mod_now[i]; else if(mx44->modulation[i] < mx44->mod_now[i]) --mx44->mod_now[i]; for(q = 0; q < 5; ++q) { Mx44voice *voice; if(q == 3) continue; else voice = mx44->que[q]; while(voice) { if(voice->env.running) { unsigned int mod = mx44->mod_now[voice->channel]; voicecount ++; mod += mod << 7; for(i=0;i<4;++i) voice->magicnumber.w[i] += voice->magicmodulation.w[i]; mx44run( mx44,voice, stereo_out, mx44->pitchbend[voice->channel], SHRT_MAX - (mod << 1), lfo[voice->channel] ); for(i=0;i<4;++i) voice->magicnumber.w[i] += voice->magicmodulation.w[i]; mx44run( mx44,voice, stereo_out + SAMPLES, mx44->pitchbend[voice->channel], SHRT_MAX - (mod << 1), lfo[voice->channel] ); voice = voice->next; } else { Mx44voice *next = voice->next; un_link(mx44,voice); append(mx44,3,voice); voice = next; } } } emms(); pthread_mutex_unlock(&mx44->busy); return voicecount; } #ifdef OMNIMODE // Under construction static void render32(Mx44state * mx44) { int q,i; short samples[MIDICHANNELS][64]; // [midi channel][left/right interleaved index] bzero(samples,sizeof(samples)); bzero(mx44->fsamples,sizeof(mx44->fsamples)); bzero(mx44->touched,sizeof(mx44->touched)); mx4->delivered = 0; for(q = 0; q < 5; ++q) { Mx44voice *voice = mx44->que[q]; if(q == 3) continue; while(voice) { if(voice->env.running) { unsigned int mod = mx44->mod_now[voice->channel]; mod += mod << 7; mx44(mx44,voice, samples[voice->channel], mx44->pitchbend[voice->channel],SHRT_MAX -(mod << 1)); voice = voice->next; mx44->touched[voice->channel] = 1; } else { Mx44voice *next = voice->next; un_link(mx44,voice); append(mx44,3,voice); voice = next; } } } for(q = 0; q < MIDICHANNELS; ++q) if(mx44->touched[q]) { short *s = samples[q]; for(i = 0; i < 32;++i) { mx44->fsamples[q][0][i] = *(s++); mx44->fsamples[q][0][i] /= 0x07FFF; mx44->fsamples[q][1][i] = *(s++); mx44->fsamples[q][1][i] /= 0x07FFF; } } } // syntax checking only ... // use with debugger at your own risk .. void omni(Mx44state* mx44, int request,float* port_left, float* port_right) { // int i = 0; int r = 0; while(r++ < request) { if(mx44->delivered == 32) render32(mx4); *port_left = mx44->fsamples[0][0][mx44->delivered]; *port_right = mx44->fsamples[0][0][mx44->delivered]; ++port_left; ++port_right; ++mx44->delivered; } } #endif Mx44/cmmx.h0000644000076400007640000003051510211066151011414 0ustar jensjens/* 1997-98 by H. Dietz and R. Fisher */ #ifndef _MMX_H #define _MMX_H /* The type of an value that fits in an MMX register (note that long long constant values MUST be suffixed by LL and unsigned long long values by ULL, lest they be truncated by the compiler) */ typedef union { long long q; /* Quadword 64-bit value */ unsigned long long uq; /* Unsigned Quadword */ int d[2]; /* 2 Doubleword (32-bit) values */ unsigned int ud[2]; /* 2 Unsigned Doubleword */ short w[4]; /* 4 Word (16-bit) values */ unsigned short uw[4]; /* 4 Unsigned Word */ char b[8]; /* 8 Byte (8-bit) values */ unsigned char ub[8]; /* 8 Unsigned Byte */ float s[2]; /* Single-precision (32-bit) value */ } mmx_t; mmx_t mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7; #define mmx_q(src,op,dst) ((dst).q op (src).q) #define mmx_uq(src,op,dst) ((dst).uq op (src).uq) #define mmx_d(src,op,dst)\ ((dst).d[0] = (dst).d[0] op (src).d[0],\ (dst).d[1] = (dst).d[1] op (src).d[1]) #define mmx_ud(src,op,dst)\ ((dst).ud[0] = (dst).ud[0] op (src).ud[0],\ (dst).ud[1] = (dst).ud[1] op (src).ud[1]) inline short _mmx_sat_w(int x) { if(x > 0x07FFF) return 0x7FFF; if(x < 0xFFFF8000) return 0x8000; return x; } inline short _mmx_sat_uw(int x) { if(x > 0x0FFFF) return 0xFFFF; if(x < 0) return 0; return x; } #define mmx_w(src,op,dst)\ ((dst).w[0] = (dst).w[0] op (src).w[0],\ (dst).w[1] = (dst).w[1] op (src).w[1],\ (dst).w[2] = (dst).w[2] op (src).w[2],\ (dst).w[3] = (dst).w[3] op (src).w[3]) #define mmx_sat_w(src,op,dst)\ ((dst).w[0] = _mmx_sat_w((dst).w[0] op (src).w[0]),\ (dst).w[1] = _mmx_sat_w((dst).w[1] op (src).w[1]),\ (dst).w[2] = _mmx_sat_w((dst).w[2] op (src).w[2]),\ (dst).w[3] = _mmx_sat_w((dst).w[3] op (src).w[3])) #define mmx_uw(src,op,dst)\ ((dst).uw[0] = (dst).uw[0] op (src).uw[0],\ (dst).uw[1] = (dst).uw[1] op (src).uw[1],\ (dst).uw[2] = (dst).uw[2] op (src).uw[2],\ (dst).uw[3] = (dst).uw[3] op (src).uw[3]) #define mmx_sat_uw(src,op,dst)\ ((dst).uw[0] = _mmx_sat_uw((dst).uw[0] op (src).uw[0]),\ (dst).uw[1] = _mmx_sat_uw((dst).uw[1] op (src).uw[1]),\ (dst).uw[2] = _mmx_sat_uw((dst).uw[2] op (src).uw[2]),\ (dst).uw[3] = _mmx_sat_uw((dst).uw[3] op (src).uw[3])) #define mmx_b(src,op,dst)\ ((dst).b[0] = (dst).b[0] op (src).b[0],\ (dst).b[1] = (dst).b[1] op (src).b[1],\ (dst).b[2] = (dst).b[2] op (src).b[2],\ (dst).b[3] = (dst).b[3] op (src).b[3],\ (dst).b[4] = (dst).b[4] op (src).b[4],\ (dst).b[5] = (dst).b[5] op (src).b[5],\ (dst).b[6] = (dst).b[6] op (src).b[6],\ (dst).b[7] = (dst).b[7] op (src).b[7]) #define mmx_ub(src,op,dst)\ ((dst).ub[0] = (dst).ub[0] op (src).ub[0],\ (dst).ub[1] = (dst).ub[1] op (src).ub[1],\ (dst).ub[2] = (dst).ub[2] op (src).ub[2],\ (dst).ub[3] = (dst).ub[3] op (src).ub[3],\ (dst).ub[4] = (dst).ub[4] op (src).ub[4],\ (dst).ub[5] = (dst).ub[5] op (src).ub[5],\ (dst).ub[6] = (dst).ub[6] op (src).ub[6],\ (dst).ub[7] = (dst).ub[7] op (src).ub[7]) /* 1x64 MOVe Quadword (this is both a load and a store... in fact, it is the only way to store) */ #define movq_i2r(var, reg) (reg.q = (long long)var) #define movq_m2r(var, reg) (reg.q = var.q) #define movq_r2m(reg, var) (var.q = reg.q) #define movq_r2r(regs, regd) (regd.q = regs.q) /* 1x32 MOVe Doubleword (like movq, this is both load and store... but is most useful for moving things between mmx registers and ordinary registers) */ #define movd_m2r(var, reg) (reg.uw[0] = (unsigned)var, reg.uw[1]=0) #define movd_r2m(reg, var) (var = reg.uw[0]) #define movd_r2r(regs, regd) (regd.uw[0] = regs.uw[0], regd.uw[1]=0) /* 2x32, 4x16, and 8x8 Parallel ADDs */ #define paddd_m2r(var, reg) mmx_d(var, +, reg) #define paddd_r2r(regs, regd) mmx_d(regs, +, regd) #define paddw_m2r(var, reg) mmx_w(var, +, reg) #define paddw_r2r(regs, regd) mmx_w(regs, +, regd) #define paddb_m2r(var, reg) mmx_b(var, +, reg) #define paddb_r2r(regs, regd) mmx_b(regs, +, regd) /* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic */ #define paddsw_m2r(var, reg) mmx_sat_w(var,+,reg) #define paddsw_r2r(regs, regd) mmx_sat_w(regs,+,regd) /* #define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg) #define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd) */ /* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic */ #define paddusw_m2r(var, reg) mmx_sat_uw(var,+,reg) #define paddusw_r2r(regs, regd) mmx_sat_uw(regs,+,regd) /* #define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg) #define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd) */ /* 2x32, 4x16, and 8x8 Parallel SUBs */ #define psubd_m2r(var, reg) mmx_d(var,-,reg) #define psubd_r2r(regs, regd) mmx_d(regs,-,regd) #define psubw_m2r(var, reg) mmx_w(var,-,reg) #define psubw_r2r(regs, regd) mmx_w(regs,-,regd) /* #define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg) #define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd) */ /* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic */ #define psubsw_m2r(var, reg) mmx_sat_w(var,-,reg) #define psubsw_r2r(regs, regd) mmx_sat_w(regs,-,regd) /* #define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg) #define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd) */ /* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic */ #define psubusw_m2r(var, reg) mmx_sat_uw(var,-,reg) #define psubusw_r2r(regs, regd) mmx_sat_uw(regs,-,regd) /* #define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg) #define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd) */ /* 4x16 Parallel MULs giving Low 4x16 portions of results */ #define pmullw_m2r(var, reg) mmx_w(var,*,reg) #define pmullw_r2r(regs, regd) mmx_w(regs,*,regd) /* 4x16 Parallel MULs giving High 4x16 portions of results */ #define pmulhw_r2r(src, dst)\ ((dst).w[0] = ((dst).w[0] * (src).w[0])>>16,\ (dst).w[1] = ((dst).w[1] * (src).w[1])>>16,\ (dst).w[2] = ((dst).w[2] * (src).w[2])>>16,\ (dst).w[3] = ((dst).w[3] * (src).w[3])>>16) #define pmulhw_m2r(src, dst) pmulhw_r2r(src, dst) /* 4x16->2x32 Parallel Mul-ADD (muls like pmullw, then adds adjacent 16-bit fields in the multiply result to make the final 2x32 result) */ /* #define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg) #define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd) */ /* 1x64 bitwise AND */ #define pand_m2r(var, reg) mmx_uq(var,&,reg) #define pand_r2r(regs, regd) mmx_uq(regs,&,regd) /* 1x64 bitwise AND with Not the destination */ /* #define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg) #define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd) #define pandn(vars, vard) mmx_m2m(pandn, vars, vard) */ /* 1x64 bitwise OR */ #define por_m2r(var, reg) mmx_uq(var,|,reg) #define por_r2r(regs, regd) mmx_uq(regs,|,regd) /* 1x64 bitwise eXclusive OR */ #define pxor_m2r(var, reg) mmx_uq(var,^,reg) #define pxor_r2r(regs, regd) mmx_uq(regs,^,regd) /* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality (resulting fields are either 0 or -1) */ #define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg) #define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd) #define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard) #define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg) #define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd) #define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard) #define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg) #define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd) #define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard) /* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than (resulting fields are either 0 or -1) */ #define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg) #define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd) #define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard) #define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg) #define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd) #define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard) #define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg) #define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd) #define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard) /* 1x64, 2x32, and 4x16 Parallel Shift Left Logical */ #define psllq_i2r(imm, reg) mmx_m2r(psllq, imm, reg) #define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg) #define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd) #define psllq(vars, vard) mmx_m2m(psllq, vars, vard) #define pslld_i2r(imm, reg) mmx_m2r(pslld, imm, reg) #define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg) #define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd) #define pslld(vars, vard) mmx_m2m(pslld, vars, vard) #define psllw_i2r(imm, reg) mmx_m2r(psllw, imm, reg) #define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg) #define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd) #define psllw(vars, vard) mmx_m2m(psllw, vars, vard) /* 1x64, 2x32, and 4x16 Parallel Shift Right Logical */ #define psrlq_i2r(imm, reg) mmx_m2r(psrlq, imm, reg) #define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg) #define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd) #define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard) #define psrld_i2r(imm, reg) mmx_m2r(psrld, imm, reg) #define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg) #define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd) #define psrld(vars, vard) mmx_m2m(psrld, vars, vard) #define psrlw_i2r(imm, reg) mmx_m2r(psrlw, imm, reg) #define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg) #define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd) #define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard) /* 2x32 and 4x16 Parallel Shift Right Arithmetic */ #define psrad_i2r(imm, reg) mmx_m2r(psrad, imm, reg) #define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg) #define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd) #define psrad(vars, vard) mmx_m2m(psrad, vars, vard) #define psraw_i2r(imm, reg) mmx_m2r(psraw, imm, reg) #define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg) #define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd) #define psraw(vars, vard) mmx_m2m(psraw, vars, vard) /* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate (packs source and dest fields into dest in that order) */ #define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg) #define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd) #define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard) #define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg) #define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd) #define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard) /* 4x16->8x8 PACK and Unsigned Saturate (packs source and dest fields into dest in that order) */ #define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg) #define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd) #define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard) /* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low (interleaves low half of dest with low half of source as padding in each result field) */ #define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg) #define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd) #define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard) #define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg) #define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd) #define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard) #define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg) #define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd) #define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard) /* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High (interleaves high half of dest with high half of source as padding in each result field) */ #define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg) #define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd) #define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard) #define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg) #define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd) #define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard) #define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg) #define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd) #define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard) /* Empty MMx State (used to clean-up when going from mmx to float use of the registers that are shared by both; note that there is no float-to-mmx operation needed, because only the float tag word info is corruptible) */ #ifdef MMX_TRACE #define emms() \ { \ fprintf(stderr, "emms()\n"); \ __asm__ __volatile__ ("emms"); \ } #else #define emms() __asm__ __volatile__ ("emms") #endif #endif Mx44/mmx.h0000644000076400007640000005556410232730174011272 0ustar jensjens/* mmx.h MultiMedia eXtensions GCC interface library for IA32. To use this library, simply include this header file and compile with GCC. You MUST have inlining enabled in order for mmx_ok() to work; this can be done by simply using -O on the GCC command line. Compiling with -DMMX_TRACE will cause detailed trace output to be sent to stderr for each mmx operation. This adds lots of code, and obviously slows execution to a crawl, but can be very useful for debugging. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE. 1997-98 by H. Dietz and R. Fisher History: 97-98* R.Fisher Early versions 980501 R.Fisher Original Release 980611* H.Dietz Rewrite, correctly implementing inlines, and R.Fisher including direct register accesses. 980616 R.Fisher Release of 980611 as 980616. 980714 R.Fisher Minor corrections to Makefile, etc. 980715 R.Fisher mmx_ok() now prevents optimizer from using clobbered values. mmx_ok() now checks if cpuid instruction is available before trying to use it. 980726* R.Fisher mm_support() searches for AMD 3DNow, Cyrix Extended MMX, and standard MMX. It returns a value which is positive if any of these are supported, and can be masked with constants to see which. mmx_ok() is now a call to this 980726* R.Fisher Added i2r support for shift functions 980919 R.Fisher Fixed AMD extended feature recognition bug. 980921 R.Fisher Added definition/check for _MMX_H. Added "float s[2]" to mmx_t for use with 3DNow and EMMX. So same mmx_t can be used. 981013 R.Fisher Fixed cpuid function 1 bug (looked at wrong reg) Fixed psllq_i2r error in mmxtest.c * Unreleased (internal or interim) versions Notes: It appears that the latest gas has the pand problem fixed, therefore I'll undefine BROKEN_PAND by default. String compares may be quicker than the multiple test/jumps in vendor test sequence in mmx_ok(), but I'm not concerned with that right now. Acknowledgments: Jussi Laako for pointing out the errors ultimately found to be connected to the failure to notify the optimizer of clobbered values. Roger Hardiman for reminding us that CPUID isn't everywhere, and that someone may actually try to use this on a machine without CPUID. Also for suggesting code for checking this. Robert Dale for pointing out the AMD recognition bug. Jimmy Mayfield and Carl Witty for pointing out the Intel recognition bug. Carl Witty for pointing out the psllq_i2r test bug. */ #ifndef _MMX_H #define _MMX_H /* Warning: at this writing, the version of GAS packaged with most Linux distributions does not handle the parallel AND operation mnemonic correctly. If the symbol BROKEN_PAND is defined, a slower alternative coding will be used. If execution of mmxtest results in an illegal instruction fault, define this symbol. */ #undef BROKEN_PAND /* The type of an value that fits in an MMX register (note that long long constant values MUST be suffixed by LL and unsigned long long values by ULL, lest they be truncated by the compiler) */ typedef union { long long q; /* Quadword 64-bit value */ unsigned long long uq; /* Unsigned Quadword */ int d[2]; /* 2 Doubleword (32-bit) values */ unsigned int ud[2]; /* 2 Unsigned Doubleword */ short w[4]; /* 4 Word (16-bit) values */ unsigned short uw[4]; /* 4 Unsigned Word */ char b[8]; /* 8 Byte (8-bit) values */ unsigned char ub[8]; /* 8 Unsigned Byte */ float s[2]; /* Single-precision (32-bit) value */ } mmx_t; /* Function to test if multimedia instructions are supported... */ static inline int mm_support(void) { /* Returns 1 if MMX instructions are supported, 3 if Cyrix MMX and Extended MMX instructions are supported 5 if AMD MMX and 3DNow! instructions are supported 0 if hardware does not support any of these */ register int rval = 0; __asm__ //__volatile__ ( "\n\t" /* See if CPUID instruction is supported ... */ /* ... Get copies of EFLAGS into eax and ecx */ "pushf\n\t" "popl %%eax\n\t" "movl %%eax, %%ecx\n\t" /* ... Toggle the ID bit in one copy and store */ /* to the EFLAGS reg */ "xorl $0x200000, %%eax\n\t" "push %%eax\n\t" "popf\n\t" /* ... Get the (hopefully modified) EFLAGS */ "pushf\n\t" "popl %%eax\n\t" /* ... Compare and test result */ "xorl %%eax, %%ecx\n\t" "testl $0x200000, %%ecx\n\t" "jz NotSupported1\n\t" /* Nothing supported */ /* Get standard CPUID information, and */ /* go to a specific vendor section */ "movl $0, %%eax\n\t" "cpuid\n\t" /* Check for Intel */ "cmpl $0x756e6547, %%ebx\n\t" "jne TryAMD\n\t" "cmpl $0x49656e69, %%edx\n\t" "jne TryAMD\n\t" "cmpl $0x6c65746e, %%ecx\n" "jne TryAMD\n\t" "jmp Intel\n\t" /* Check for AMD */ "\nTryAMD:\n\t" "cmpl $0x68747541, %%ebx\n\t" "jne TryCyrix\n\t" "cmpl $0x69746e65, %%edx\n\t" "jne TryCyrix\n\t" "cmpl $0x444d4163, %%ecx\n" "jne TryCyrix\n\t" "jmp AMD\n\t" /* Check for Cyrix */ "\nTryCyrix:\n\t" "cmpl $0x69727943, %%ebx\n\t" "jne NotSupported2\n\t" "cmpl $0x736e4978, %%edx\n\t" "jne NotSupported3\n\t" "cmpl $0x64616574, %%ecx\n\t" "jne NotSupported4\n\t" /* Drop through to Cyrix... */ /* Cyrix Section */ /* See if extended CPUID is supported */ "movl $0x80000000, %%eax\n\t" "cpuid\n\t" "cmpl $0x80000000, %%eax\n\t" "jl MMXtest\n\t" /* Try standard CPUID instead */ /* Extended CPUID supported, so get extended features */ "movl $0x80000001, %%eax\n\t" "cpuid\n\t" "testl $0x00800000, %%eax\n\t" /* Test for MMX */ "jz NotSupported5\n\t" /* MMX not supported */ "testl $0x01000000, %%eax\n\t" /* Test for Ext'd MMX */ "jnz EMMXSupported\n\t" "movl $1, %0:\n\n\t" /* MMX Supported */ "jmp Return\n\n" "EMMXSupported:\n\t" "movl $3, %0:\n\n\t" /* EMMX and MMX Supported */ "jmp Return\n\t" /* AMD Section */ "AMD:\n\t" /* See if extended CPUID is supported */ "movl $0x80000000, %%eax\n\t" "cpuid\n\t" "cmpl $0x80000000, %%eax\n\t" "jl MMXtest\n\t" /* Try standard CPUID instead */ /* Extended CPUID supported, so get extended features*/ "movl $0x80000001, %%eax\n\t" "cpuid\n\t" "testl $0x00800000, %%edx\n\t" /* Test for MMX */ "jz NotSupported6\n\t" /* MMX not supported */ "testl $0x80000000, %%edx\n\t" /* Test for 3DNow! */ "jnz ThreeDNowSupported\n\t" "movl $1, %0:\n\n\t" /* MMX Supported */ "jmp Return\n\n" "ThreeDNowSupported:\n\t" "movl $5, %0:\n\n\t" /* 3DNow! and MMX Supported */ "jmp Return\n\t" /* Intel Section */ "Intel:\n\t" /* Check for MMX */ "MMXtest:\n\t" "movl $1, %%eax\n\t" "cpuid\n\t" "testl $0x00800000, %%edx\n\t" /* Test for MMX */ "jz NotSupported7\n\t" /* MMX Not supported */ "movl $1, %0:\n\n\t" /* MMX Supported */ "jmp Return\n\t" /* Nothing supported */ "\nNotSupported1:\n\t" "#movl $101, %0:\n\n\t" "\nNotSupported2:\n\t" "#movl $102, %0:\n\n\t" "\nNotSupported3:\n\t" "#movl $103, %0:\n\n\t" "\nNotSupported4:\n\t" "#movl $104, %0:\n\n\t" "\nNotSupported5:\n\t" "#movl $105, %0:\n\n\t" "\nNotSupported6:\n\t" "#movl $106, %0:\n\n\t" "\nNotSupported7:\n\t" "#movl $107, %0:\n\t" "movl $0, %0:\n\n\t" "Return:\n\t" : "=a" (rval):: "eax", "ebx", "ecx", "edx" ); /* Return */ return(rval); } /* Function to test if mmx instructions are supported... */ inline extern int mmx_ok(void) { /* Returns 1 if MMX instructions are supported, 0 otherwise */ return ( mm_support() & 0x1 ); } /* Helper functions for the instruction macros that follow... (note that memory-to-register, m2r, instructions are nearly as efficient as register-to-register, r2r, instructions; however, memory-to-memory instructions are really simulated as a convenience, and are only 1/3 as efficient) */ #ifdef MMX_TRACE /* Include the stuff for printing a trace to stderr... */ #include #define mmx_i2r(op, imm, reg) \ { \ mmx_t mmx_trace; \ mmx_trace = (imm); \ fprintf(stderr, #op "_i2r(" #imm "=0x%016llx, ", mmx_trace.q); \ __asm__ __volatile__ ("movq %%" #reg ", %0" \ : "=X" (mmx_trace) \ : /* nothing */ ); \ fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \ __asm__ __volatile__ (#op " %0, %%" #reg \ : /* nothing */ \ : "X" (imm)); \ __asm__ __volatile__ ("movq %%" #reg ", %0" \ : "=X" (mmx_trace) \ : /* nothing */ ); \ fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \ } #define mmx_m2r(op, mem, reg) \ { \ mmx_t mmx_trace; \ mmx_trace = (mem); \ fprintf(stderr, #op "_m2r(" #mem "=0x%016llx, ", mmx_trace.q); \ __asm__ __volatile__ ("movq %%" #reg ", %0" \ : "=X" (mmx_trace) \ : /* nothing */ ); \ fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \ __asm__ __volatile__ (#op " %0, %%" #reg \ : /* nothing */ \ : "X" (mem)); \ __asm__ __volatile__ ("movq %%" #reg ", %0" \ : "=X" (mmx_trace) \ : /* nothing */ ); \ fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \ } #define mmx_r2m(op, reg, mem) \ { \ mmx_t mmx_trace; \ __asm__ __volatile__ ("movq %%" #reg ", %0" \ : "=X" (mmx_trace) \ : /* nothing */ ); \ fprintf(stderr, #op "_r2m(" #reg "=0x%016llx, ", mmx_trace.q); \ mmx_trace = (mem); \ fprintf(stderr, #mem "=0x%016llx) => ", mmx_trace.q); \ __asm__ __volatile__ (#op " %%" #reg ", %0" \ : "=X" (mem) \ : /* nothing */ ); \ mmx_trace = (mem); \ fprintf(stderr, #mem "=0x%016llx\n", mmx_trace.q); \ } #define mmx_r2r(op, regs, regd) \ { \ mmx_t mmx_trace; \ __asm__ __volatile__ ("movq %%" #regs ", %0" \ : "=X" (mmx_trace) \ : /* nothing */ ); \ fprintf(stderr, #op "_r2r(" #regs "=0x%016llx, ", mmx_trace.q); \ __asm__ __volatile__ ("movq %%" #regd ", %0" \ : "=X" (mmx_trace) \ : /* nothing */ ); \ fprintf(stderr, #regd "=0x%016llx) => ", mmx_trace.q); \ __asm__ __volatile__ (#op " %" #regs ", %" #regd); \ __asm__ __volatile__ ("movq %%" #regd ", %0" \ : "=X" (mmx_trace) \ : /* nothing */ ); \ fprintf(stderr, #regd "=0x%016llx\n", mmx_trace.q); \ } #define mmx_m2m(op, mems, memd) \ { \ mmx_t mmx_trace; \ mmx_trace = (mems); \ fprintf(stderr, #op "_m2m(" #mems "=0x%016llx, ", mmx_trace.q); \ mmx_trace = (memd); \ fprintf(stderr, #memd "=0x%016llx) => ", mmx_trace.q); \ __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ #op " %1, %%mm0\n\t" \ "movq %%mm0, %0" \ : "=X" (memd) \ : "X" (mems)); \ mmx_trace = (memd); \ fprintf(stderr, #memd "=0x%016llx\n", mmx_trace.q); \ } #else /* These macros are a lot simpler without the tracing... */ #define mmx_i2r(op, imm, reg) \ __asm__ __volatile__ (#op " $" #imm "0, %%" #reg \ : /* nothing */ \ : /* nothing */) #define mmx_m2r(op, mem, reg) \ __asm__ __volatile__ (#op " %0, %%" #reg \ : /* nothing */ \ : "X" (mem)) #define mmx_r2m(op, reg, mem) \ __asm__ __volatile__ (#op " %%" #reg ", %0" \ : "=X" (mem) \ : /* nothing */ ) #define mmx_r2r(op, regs, regd) \ __asm__ __volatile__ (#op " %" #regs ", %" #regd) #define mmx_m2m(op, mems, memd) \ __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ #op " %1, %%mm0\n\t" \ "movq %%mm0, %0" \ : "=X" (memd) \ : "X" (mems)) #endif /* 1x64 MOVe Quadword (this is both a load and a store... in fact, it is the only way to store) */ #define movq_i2r(var, reg) mmx_i2r(movq, var, reg) #define movq_m2r(var, reg) mmx_m2r(movq, var, reg) #define movq_r2m(reg, var) mmx_r2m(movq, reg, var) #define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd) #define movq(vars, vard) \ __asm__ __volatile__ ("movq %1, %%mm0\n\t" \ "movq %%mm0, %0" \ : "=X" (vard) \ : "X" (vars)) /* 1x32 MOVe Doubleword (like movq, this is both load and store... but is most useful for moving things between mmx registers and ordinary registers) */ #define movd_m2r(var, reg) mmx_m2r(movd, var, reg) #define movd_r2m(reg, var) mmx_r2m(movd, reg, var) #define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd) #define movd(vars, vard) \ __asm__ __volatile__ ("movd %1, %%mm0\n\t" \ "movd %%mm0, %0" \ : "=X" (vard) \ : "X" (vars)) /* 2x32, 4x16, and 8x8 Parallel ADDs */ #define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg) #define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd) #define paddd(vars, vard) mmx_m2m(paddd, vars, vard) #define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg) #define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd) #define paddw(vars, vard) mmx_m2m(paddw, vars, vard) #define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg) #define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd) #define paddb(vars, vard) mmx_m2m(paddb, vars, vard) /* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic */ #define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg) #define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd) #define paddsw(vars, vard) mmx_m2m(paddsw, vars, vard) #define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg) #define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd) #define paddsb(vars, vard) mmx_m2m(paddsb, vars, vard) /* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic */ #define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg) #define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd) #define paddusw(vars, vard) mmx_m2m(paddusw, vars, vard) #define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg) #define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd) #define paddusb(vars, vard) mmx_m2m(paddusb, vars, vard) /* 2x32, 4x16, and 8x8 Parallel SUBs */ #define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg) #define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd) #define psubd(vars, vard) mmx_m2m(psubd, vars, vard) #define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg) #define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd) #define psubw(vars, vard) mmx_m2m(psubw, vars, vard) #define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg) #define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd) #define psubb(vars, vard) mmx_m2m(psubb, vars, vard) /* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic */ #define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg) #define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd) #define psubsw(vars, vard) mmx_m2m(psubsw, vars, vard) #define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg) #define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd) #define psubsb(vars, vard) mmx_m2m(psubsb, vars, vard) /* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic */ #define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg) #define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd) #define psubusw(vars, vard) mmx_m2m(psubusw, vars, vard) #define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg) #define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd) #define psubusb(vars, vard) mmx_m2m(psubusb, vars, vard) /* 4x16 Parallel MULs giving Low 4x16 portions of results */ #define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg) #define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd) #define pmullw(vars, vard) mmx_m2m(pmullw, vars, vard) /* 4x16 Parallel MULs giving High 4x16 portions of results */ #define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg) #define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd) #define pmulhw(vars, vard) mmx_m2m(pmulhw, vars, vard) /* 4x16->2x32 Parallel Mul-ADD (muls like pmullw, then adds adjacent 16-bit fields in the multiply result to make the final 2x32 result) */ #define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg) #define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd) #define pmaddwd(vars, vard) mmx_m2m(pmaddwd, vars, vard) /* 1x64 bitwise AND */ #ifdef BROKEN_PAND #define pand_m2r(var, reg) \ { \ mmx_m2r(pandn, (mmx_t) -1LL, reg); \ mmx_m2r(pandn, var, reg); \ } #define pand_r2r(regs, regd) \ { \ mmx_m2r(pandn, (mmx_t) -1LL, regd); \ mmx_r2r(pandn, regs, regd) \ } #define pand(vars, vard) \ { \ movq_m2r(vard, mm0); \ mmx_m2r(pandn, (mmx_t) -1LL, mm0); \ mmx_m2r(pandn, vars, mm0); \ movq_r2m(mm0, vard); \ } #else #define pand_m2r(var, reg) mmx_m2r(pand, var, reg) #define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd) #define pand(vars, vard) mmx_m2m(pand, vars, vard) #endif /* 1x64 bitwise AND with Not the destination */ #define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg) #define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd) #define pandn(vars, vard) mmx_m2m(pandn, vars, vard) /* 1x64 bitwise OR */ #define por_m2r(var, reg) mmx_m2r(por, var, reg) #define por_r2r(regs, regd) mmx_r2r(por, regs, regd) #define por(vars, vard) mmx_m2m(por, vars, vard) /* 1x64 bitwise eXclusive OR */ #define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg) #define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd) #define pxor(vars, vard) mmx_m2m(pxor, vars, vard) /* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality (resulting fields are either 0 or -1) */ #define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg) #define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd) #define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard) #define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg) #define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd) #define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard) #define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg) #define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd) #define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard) /* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than (resulting fields are either 0 or -1) */ #define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg) #define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd) #define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard) #define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg) #define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd) #define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard) #define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg) #define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd) #define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard) /* 1x64, 2x32, and 4x16 Parallel Shift Left Logical */ #define psllq_i2r(imm, reg) mmx_m2r(psllq, imm, reg) #define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg) #define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd) #define psllq(vars, vard) mmx_m2m(psllq, vars, vard) #define pslld_i2r(imm, reg) mmx_m2r(pslld, imm, reg) #define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg) #define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd) #define pslld(vars, vard) mmx_m2m(pslld, vars, vard) #define psllw_i2r(imm, reg) mmx_m2r(psllw, imm, reg) #define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg) #define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd) #define psllw(vars, vard) mmx_m2m(psllw, vars, vard) /* 1x64, 2x32, and 4x16 Parallel Shift Right Logical */ #define psrlq_i2r(imm, reg) mmx_m2r(psrlq, imm, reg) #define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg) #define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd) #define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard) #define psrld_i2r(imm, reg) mmx_m2r(psrld, imm, reg) #define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg) #define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd) #define psrld(vars, vard) mmx_m2m(psrld, vars, vard) #define psrlw_i2r(imm, reg) mmx_m2r(psrlw, imm, reg) #define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg) #define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd) #define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard) /* 2x32 and 4x16 Parallel Shift Right Arithmetic */ #define psrad_i2r(imm, reg) mmx_m2r(psrad, imm, reg) #define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg) #define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd) #define psrad(vars, vard) mmx_m2m(psrad, vars, vard) #define psraw_i2r(imm, reg) mmx_m2r(psraw, imm, reg) #define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg) #define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd) #define psraw(vars, vard) mmx_m2m(psraw, vars, vard) /* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate (packs source and dest fields into dest in that order) */ #define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg) #define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd) #define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard) #define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg) #define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd) #define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard) /* 4x16->8x8 PACK and Unsigned Saturate (packs source and dest fields into dest in that order) */ #define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg) #define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd) #define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard) /* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low (interleaves low half of dest with low half of source as padding in each result field) */ #define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg) #define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd) #define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard) #define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg) #define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd) #define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard) #define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg) #define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd) #define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard) /* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High (interleaves high half of dest with high half of source as padding in each result field) */ #define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg) #define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd) #define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard) #define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg) #define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd) #define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard) #define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg) #define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd) #define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard) /* Empty MMx State (used to clean-up when going from mmx to float use of the registers that are shared by both; note that there is no float-to-mmx operation needed, because only the float tag word info is corruptible) */ #ifdef MMX_TRACE #define emms() \ { \ fprintf(stderr, "emms()\n"); \ __asm__ __volatile__ ("emms"); \ } #else #define emms() __asm__ __volatile__ ("emms") #endif #endif Mx44/mx44.h0000644000076400007640000002130010242557305011246 0ustar jensjens/* * This software is released under GPL. If you don't know what that is * immediately point your webbrowser to http://www.gnu.org and read * all about it. * * The short version: You can modify the sources for your own purposes * but you must include the new source if you distribute a derived work. * * (C) 2002, 2003, 2004, 2005 Jens M Andreasen * * * * ( * ) * c[] * */ /* // binary pattern #define oooo 0 #define oooi 1 #define ooio 2 #define ooii 3 #define oioo 4 #define oioi 5 #define oiio 6 #define oiii 7 #define iooo 8 #define iooi 9 #define ioio A #define ioii B #define iioo C #define iioi D #define iiio E #define iiii F #define B16_PASTE(a,b,c,d) 0x ## a ## b ## c ## d #define B16(a,b,c,d) B16_PASTE(a,b,c,d) */ #ifndef MX44_H #define MX44_H #include "mmx.h" #include //#define OMNIMODE #ifdef OMNIMODE // Tim suggested a smaller footprint #define MIDICHANNELS 1 #define CHANNELMASK 0x0 #else // Elsewise we are multitimbral #define MIDICHANNELS 16 #define CHANNELMASK 0x0F #endif #define SAMPLES 32 // number of samples to produce before polling midi #define ENVLOOP 2 // number of envelope updates during sample production #define OPLOOP SAMPLES/ENVLOOP #define OUTBUF SAMPLES * 2 // stereo == 2 /* * Data for a running envelope * */ typedef struct { // Each envelope has a current value .. mmx_t state02; // d mmx_t state13; // d // .. and a precalculated +/- value to be added .. mmx_t delta02; // d mmx_t delta13; // d // .. for exactly x samples .. int time[4][8]; // [op][step] int time_count[4]; // [op] // .. before being replaced by the next precalculated delta value int delta_value[4][9]; // [op][step] int step[4]; // op int sustain[4]; // middle level in the sustain loop int release[4]; // the release deltas cannot be precalculated int running; // bit 0 - 3 set while env still running int audible; // bit 0 - 3 set if this voice is in the mix }Mx44env; /* * Data for a single running voice * */ typedef struct _mx44voice { // mmx_t samples[SAMPLES]; // mmx_t delay[1024]; // Delay on am/pm feedback; // intonation parameters int intonation[4][2]; // w (op) [amount | decay] // state of oscillators mmx_t state02; // d (op 0, op 2) mmx_t state13; // d (op 1, op3) // frequency of oscillators mmx_t delta02; // d mmx_t delta13; // d // Each oscillator is phase- and amplitude modulated // by every other oscillators previous output // Modulaton arguments are skewed diagonally as in: // x[3](op2,op1,op0,op3) // x[2](op1,op0,op3,op2) // x[1](op0,op3,op2,op1) // x[0](op3,op2,op1,op0) mmx_t pm[4]; // w mmx_t am[4]; // w // pseudo sin is averaged from two bumpy approximations // running 60 degrees apart at the same frequency. // Optionally one part can be "octave doubled" and // crossmodulated to a second set of waweshapes. mmx_t od; // w (op) mmx_t complexwawe; // Magic Number Modulation mmx_t magicnumber; mmx_t magicmodulation; mmx_t magicmodulation2; // some switches mmx_t lowpass; mmx_t waweshape; // Stereo mix mmx_t mixL; // w mmx_t mixR; // w mmx_t wheel; // w // Final utput of oscillator 0,1,2,3 mmx_t out; // w short delay_index; short delay_time; int delay_osc_state; int delay_osc_delta; int delay_osc_amount; // Next voice in an asignment que (running, hold, released, silent) struct _mx44voice *next; struct _mx44voice *previous; // envelopes Mx44env env; unsigned char channel; // channel number unsigned char key; short padding[3]; }Mx44voice; // The patch sets up the initial state according to // key and velocity etc #define WAWEBUTTON 1 #define WHEELBUTTON 2 #define INVERTWHEELBUTTON 4 #define LOWPASSBUTTON 8 #define WAWESHAPEBUTTON 16 #define PHASEFOLLOWKEYBUTTON 32 #define MAGICBUTTON 64 typedef struct // Mx44patch { short pm[4][4]; // [destination] [source] short am[4][4]; short mix[4][2]; // [op] [left | right] short env_level[4][8]; // [op] [stage] short env_time[4][8]; short harmonic[4]; short intonation[4][2]; // [op] [amount | decay] short detune[4]; short velocityfollow[4]; unsigned char od[4]; // octave doubling unsigned char button[4]; // WAWE, WHEEL, LOWPASS and WAWESHAPE // key bias short breakpoint[4]; // [op] short keybias[4][2]; // [op] [hi | lo value] // env keyfollow short keyfollow[4][2]; // [op] [attack | sustain-loop] // key velocity short velocity[4]; // [op] short phase[4][2]; // [op] [offset | velocityfollow] char name[32]; short fx_delay[5]; // delay time, spread, feedback, modulation and outlevel short fx_overdrive; // distortion char lfo_button[2]; // loop, aftertouch . short lfo[6]; // lfo rate 1, rate 2, level 1, level 2, time 1 and time 2 // unused //---------- short mod_delay; short mod_keyfollow; short mod_freq; short mod_freq_keyfollow; short mod_freg_amount; short unused[46]; } Mx44patch; typedef struct { // Mx44state mmx_t mmxtmp[2]; mmx_t wheel; Mx44voice *voices; Mx44voice *que[5]; // assigned, held, released, silent, excess held Mx44voice *last[4]; Mx44voice *keyboard[MIDICHANNELS][128][4]; int keyTable[128]; // some controllers char holdpedal[MIDICHANNELS]; short pitchbend[MIDICHANNELS]; char modulation[MIDICHANNELS]; char mod_now[MIDICHANNELS]; pthread_mutex_t busy; pthread_t midi_thread; pthread_attr_t midi_thread_attr; struct sched_param midi_thread_param; int lfo_env_state[MIDICHANNELS]; int lfo_rate_state[MIDICHANNELS]; int current; // number of prerendered samples already delivered int isGraphic; int maxpoly; int samplerate; Mx44patch patch[128]; // preset patches Mx44patch tmpPatch[MIDICHANNELS]; // actual editable and sounding patch char patchNo[MIDICHANNELS]; // chosen preset number char monomode[MIDICHANNELS]; }Mx44state; extern Mx44state* mx44_new(int maxpolyphony,char* patch_path); // middle A == 440.0 extern void mx44_reset(Mx44state* mx44,double tuningfork,int samplerate); extern void mx44_pgmchange(Mx44state* mx44,int channel,int patchnumber); extern void mx44_noteon(Mx44state* mx44,int channel,int key,int velocity); extern void mx44_noteoff(Mx44state* mx44,int channel,int key,int velocity); extern void mx44_pitchbend(Mx44state* mx44,int channel,int data1,int data2); extern void mx44_control(Mx44state* mx44,int channel,int control,int data); extern void mx44_chanpress(Mx44state* mx44,int channel,int data); extern void mx44_dispose(Mx44state * mx44); #ifdef OMNIMODE // syntax checking only ... // use with debugger at your own risk .. extern void omni(Mx4state* mx4, int request,float* port_left, float* port_right) #endif extern int mx44_play(Mx44state* mx44,short * stereo_out); #endif /* Table comparing ratios between Thomas Young 1799 well temperament to equal temperament C 1.0 1.0 C# 1.055730636 1.059463094 D 1.119771437 1.122462048 Eb 1.187696971 1.189207115 E 1.253888072 1.259921050 F 1.334745462 1.334839854 F# 1.407640848 1.414213562 G 1.496510232 1.498307077 Ab 1.583595961 1.587401052 A 1.675749414 1.681792831 Bb 1.781545449 1.781797436 B 1.878842233 1.887748625 C 2.0 2.0 cent == 1.0005777895 == 2^(1/1200) 100 cent == cent^100 == one semitone A table for Pythagorian tuning: Pitch: C C# D Eb E F F# G G# A A# B C Cents: 0 113.7 203.9 294.1 407.8 498 611.7 702 792.2 905.9 996.1 1109.8 1200 Ratios: 1/1 2187 9/8 32/27 81/64 4/3 729/512 3/2 128/81 27/16 16/9 243/128 2/1 / 2048 A table for meantone tuning by Pietro Aaron (1523). Pitch: C C# D Eb E F F# G G# A A# B C Cents: 0 76.0 193.2 310.3 386.3 503.4 579.5 696.8 772.6 889.7 1006.8 1082.9 1200 A table for Werckmeister III (1691) is as follows: Pitch: C C# D Eb E F F# G G# A A# B C Cents: 0 90.225 192.18 294.135 390.225 498.045 588.27 696.09 792.18 888.27 996.09 1092.18 1200 A table for Young (1799): Pitch: C C# D Eb E F F# G G# A A# B C Cents: 0 93.9 195.8 297.8 391.7 499.9 591.9 697.9 795.8 893.8 999.8 1091.8 1200 (new tuning :name 'just :ratios '((1 c) (16/15 cs) (9/8 d) (6/5 ds ) (5/4 e) (4/3 f) (45/32 fs ) (3/2 g) (8/5 gs ) (5/3 a) (16/9 as) (15/8 b) 2/1)) (new tuning :name 'werckmeister3 :cents '((0 c) (94 cs) (192 d) (278 ds) (390 e) (475 f) (588 fs) (696 g) (790 gs) (888 a) (975 as) (1092 b) 1200)) */ Mx44/sse.h0000644000076400007640000002234010202153152011235 0ustar jensjens/* * sse.h * Copyright (C) 1999-2003 R. Fisher * * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. * See http://libmpeg2.sourceforge.net/ for updates. * * mpeg2dec is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mpeg2dec is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef union { float sf[4]; /* Single-precision (32-bit) value */ } ATTR_ALIGN(16) sse_t; /* On a 16 byte (128-bit) boundary */ #define sse_i2r(op, imm, reg) \ __asm__ __volatile__ (#op " %0, %%" #reg \ : /* nothing */ \ : "X" (imm) ) #define sse_m2r(op, mem, reg) \ __asm__ __volatile__ (#op " %0, %%" #reg \ : /* nothing */ \ : "X" (mem)) #define sse_r2m(op, reg, mem) \ __asm__ __volatile__ (#op " %%" #reg ", %0" \ : "=X" (mem) \ : /* nothing */ ) #define sse_r2r(op, regs, regd) \ __asm__ __volatile__ (#op " %" #regs ", %" #regd) #define sse_r2ri(op, regs, regd, imm) \ __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ : /* nothing */ \ : "X" (imm) ) #define sse_m2ri(op, mem, reg, subop) \ __asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \ : /* nothing */ \ : "X" (mem)) #define movaps_m2r(var, reg) sse_m2r(movaps, var, reg) #define movaps_r2m(reg, var) sse_r2m(movaps, reg, var) #define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd) #define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var) #define movups_m2r(var, reg) sse_m2r(movups, var, reg) #define movups_r2m(reg, var) sse_r2m(movups, reg, var) #define movups_r2r(regs, regd) sse_r2r(movups, regs, regd) #define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd) #define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd) #define movhps_m2r(var, reg) sse_m2r(movhps, var, reg) #define movhps_r2m(reg, var) sse_r2m(movhps, reg, var) #define movlps_m2r(var, reg) sse_m2r(movlps, var, reg) #define movlps_r2m(reg, var) sse_r2m(movlps, reg, var) #define movss_m2r(var, reg) sse_m2r(movss, var, reg) #define movss_r2m(reg, var) sse_r2m(movss, reg, var) #define movss_r2r(regs, regd) sse_r2r(movss, regs, regd) #define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index) #define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index) #define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg) #define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg) #define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg) #define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg) #define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg) #define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg) #define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg) #define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg) #define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) #define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) #define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) #define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) #define movmskps(xmmreg, reg) \ __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) #define addps_m2r(var, reg) sse_m2r(addps, var, reg) #define addps_r2r(regs, regd) sse_r2r(addps, regs, regd) #define addss_m2r(var, reg) sse_m2r(addss, var, reg) #define addss_r2r(regs, regd) sse_r2r(addss, regs, regd) #define subps_m2r(var, reg) sse_m2r(subps, var, reg) #define subps_r2r(regs, regd) sse_r2r(subps, regs, regd) #define subss_m2r(var, reg) sse_m2r(subss, var, reg) #define subss_r2r(regs, regd) sse_r2r(subss, regs, regd) #define mulps_m2r(var, reg) sse_m2r(mulps, var, reg) #define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd) #define mulss_m2r(var, reg) sse_m2r(mulss, var, reg) #define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd) #define divps_m2r(var, reg) sse_m2r(divps, var, reg) #define divps_r2r(regs, regd) sse_r2r(divps, regs, regd) #define divss_m2r(var, reg) sse_m2r(divss, var, reg) #define divss_r2r(regs, regd) sse_r2r(divss, regs, regd) #define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg) #define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd) #define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg) #define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd) #define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg) #define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd) #define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg) #define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd) #define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg) #define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd) #define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg) #define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd) #define andps_m2r(var, reg) sse_m2r(andps, var, reg) #define andps_r2r(regs, regd) sse_r2r(andps, regs, regd) #define andnps_m2r(var, reg) sse_m2r(andnps, var, reg) #define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd) #define orps_m2r(var, reg) sse_m2r(orps, var, reg) #define orps_r2r(regs, regd) sse_r2r(orps, regs, regd) #define xorps_m2r(var, reg) sse_m2r(xorps, var, reg) #define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd) #define maxps_m2r(var, reg) sse_m2r(maxps, var, reg) #define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd) #define maxss_m2r(var, reg) sse_m2r(maxss, var, reg) #define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd) #define minps_m2r(var, reg) sse_m2r(minps, var, reg) #define minps_r2r(regs, regd) sse_r2r(minps, regs, regd) #define minss_m2r(var, reg) sse_m2r(minss, var, reg) #define minss_r2r(regs, regd) sse_r2r(minss, regs, regd) #define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op) #define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op) #define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0) #define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0) #define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1) #define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1) #define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2) #define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2) #define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3) #define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3) #define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4) #define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4) #define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5) #define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5) #define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6) #define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6) #define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7) #define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7) #define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op) #define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op) #define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0) #define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0) #define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1) #define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1) #define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2) #define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2) #define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3) #define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3) #define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4) #define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4) #define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5) #define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5) #define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6) #define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6) #define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7) #define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7) #define comiss_m2r(var, reg) sse_m2r(comiss, var, reg) #define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd) #define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg) #define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd) #define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg) #define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd) #define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg) #define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd) #define fxrstor(mem) \ __asm__ __volatile__ ("fxrstor %0" \ : /* nothing */ \ : "X" (mem)) #define fxsave(mem) \ __asm__ __volatile__ ("fxsave %0" \ : /* nothing */ \ : "X" (mem)) #define stmxcsr(mem) \ __asm__ __volatile__ ("stmxcsr %0" \ : /* nothing */ \ : "X" (mem)) #define ldmxcsr(mem) \ __asm__ __volatile__ ("ldmxcsr %0" \ : /* nothing */ \ : "X" (mem)) Mx44/Makefile0000644000076400007640000000173210234200434011735 0ustar jensjens.SUFFIXES: .c $(SUFFIXES) TARGET = mx44 DIR = Mx44 CC = gcc GTK_CFLAGS = `pkg-config --cflags gtk+-2.0` GTK_LIBS = `pkg-config --libs gtk+-2.0` LIBS = $(GTK_LIBS) -lasound -ljack -lpthread -lm FLAGS = -O3 -Wall -pipe -fomit-frame-pointer -D_REENTRANT $(GTK_CFLAGS) # -msse SRCS = interface2.c mx44.c main.c INCLUDE = mx44.h old/mmx4.h OBJS = $(SRCS:.c=.o) $(TARGET): $(OBJS) $(CC) -D_REENTRANT -o $@ $(OBJS) $(LIBS) .c.o: $(CC) -c $(FLAGS) $< clean: rm -f $(TARGET) $(OBJS) core core.* *.bak *~ depend: makedepend -Y $(SRCS) &>/dev/null edit: exec emacs -font 9x15 $(INCLUDE) $(SRCS) Makefile& etag: rm TAGS;etags --members $(SRCS) $(INCLUDE) tar: cd ..; rm $(DIR).tar.gz ; tar -cf $(DIR).tar $(DIR)/*.c $(DIR)/*.h \ $(DIR)/Makefile $(DIR)/$(TARGET) $(DIR)/COPYING $(DIR)/mx41patch $(DIR)/old/*.h;\ gzip $(DIR).tar # DO NOT DELETE interface2.o: mx44.h mmx.h mx44.o: mx44.h mmx.h main.o: mx44.h mmx.h old/mmx4.h Mx44/mx440004711000000000000000000020672410254255412011041 0ustar rootrootELFP4`4 ("444hhhhdhd ||d|d@@((( Qtd/lib/ld-linux.so.2GNU$3K>Eqxg}t2+'~p@b5k6e,c{|?ZnAdPIVR. 0=%YrOSljf[w*1Lz"XWa4uvy   ):9/(JC BD-H<&7UM^ N;im\!Q`#o_F]TsG8h'(\\ RCQV\p^ 0X|d@Yv u |` e  q (  0 69'FR9/+ ;=\P_bB|On oğ   . 4 { =nu\_9\' \m @h8I^q~ n Be D5 _ܤO!am:M  ,h  Vp) + LaG < qyaG AP |U'K  ,hge  n < Y h1\I{ HP u`ny}u1e &t n9_  9K | < libgtk-x11-2.0.so.0gtk_hseparator_newgtk_toggle_button_get_typegtk_entry_set_textgtk_radio_button_get_typegtk_combo_box_new_textgtk_object_get_typegtk_rc_add_default_filegtk_toggle_button_get_activegtk_spin_button_set_numericgtk_combo_box_get_typegtk_misc_set_alignmentg_signal_emit_by_namegtk_widget_showgtk_combo_box_get_activegtk_toggle_button_set_activegtk_combo_box_append_textgtk_widget_set_size_requestg_signal_connect_datagtk_widget_set_namegtk_frame_newgtk_vseparator_newgtk_table_attachgtk_vscale_newgtk_object_set_datagtk_container_addgtk_table_get_typegtk_misc_get_typegtk_frame_set_shadow_typegtk_adjustment_set_valuegtk_label_newgtk_window_newgtk_window_get_typegtk_scale_get_typegtk_hscale_newgtk_label_get_typegtk_tooltips_newgtk_frame_get_typegtk_range_get_adjustmentgtk_widget_unrefgtk_window_set_titlegtk_entry_get_textgtk_spin_button_set_adjustmentgtk_adjustment_newgtk_container_set_border_widthgtk_initgtk_spin_button_newgtk_scale_set_draw_valuegtk_radio_button_get_groupgtk_main_quitgtk_widget_set_sensitivegtk_entry_get_typegtk_maingtk_spin_button_set_valuegtk_set_localegtk_object_set_data_fullgtk_tooltips_set_tipgtk_label_set_textgtk_entry_set_alignmentgtk_radio_button_newgtk_check_button_newgtk_label_set_justifygtk_combo_box_set_activegtk_adjustment_get_typegtk_range_set_invertedgtk_table_newgtk_entry_new_with_max_lengthg_timeout_addgtk_toggle_button_new_with_labelgtk_container_get_type_Jv_RegisterClassesgtk_button_new_with_labelgtk_widget_ref__gmon_start__gtk_widget_grab_focuslibgdk-x11-2.0.so.0libatk-1.0.so.0_DYNAMIC_fini_GLOBAL_OFFSET_TABLE_g_type_check_instance_castlibgdk_pixbuf-2.0.so.0libm.so.6sqrtldexpflibpangoxft-1.0.so.0libpangox-1.0.so.0libpango-1.0.so.0libgobject-2.0.so.0libgmodule-2.0.so.0libdl.so.2libglib-2.0.so.0libasound.so.2snd_seq_free_eventsnd_seq_poll_descriptorssnd_seq_opensnd_seq_create_simple_portsnd_seq_event_input_pendingsnd_seq_poll_descriptors_countsnd_seq_set_client_namesnd_seq_event_inputlibjack.so.0jack_get_sample_ratejack_port_registerjack_connectjack_client_newjack_activatejack_port_get_bufferjack_get_portsjack_set_process_callbackjack_port_namejack_on_shutdownlibpthread.so.0pthread_attr_initpthread_createlseekpthread_getschedparampthread_attr_setinheritschedpthread_setschedparamreadpthread_mutex_unlock_pthread_cleanup_pushpthread_mutex_destroypthread_mutex_lockpthread_mutex_initcloselibc.so.6strcpyioctlgetenv__strtol_internalusleepmemcpyperrorputsgetuidmallocsched_setschedulerfprintfsched_get_priority_max__strdupsetreuidmemsetpollsprintfstderrfwrite_IO_stdin_used__libc_start_mainsched_yieldfree__cxa_atexit_edata__bss_start_endGLIBC_2.0ALSA_0.9GLIBC_2.1.3GLIBC_2.1 ii  C y'w  0si  ii  ii  ii  e@h?eeeeeeeee e e e f ff fffff f$f(f,f0f4f8ff@fAfBfCfDfEfFfGfHfIfJfKfLfMfNfOgPgQgR gSgTgUgVgW gX$gZ(g[,g\0g]4g^8g_US[GRtX[ÐUPP=Dht gҡguDhÉUQQxdtt hxd WÐUWVS h$$=`hR $$),trك?ƒ?LlWhhW lhQphPY=ph[5PlWVhhPPDlhHPWW@WJ[^5@lPV2P<DŽ$\$ 1$D]hݜ$Nܼ$ݜ$t% Pk $R$QPRD] hݜ$Nܼ$ݜ$t% P $W$SPFNt$ $߆5xNiݜ$t% P $S$RP|$ $߇5|Niݜ$t% Pv $R$QP]1$7D]P5N i\$xt% P) $R$QP߄]5xNi\$pt P L$xQ\$xSPFpQQj1 ^ZP$*4@jVVP$߄} N k\$ht P^ |$pWL$pQPK$߄u5N0k\$`t P T$hR\$hSP L$ $A@k\$XN|$X\$Xt P \$`St$`VPT$ $BDk\$PN|$P\$Pt P t$XV|$XWPu$߄]5xN`k\$Ht PF L$PQT$PRP3$߄}pk\$@t P \$HSt$HVPT$ $B<̈́kE@{$t$$t W VSPt$ $F<݀kE@$t$$t WV VSPK|$ $Gՠk\$8N|$8\$8t P t$@VL$@QP\$ $Ck\$0N|$0\$0t P L$8QT$8RP$߄u(k\$(N|$(\$(t P |$0W\$0SPmT$ $Bk\$ N|$ \$ t P6 \$(St$(VP#|$ $k\$N|$\$t P t$ VL$ QP$(:PPj^_P$jS_P$.SSjZYP$ jPP$)lQQj~_ZP$4jVP^$*PPj:^_P$ jQP$/ SSjZYP$ kQOP$+@7QQj_ZP$<kW P$D$ C$D$ $m1߄]n5xNl\$t P L$Q|$WPC~1ۀ+lWWjZ4lYPVhCP~ċ-n$*tIVVjZYPkP!P hļ[^_]PPHl>SSj{ZYP$4kVPPjX^_P$4kV]QQj5_ZP$jPSSjZYP$jSPPj^_P$< jW(QQj_ZP$jR؃$h؃$SrVVjrSSjAPQTl$`h$P T$;`htÍvD$mmà n`hm d9t"m mmPm Ðt&UWVSLՉdhRhHhHB\$ dhSH$[ZPVE4$hVSZ lYPSP6V=Y[jjjj$L$xQT$|R$PUVZYPWP|[^_]Ít&UWVSXՉNjt$tV'ơdhPhHhH@\$ dhSr$[ZPVo4$hVSZYPWPfVm[Xjjjj\$xCSL$|Q$PUVY[PWPP(jV5XZj_]PVP h?jY[PV|P\[^_]Í'VST$t$$Rá hug9Xlt_PP kFXlPQxD4gRRV5kV|XkZSPn K$QS kRS1[[^QQhH뽉'VSQ ht$t Z[^Í L$Qá hug9Xlt_PPkFXlPRxV4gRRV5kVXkZSP S$RK kQS  kS1Z[^QQhH뫍'SQD$  h\$@ uXlC w $Nt&[[Ë `hS|$ xN)ȋ nPfD$ f$,$ߛnl$[[ËC `h|$ xN)ȋn fD$ f$,$ߙ0l$[[Ë`hK xN)Ћ|$fL$ Pnf $,$ߛl$[[Ë`hK N)Ћ|$ы nPfD$ f$,$[Pl$[[ËC `h|$ xN)ȋ nPfD$ f$,$ߛl$[[Ë `hS xN)ȋ |$ nHfD$ f$,$l$[[Ë`hK xN)Ћ|$ nPfD$ f$,$[ l$[[ËC `h|$ N)ȋ nPfD$ f$,$ߛl$[[ËC`h|$)nQfL$ f $,$ߛl$[[D$ HX[D$ HV@`h|$ N)nfL$ f $,$ߛl$[[Ã`h|$)nfL$ f $,$ߛl$[[Ãm `h |$f\$) |N f$n,$ZBl$[[Ã> `h|$ xN)ȋ nfD$ f$,$ߛl$[[Ë `h|$ N)ȋ nPfD$ f$,$ߛl$[[Ë `h|$ xN)ȋ nfD$ f$,$ߛl$[[á`h|$)nfL$ f $,$ߛ l$[[Ë `h|$ xN)ȋ nfD$ f$,$ߛ2l$[[Ë `h|$ xN)ȋ nPfD$ f$,$ߛ(l$[[Ë`h |$f\$) N f$n,$ߚl$[[Ë `h|$ xN)ȋ nfD$ f$,$[@l$[[Ð&UWVShՉD$jHdhShHhHC|$dhW<$ID$|$$^ V$1ل$F1^$^RQh?jhz?h{Gل$\$ل$$RQ(jjVhhHP D$x9D$t ZYPSPXZjjVhhHSjjVhhHSjjVhh ISWS$FhSWwZYP lPyPSY^jjjj$$׉W$Q$PUS.ZYPl$HU!P(j^_PSPl[^_]Ív ZYPSPYXjSvt&`hSЋL$ )ЋnЈ[ÐVSST$9lt99ltY[^Ë `h ˋ5nR)e3mY[^á`h Ë5nR)93lҍ&'`hWVSL$)Љ΃ nL$؊Qt+`h )5n[^_Ðt&`hу!)5n[^_Ðt& hhlhph Ѓ|`hn  m hu_\luV`htL)‰) nʋ nQhPR'D$ `hn` Í hhlhph Ѓw}`hn  m hu`\luW`htM)‰) nʋ nQhPRxD$ `hn ÍD$P hhlhȡph Ѓw|n`h  m hu^\luU`htK)‰) nʋ nQhPR`hn$1 ÍvD$P lhhhphэ Ѓw|n`h  m hu^\luU`htK)‰) nʋ nQhPR`hn$K1 ÉS\$Stm\lXZ[Í&mu\lmXZ[Ív`h nP`hP%Ph IFX @lQYZ`hPѡn)@Q `hn  %h)‰) nʋ nPR\lA&'mmtD$D$Ít&'VS5n`hD$Pa3t[^Ð&D$Pn`h n $n `hdm1ÐUWVS 5gV[^$S$RdhI l$`UQ_P<$[^jjjjjjjjW3ZYD$pP$VP$jãDlY^PSPZDlRDlhPhJI thl$`UQP ]DlR XDlZjjjjjjjjP l$pUWwP0 DljhXIQT$HR$HlRRVP=PDXHlPHl5thhShfI l$`UVPW HlXQZHl[^jjjjjjjjR D$pPWPJ0HljhtISl$HUw P< thhUhI t$`VQjPjhIUT$HR,$^Xjjjjjjj jU D$pPW#P(\$PSU ^Zp p hI1ZYPUP}Y^hI SUPcXZhI SUPIY^h7R SUP/XZhER SU~PY^hI SUdPXZhI SUJPY^hI SU0PXZj SUP -Ll PthhVhI L$`QRP,4$4XZjjjjjjj j V D$pPWP*(hJ SVPXZhJ SVnPYXh K SVTPXZhK SV:PYXhJ SV PXZhJ SVPYXhJ SVPXZh J SVPiZYj SVP5Pl$@l$C @lthhQhI t$`VRkPX@lP^@lXjjjjjjjj S L$pQW/P$hIiZD$PPhtht$HVhI T$`RPP@[\$PSEXZjjjjjjjjL$lQ t$pVWP70jh@HT$LRD$HP$IZD$LP'h5th\$DShI L$`QVQP[T$LRXZjjjjjjj"jD$hP \$pSWP0jhIL$HQt$HVf^ lT$@hHƉ$dhPhHhH@$|dhS$IhVP L$`Q\$PSP4$XZj5kzY[PVaPX h?jV^ZkD$HPR3Pz kjjP kXZjjjjjjj'j$Q^X\$p\$dSWPm$5kV>jh?jZZYPjPk$J[k^jRXkZh?P kjj2Q[kS5kXZjjjjjjj,j'V T$dRW1P$ lD$4hpHƉ$ dhQhHhHA$< dhS$xhVPZYD$Oa 1[^_]à FRgu~%P mPPQHZYPWN~PK5nQPVZYPW`=@hWjjhWOֺC=@hWjjhuOQ @hQj'jhO袺@hSj(jh$P舺@hRjjhOiMt&D$T$ L$ЃT$fJPÍSD$ \$L$d)‰D$)dsdT$D$ [ݷ UWVSt$,h hjPո)j,$迴C1󫍋XZjQ\贴<$輱ЂShWR` VD$PU苴_D$j+ Vt$HVQЂ$;`[^_]Ít&'VSVt$t- SB$*Fut$[[^餷Y[^Ít& P蓷t$[[^鄷&VSPL$\$`tNL$S$P1|$fD$ f$P P,$ۜ@l$B~؋\AA A$A(A,~]1#pKQ(Q<ǂǂt4QA(tыA@[^_]ÉL$s@CDt t1ҍ9tf9t0LB~捎dždž0dž‰dž4dž`dž8`A8)ډÉY؋dЋAXd)ډÉY؋hЋAxh)ډÉY ؋88lЋl)ډÉ4W$dždž<t[_8O8džw8D$tD>@[^_]ÉLL0ǁǁ D$w$w8dždžtD>@[^_]Ët0DkL0\D0tD$LL0tǁǁD>@[^_]Ív'UWVS|$$$)퍄dsD$l@ $7LHt1ҍv$9L$9L0B~؋$P,Ƌ@@~@ǁL0닼$$KDKHK@KDt t1$9L0t1BB$9Lu$$D9L0uϋ$D0B~$P Ƌ@4~4ǁL0$\ $D+@|[^_]É$$ȋP@t $M(tPt t1ҋ$9L $9L0B~؉ʅ$pX0ʼn@0ǂU0L$h$L$hЋ$L(@UhpjQdL$x$ih5$h hT$|$$t$x߂zۄ@ټ$f$ f$ P٬$ߞ٬$ ]l$l$ 20F D$l |$l$ \$h645K(L$l u:$|$h 8(_$L$l >$T$h <>J,l$h|$hD$lB\$lD$pl$4|$0D$,l$(l$$\$ L$p\$lt$,1K;$r $)Ѹ)z ~T$p|$lW($o )Ƌ\$,D$dffd $L$pl$hDT$,$)ދL$p|$htt$l1tl$0fE1tt$0fFL$p|$l9tD$0f@T$p\$ltL$0fA|$pl$l/@tRL$p\$lt$0fKfFfKffV |$p}|$pT$pL$l$\$,Q$})$)Ƌ\$lD$p)CL$L$pt$K6  |$pX |$p L$pt$l1ҋ\$01BfS1ۋD$pD$ T$ D$lڋt$pLP C)t$pt$hfLF`L$lQfTF@~ËT$ L$dD$drPT$dt$`t$ ^RD$\$\~TT$d |$XvVD$ T$ t$TT$ D$d t$PrXRZ D$LD$dT$HT$ l$DT$D T$DD$ l$dP\D$ T$@T$T$ D$dl$<j^T$ T$\AD$8D$`L$)‰CL$(T$$GD$B L$\T$X)L$(T$TL$$Y$\$X)ډT$(y(|$P|$PD$T|$P)GL$LT$(L$LL$LT$HAD$$)x,|$$\$(T$pO0L$D|$H\$4L$DL$D)A|$(Pt$<\$$T$pD$4K4|$@` )ˋt$(D$$H8|$8|$8l$$|$8GD$`}<|$pO|$p|$p| L$,$Li)$@96)ыT$0fJfl$pt$ E\$$D$(|$, $l$pt$ \$$D$(|$,T$0|$pFL$hǁ`|[^_]Ë$7@mHHt t1ҋ$9L $9L0 B~؋$P,o P@Ɖ@@ǁL0닔$$ËKDKHK@KDk t1$9L0W Bv$9Lu؋$D$$p@@DNt1ҍ&$9t$9t0B~؍dž`dž0dždž4`y8)ڋYdžߋڋddž8dyX)ډЋYߋڋhhyx)ډЋY ߋ8ڋll8)ډ4$dždž<P$@8Y8džq8$t$D.@|[^_]@D֋t t1ҋ$9t$9t0B~؍dždž0dž‰dž4dž`dž8`A8)ډÉY؋dЋAXd)ډÉY؋hЋAxh)ډÉY ؋88lЋl)ډÉ4$dždž<P$@8Y8džq8$$LD1@&‹$)Ӊ)T$p|$l1W($\$,D$dff$$)͋t$pD$hL$4AT$(i$$D$@D$t$T$T$h3B8\0t|$4G\$(G;$$D$@D$T$T$\$hC4zl$pt$hD$(|$4_F$$D$@D$t$T$3\$hC0 L$hq( f%t$l$ l$h><E,l$l$ L$h:8q$t$l$ \$h64C(|$l$ 20t$h$VV0ǂǂht$4F l$(Nk$$D$@D$T$T$\$hC<$D0D|0h$DAT$hZ$ fzrl$h} f\$P P4Ɖ@4ǁL0$\ $D+@l$hE, f$LL0ǁǁ1$w$w8dždžLi$D0D$D0?$J$tHt1ҋ$9L$9L0B~؉ʅ$N,tPt t1ҋ$9L$9L0tB~؉ʅ$J pt t1$9L0B+$9Lu؋D̋$LL0ǁǁG$LL0ǁǁ$r$r8dždžF]$D0\0[D;$LL0ǁǁ\0}D]$pX0ʼn@0ǁM011ۊhi$ЋPH9tm9HDPD1h1Ҋi$D(H\0!$NN0ǁǁk@Hi$Nt t1ҋ$9Lu l$9L0u$\0B~ŅtY$VtXF0n0ǁN011Ҋhi$D@D$h$NN0ǁǁ뤍'UWVS<|$PjjhOD$(PPPhHL$(Q貆hjBhHl$(Uil$~SSjU踆D$ Y\$SvdsD$$ Pht$,VقjL$$QT$,RU \$D$PhT$RD$ P聂~ L$Q]PPt$ VUML$1<$P11YAD$ $;@ދL$ L>Htrt t19L9L0B~W,G@w@ǁL0$T$ KDKHK@KDtrt t19LA9L0(B~W uw4G4ǁL0$D$ $4$D>@ t$$V訁XZjU~Y& L$Q识Z 1V@hShOPր t$$VFXZjU11ҊY1SQRAPW1ۋqY ƀf_Pt$$VXZjU迅C1AI))ˆ8dVh:ds;dPQ.XQL$QRYSt$VQ1RAPYSW1PPY1S1Q1RAPY @hShPPQ t$$VXZjUׄ[$L$ s@CDt t19ty9t0`B~捎dždž0dž‰dž4dž`dž8`A8)ډÉY؋dЋAXd)ډÉY؋hЋAxh)ډÉY ؋88lЋl)ډÉ4W$dždž<tB_8O8džw8 t0Dw$w8dždžLL0ǁǁLL0ǁǁ@hRjjh|P j躁5@hVjjhP܋L0\xD0etLUWVS$D$xD$ $ > 4: ; I?  &I%%T/ ../sysdeps/i386/elfstart.SP01:"VWYX   init.cN /home/gb/rpm/BUILD/glibc-2.3.4/build-i586-linux/csucrti.SG3,Wdğ#,:t ,Wdd,,-vN /home/gb/rpm/BUILD/glibc-2.3.4/build-i586-linux/csucrtn.S Hٟ GNU C 3.4.3 (Mandrakelinux 10.2 3.4.3-3mdk)init.cshort intlong long intunsigned charlong long unsigned intshort unsigned int/home/gb/rpm/BUILD/glibc-2.3.4/csu_IO_stdin_used.symtab.strtab.shstrtab.interp.note.ABI-tag.hash.dynsym.dynstr.gnu.version.gnu.version_r.rel.dyn.rel.plt.init.text.fini.rodata.eh_frame.ctors.dtors.jcr.dynamic.got.got.plt.data.bss.comment.debug_aranges.debug_pubnames.debug_info.debug_abbrev.debug_line.debug_str#(( 1HH\7  ?Ď Go$Toc l 0 uğpܟp{PP(GHS dTdhdhpdpxdx|d|@ee$gD@h, ,x8%]`v07'0! (HĎ ğ ܟ P G HdThdpdxd|deeg@h !,ep,,ep  [,eft vhdpdxdgDh Ш vldtddTxdG &  [&,e&ang{g h`h  LlhhlhphPlDl@lhHlTlгK dh"  ' - 6Xl? H Y+ _/ mr `  \l `   % -( C0O O ;S \ _$ > K d nt n} o ğ <= U%  . 4  =5 nC uR \f _y m 9 0= \ m ' \ @h X  ( = P o   P   n n 0%  B# < W z D   m  ܤO a + hd> g GP w   ,h > 9  hd  g !m *+<LNG T<eqwyG/ a % A  ,n1|AUV'knrK` ,he* n/<@ Oha[ p\hdHu6Dybu}1&n9g_/ C9]ng|w<v n ./../include/libc-symbols.h/home/gb/rpm/BUILD/glibc-2.3.4/build-i586-linux/config.h/home/gb/rpm/BUILD/glibc-2.3.4/csu//abi-note.S/home/gb/rpm/BUILD/glibc-2.3.4/build-i586-linux/csu/abi-tag.hinit.c/home/gb/rpm/BUILD/glibc-2.3.4/build-i586-linux/csu/crti.S/home/gb/rpm/BUILD/glibc-2.3.4/build-i586-linux/csu/defs.hinitfini.ccall_gmon_startcrtstuff.c__CTOR_LIST____DTOR_LIST____JCR_LIST__p.0completed.1__do_global_dtors_auxframe_dummy__CTOR_END____DTOR_END____FRAME_END____JCR_END____do_global_ctors_aux/home/gb/rpm/BUILD/glibc-2.3.4/build-i586-linux/csu/crtn.Sinterface2.cwidget_themeop_labelpatch_changemidichannelset_widgetsbank_entrygroupbankpatchpatch_entrypatch_group_1patchnameedpatch_group_2midichannel_spinner_adjcheck_patchn.0linelabelon_focusspin_adjon_rangeon_value_changedscaleon_od_clickedon_lfo_button_clickedon_button_clickedon_patch_group_1_clickedsavingon_patch_group_2_clickedon_bank_entry_changedon_patch_entry_changedon_save_button_toggledon_esc_save_button_pressedon_monobutton_toggledon_ch_combownwindow1mx44.cshrt_minhigh_maskmx44_midi_threadoff_60.0mx44buf.1current.2called.3mmxtmpmain.cmidiaudio_argc_argv__dso_handlegtk_hseparator_newgtk_toggle_button_get_typepthread_attr_init@@GLIBC_2.1usleep@@GLIBC_2.0gtk_entry_set_textgtk_radio_button_get_typegtk_combo_box_new_textWITH_JACKgtk_object_get_typemx44_pgmchangegtk_rc_add_default_filegtk_toggle_button_get_activegtk_spin_button_set_numericjack_get_sample_rategtk_combo_box_get_typegtk_misc_set_alignmentg_signal_emit_by_namegtk_widget_show_DYNAMICmx44patchNomx44_newmx44_chanpressgtk_combo_box_get_activegtk_toggle_button_set_activegtk_combo_box_append_textgtk_widget_set_size_requestwrite@@GLIBC_2.0poll@@GLIBC_2.0g_signal_connect_data_pthread_cleanup_push@@GLIBC_2.0close@@GLIBC_2.0_fp_hwperror@@GLIBC_2.0setwidgetsfprintf@@GLIBC_2.0getenv@@GLIBC_2.0gtk_widget_set_namesched_get_priority_max@@GLIBC_2.0pthread_create@@GLIBC_2.1__fini_array_endgtk_frame_newmx44_pitchbendgtk_vseparator_newgtk_table_attachsnd_seq_free_event@@ALSA_0.9gtk_vscale_newgtk_object_set_datamx44_jack_processjack_port_register__libc_csu_finigtk_container_add__cxa_atexit@@GLIBC_2.1.3mx44_noteongtk_table_get_typegtk_misc_get_typegtk_frame_set_shadow_typejack_connectgtk_adjustment_set_valuejack_client_newpatch_fdputs@@GLIBC_2.0_initinterfacemain_interfacemalloc@@GLIBC_2.0sched_yield@@GLIBC_2.0pthread_mutex_init@@GLIBC_2.0pthread_getschedparam@@GLIBC_2.0pthread_mutex_destroy@@GLIBC_2.0gtk_label_newgtk_window_newgtk_window_get_typegtk_scale_get_typeWITH_ALSAgtk_hscale_newsave_stategtk_label_get_typesavebuttongtk_tooltips_newgtk_frame_get_typestderr@@GLIBC_2.0mx44_disposegtk_range_get_adjustmentgtk_widget_unrefgtk_window_set_titlegtk_entry_get_textgtk_spin_button_set_adjustmentgtk_adjustment_newsnd_seq_open@@ALSA_0.9_startgtk_container_set_border_widthpthread_mutex_lock@@GLIBC_2.0mx44tmpPatchgtk_initmx44_resetgtk_spin_button_newsleep@@GLIBC_2.0gtk_scale_set_draw_valuegtk_radio_button_get_groupsnd_seq_poll_descriptors@@ALSA_0.9__strtol_internal@@GLIBC_2.0pthread_setschedparam@@GLIBC_2.0jack_activateport_Lsnd_seq_set_client_name@@ALSA_0.9gtk_main_quitgtk_widget_set_sensitivejack_port_get_buffer__fini_array_startsnd_seq_poll_descriptors_count@@ALSA_0.9__libc_csu_initgtk_entry_get_typegtk_main__bss_startmainsetup_audio__libc_start_main@@GLIBC_2.0__init_array_endjack_get_portsgtk_spin_button_set_valuegtk_set_localedata_startnewpatchprintf@@GLIBC_2.0getuid@@GLIBC_2.0_finilseek@@GLIBC_2.0memcpy@@GLIBC_2.0sqrt@@GLIBC_2.0gtk_object_set_data_fullatexitgtk_tooltips_set_tipmx44_playgtk_label_set_textgtk_entry_set_alignment__strdup@@GLIBC_2.0mx44_jack_shutdownsetreuid@@GLIBC_2.0mx44open@@GLIBC_2.0gtk_radio_button_newgtk_check_button_newport_Rjack_set_process_callbackgtk_label_set_justifygtk_combo_box_set_activeexit@@GLIBC_2.0mx44_controlsnd_seq_create_simple_port@@ALSA_0.9_edata_GLOBAL_OFFSET_TABLE_free@@GLIBC_2.0_endioctl@@GLIBC_2.0jack_port_namememset@@GLIBC_2.0mx44_jack_initsnd_seq_event_input_pending@@ALSA_0.9jack_on_shutdowngtk_adjustment_get_typegtk_range_set_inverted__init_array_start_IO_stdin_usedsnd_seq_event_input@@ALSA_0.9pthread_mutex_unlock@@GLIBC_2.0gtk_table_newgtk_entry_new_with_max_lengthg_type_check_instance_castldexpf@@GLIBC_2.0g_timeout_addsprintf@@GLIBC_2.0fwrite@@GLIBC_2.0gtk_toggle_button_new_with_label__data_startgtk_container_get_typepthread_attr_setinheritsched@@GLIBC_2.0_Jv_RegisterClassesgtk_button_new_with_labelmx44patchread@@GLIBC_2.0sched_setscheduler@@GLIBC_2.0mx44_noteoffmx44runninggtk_widget_ref__gmon_start__strcpy@@GLIBC_2.0gtk_widget_grab_focusMx44/COPYING0000644000076400007640000004310507254564320011347 0ustar jensjens GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. Mx44/mx41patch0000644000076400007640000020704010254255400012036 0ustar jensjens@@@@@@@@@v cNubZ 'Kp<2t| O@@@@v @ @@@@@@|@@@@@@ @/'9@i/V"}}}}}},=GZd@@@d6/ 5@$@8@8@8DB(IYe#AmsterdamIInh organjUv@@@@@@@@@v cNubZ wKp< O@@@@v @ @@@@@@@@@@@@@/'9@i/V"}}}}}},=Gb5-d@@@d6/ 5@$@8@8@8DBIYe#(not so) Loud PWM Organ+ `` 6P@.A @ 5}1sL@`R@@;y0@@@+ @@@@@@KmD@#7)!4/rn1i;[ $by>@>K@.dpd Orchester SaucesIp _ @@J#$%_"_"?8ڰR}uiu}N@ | @ @d @@o@IUS^hoi,-%,E@wCYa',8Pi @ v"e/f/< dKY<}P@$}Z}v% O>IWheel Modulated III<_Jm<* ,wpTe}<} 0xDEADBEEFp<<<c,N̏@4(@@@@@@@@@@@@;@@@xx}}}}}}?pj   H}}Const Cntp %@h b(NC<O(3Nϊc  ,Z%@@@@@@@@@@@@@@@@@@@@@@@@}}Te}2ZR}}xeo}  hd  %<<3@CI@}[Bell Labsdsenp>}Fj#>T-@@@@@@@@@@@@@@}}\< -xp0n̉YKI'plain sillypk ow\B@  ?p@}}}1RB,}}}V?pk+-!q,)8{@ @ #Te\}=5}Dragspelpp(hjk}IY[;S@@@@@@@@@@?p x ?pk^-&}Te5NWasp?p v ω$<š }d3ONcc}}5)=t|W @@@i@ @@@@@@@@$}} @2CSy?y*=IX}XAA}(2$kJ2# [i[!$Wasp 2?pj*(v?v?7;'Gv?7fh[;m-J@@@@@@@@@@@@@@@@@ x ?p Lo^~. -|K}U|!NWiseguy?p(}cĀ>mNCNTe@@@@@@@@@@d<&@@@,[mresonance= Q@*m'G v?'GbZšš}A}iKU @@@{@3r&}}}}}}}}}},Y i6LU 'vE,##y}g`|P}5\}IYC>,Scarlattianop\ v f @@@@@@@}}}@}d<LFO test 1@ >><-B:>f @@@@@}}}}IdWا{sd<LFO test 2 ( X Files ?)@  <-B:>f @@@@@@@}>}@>?h}03~d2LFO test 3}@yJ|<-B:>f @@@@@@@}}@d2<LFO test 43v[6OӖ@ o;MDf0R@@;@) @0@@@[@@@@K@D@KELyyy>>>Robots6OӖ@ TMDf0x P P 6 d @) @0@@@[@@@@K@D@KE)azP'on) Zyy>>>Robots III2 6P}@ =`,;f02@@;@@@@@@[@@@0@@K/@DKE(X$5#\yyy%%>>5 Symphonic Pad &@@ `@ 6 @ @Ā%}Ty*G@` '  T w  y0@@@@@@@^@@Cmv;@f$f$heS5.S71i;Q{c`Jb >@>K>UjZm(?K}String Quartet 3 ius\B _%OӖB @ n8}f0 P P 6 0 ^aQ0e@@@@K@@D@KESdkml0 Z) Z81_>>>Fat BoyII@@s\B _ %OӖB @ }|6}f0 P P 6 0 ^aQ0ex @@@@K@@D@KESdknl0 Z) ZtYXYA1_>>I'>9>>>Fat BoyII  a@@72}O1q} @@`# @| dXM*}Y ,R}op 1 on quack-@N} iiF XM*}Y,R}op 1 on quack g,V`YA@ :} `DRd P@@@@} SL/S2} } @@f)) ![@d0}@Lyj}yOl%2@e|3)Test IIIg,V`YA@ :} `DRd P@@@@} SL/S2} } @@f)) ![q@d0}@Lyj}yOl%0|3)Test IIIg,V`YA:} XDd Rd P@@@@} 4ES2} } @@@'@$@3C $.6*}yv[y} P)Test IIg,V`YA:} N2DRd P@@@@} 4ES2} } @@@'C $!6*}ys}y} aMP)Test II & L0&ۥGҗ LY$@Q[[v-} jD \Pe @@@@} 6 17S2@=v } @@@'j&(C 2 #2yYN}yUY1@ H0)PianoI@@@@@@@@@v cNubZ 'Kp<2t| O@@@@v @ @@@@@@|@@@@@@ @/'9@i/V"}}}}}},=GZd@@@d6/ 5@$@8@8@8DB(IYe#Amsterdam IInh organu{@@@@@@@@@v cNubZ 'Kp<2t| O@@@@v @ @@@@@@|@@@@@@ @/'9@i/V"}}}}}},=GZd@@@d6/ 5@$@8@8@8DB(IYe#Amsterdamnnh organ@ Z>@+@Jcĉ$>_"_"?8ڰR}8u}N@ | @ @d s @@o@IUS^hoi,-%,E@wCYa',8P  @44 t<KY<dT@$}K}KC KIWheel Modulated IV<<<c,N̏@4(@@@@@@@@@@@@;@@@xx}}}}}}?pj    H}}Bell Labs IIp %@h b(NC<O(3Nϊc  ,Z%@@@@@@@@@@@@@@@@@@@@@@@@}}Te}2ZR}}xeo} Z dHH d %<<3@Iw}[Bell Labsdsenp>Zj#k o}e@ ?p@}}}}},}}}?pk+-!q,)8{@ @ #Te\}=5}Harmoniumpp(h@*(v?77,}'G77fh[;m-J@@@@@@@@@@@@^@@@@ x v@p Lo^~.-|K}j##|!NWiseguy?p(}cĀ>mNCNTe@@@@@@@@@@d<&@@@,[ mBell Labs II= Q 5*v A &G'GbZv نw}H@jBgNCN@@@{@@3r&}}pn}} }}}}}<,Y i6LUz 'v,##}ggP>C%nIY9 > ,Lectric Ganop= Q25*v ; v?<'GbZv نw}IY3}bsN@@@@{@@3r&}}}}}} }}}}}<,Y i6LUz 'v,##}@j`@j>>@8>IY9 > [Lectric Ganop ` 6` P@.@@ }rL@`f0R@@;@My0@@@@@@@ @KmD@-|h$7)!5.S gi;by>@>K>>>>String Quarter0=@ *'3v?G'Gms1af }x( [@{@3r@@@@@-[iOxe!}}}}} }}}}},@ < n 'jE-} kB*sg`|}}} [!C!Piano embryop@ `@ 6 @ @Ā%}Ty*G@` R@;T $$y0@@@@@@@^@@Cmv;@f$f$heS5.S71i;Jb >@>K>UjZm(?KString Quartet 3@ `` 6` P@.@ @+}TsLG@`R@;y0@@@+ @@@@^@@Cmw;@@ h$h$he!5.S:1i;by>@>K>UjZm(?lDString Quartet@ `` 6 @. @Ā%}TsLG@` R@;y0@@@@@@@^@@Cmw;@f$f$he!5.S71i;b >@>K>UjZm(?KString Quartet 2@VU:+ `` 6P@.A @ 5}1sL@`R@@;y0@@@+ @@@@@@KmD@#7)!4/rn1i;[ $by>@>K@.dpd Orchester SaucesI}[L0&ۥGҗ  N$[[v} jD\TPf @@@@} 6 17S2@=v } @@@'j&(C 2 #2yYN}yU?g,gR0)Piano 2 & L0&ۥGҗ LY$@Q[[v} jD \TPf @@@@} 6 17S2@=v } @@@'j&(C 2 #2yYN}yUY'@ R0)PianoI@@@@@@@@@v cNubZ 'Kxp<2t| O@@@@v @ @@@@@@|@@@@@@ @/'9@i/V"}}}}}},=GZd1(!@@d6/ 5@$@8@8@8DB}}K.#AmsterdamIInh organiUv@N} iiF XM*}Y,R}op 1 on quack  ! (6?P7}>@ o;/ DLD*2@@;@M@@@@@@@V0@@K/@DK0K<(X$5#\2 yyy%%>>> Symphonic PadJm<( ,wp_"_"?8ڰR}=<t}N@ | @ @d @@o@IUS^hoi,-%,E@wCYa',8Pi @<$$$KY<}P@$}Pe}KM,@,KIWheel Modulated III@@@@@@@@@v cNubZ 'Kp<2t| O@@@@v @ @@@@@@|@@@@@@ @/'9@i/V"}}}}}},=GZd@@@d6/ 5@$@8@8@8DB(IYe#Amsterdamnnh organ@@@@@@@@@v cNubZ wKp< O@@@@v @ @@@@@@@@@@@@@/'9@i/V"}}}}}},=Gb5-d@@@d6/ 5@$@8@8@8DBIYe#(not so) Loud PWM Organ@@@@@@@@@v dLubZ wKp< O@@@@v @ @@@@@@@@@@@@f@/'9@i/V"}}}}}},=Gb5-d@@@d6/ 5@$@8@8@8DBIYe#(not so) Loud PWM Organ;(}mG@@@@@@@@@@@@@@}}@}}kT+ F}KTe}<0xDEADBEEFp@+@Jcĉ$>_"_"?8ڰR}8u}N@ | @ @d s @@o@IUS^hoi,-%,E@wCXa',8P  @44 t<KY<dT@$}K}KC KIWheel Modulated IV@@@@@@@@@v cNubZ wKp< O@@@@v @ @@@@@@@@@@@@@/'9@i/V"}}}}}},=G5-d@@@d6/ 5@$@8@8@8DBIYe#(not so) Loud PWM OrganUdj*(v?v?7;'Gv?7fh[;m-J@@@@@@@@@@@@@@@@@ x ?p Lo^~.-|K}U|!NWiseguy?pj*(v?v?7;'G|?7fh[;m-J@@@@@@@@@@@@@@@@@ x ?p Lo^~.-|K}U|!NWiseguy?p= Q@*m'G v?'GbZšš}A}iKU @@@{@3r&}}}}}}}}}},Y i6LU 'vE,##y}g`|P}5\}IYC>,Scarlattianop@ b(NCO<Q3(3Nϊc  ,Z%@@@@@@@@@@@@@@@@@@@@@@@@}}Te}2ZR}}xeo}  hd %<<3@CI@}[Bell Labsdsenp:5C Mx44/old/mmx4.h0000644000076400007640000001176210231134677012131 0ustar jensjens/* * This software is released under GPL. If you don't know what that is * immediately point your webbrowser to http://www.gnu.org and read * all about it. * * The short version: You can modify the sources for your own purposes * but you must include the new source if you distribute a derived work. * * (C) 2002, 2003, 2004 Jens M Andreasen */ #ifndef MMX4_H #define MMX4_H //#include "mmx.h" //#define OMNIMODE //#ifdef OMNIMODE // Tim suggested a smaller footprint //#define MIDICHANNELS 1 //#define CHANNELMASK 0x0 //#else // Elsewise we are multitimbral //#define MIDICHANNELS 16 //#define CHANNELMASK 0x0F //#endif //#define SAMPLES 64 // number of samples to produce before polling midi //#define ENVLOOP 4 // number of envelope updates during sample production //#define OPLOOP SAMPLES/ENVLOOP //#define OUTBUF SAMPLES * 2 // stereo == 2 typedef struct { // Each envelope has a current value .. mmx_t state02; // d mmx_t state13; // d // .. and a precalculated +/- value to be added .. mmx_t delta02; // d mmx_t delta13; // d // .. for exactly x samples .. int time[4][8]; // [op][step] int time_count[4]; // [op] // .. before being replaced by the next precalculated delta value int delta_value[4][9]; // [op][step] int step[4]; // op int sustain[4]; // middle level in the sustain loop int release[4]; // the release deltas cannot be precalculated int running; // bit 0 - 3 set while env still running }mmx4env_t; // The state of a single running voice typedef struct _mmx4 { // mmx_t samples[SAMPLES]; // intonation parameters int intonation[4][2]; // w (op) [amount | decay] // state of oscillators mmx_t state02; // d (op 0, op 2) mmx_t state13; // d (op 1, op3) // frequency of oscillators mmx_t delta02; // d mmx_t delta13; // d // Each oscillator is phase- and amplitude modulated // by every other oscillators previous output // Modulaton arguments are skewed diagonally as in: // x[3](op2,op1,op0,op3) // x[2](op1,op0,op3,op2) // x[1](op0,op3,op2,op1) // x[0](op3,op2,op1,op0) mmx_t pm[4]; // w mmx_t am[4]; // w // pseudo sin is averaged from two bumpy approximations // running 60 degrees apart at the same frequency. // Optionally one part can be octave doubled and/or // modified to a second set of waweshapes. mmx_t od; // w (op) mmx_t complexwawe; // Stereo mix mmx_t mixL; // w mmx_t mixR; // w mmx_t wheel; // w // Final utput of oscillator 0,1,2,3 mmx_t out; // w // Next voice in an asignment que (running, hold, released, silent) struct _mmx4 *next; struct _mmx4 *previous; // envelopes mmx4env_t env; unsigned char channel; // channel number unsigned char key; }mmx4_t; // The patch sets up the initial state according to // key and velocity etc #define WAWEBUTTON 1 #define WHEELBUTTON 2 typedef struct { int pm[4][4]; // [destination] [source] int am[4][4]; int mix[4][2]; // [op] [left | right] int env_level[4][8]; // [op] [stage] int env_time[4][8]; int harmonic[4]; short intonation[4][2]; // [op] [amount | decay] int detune[4]; short velocityfollow[4]; unsigned char od[4]; // octave doubling unsigned char button[4]; // key bias int breakpoint[4]; // [op] int keybias[4][2]; // [op] [hi | lo value] // env keyfollow int keyfollow[4][2]; // [op] [attack | sustain-loop] // key velocity int velocity[4]; // [op] int phase[4][2]; // [op] [offset | velocityfollow] char name[32]; }mmx4patch_t; typedef struct { mmx_t mmxtmp[2]; mmx_t wheel; mmx4_t *voices; mmx4_t *que[4]; // assigned, held, released, silent mmx4_t *last[4]; mmx4_t *keyboard[MIDICHANNELS][128]; int keyTable[128]; // some controllers char holdpedal[MIDICHANNELS]; short pitchbend[MIDICHANNELS]; char modulation[MIDICHANNELS]; char mod_now[MIDICHANNELS]; mmx4patch_t mmx4patch[128]; // preset patches mmx4patch_t mmx4tmpPatch[16]; // actual editable and sounding patch int maxpoly; char mmx4patchNo[16]; // chosen preset number #ifdef OMNIMODE int touched[MIDICHANNELS]; float fsamples[MIDICHANNELS][2][32]; //[midi channel][left|right][index] int delivered; // number of prerendered samples already delivered #endif }Mx4state; extern Mx4state* mmx4new(int maxpolyphony); // middle A == 440.0 extern void mmx4reset(Mx4state* mx4,double tuningfork,int samplerate); extern void mmx4setpatch(Mx4state* mx4,int channel,int patchnumber); extern void mmx4attack(Mx4state* mx4,int channel,int key,int velocity); extern void mmx4release(Mx4state* mx4,int channel,int key,int velocity); extern void mmx4pitchbend(Mx4state* mx4,int channel,int data1,int data2); extern void mmx4control(Mx4state* mx4,int channel,int control,int data); #ifdef OMNIMODE // syntax checking only ... // use with debugger at your own risk .. extern void omni(Mx4state* mx4, int request,float* port_left, float* port_right) #endif extern void mmx4play(Mx4state* mx4,short * stereo_out); #endif