00001
00034
00035
00036
00037
00038 #include "Defs.h"
00039 #include <math.h>
00040 #ifndef MUTWIN
00041 #include <conio.h>
00042 #endif
00043
00044 #include "Global.h"
00045 #include "box.h"
00046 #include "GrafKern.h"
00047 #include "MidiKern.h"
00048 #include "Runtime.h"
00049
00050 int protokollfunktionen_aktiv=0;
00051 int protokollfunktion_aktionsausgabe=0;
00052 int zeige_aktuelles_tonsystem=0;
00053
00054
00055
00056
00057 #define KEY_CHANGED(box) { keys_changed[box]=1; keys_changed_sum = 1; }
00058
00059
00060 void MidiOut(int box, DWORD data, char n);
00061 void NotesCorrect(int box);
00062 int GetChannel(int box, int taste);
00063
00064 tone_system tonesystem_memory[MAX_BOX+1];
00065
00066 tone_system tonesystem_init =
00067 {60, 1, DOUBLE_TO_LONG(1), { DOUBLE_TO_LONG(60) }} ;
00068
00069
00070 int liegende_tasten[MAX_BOX][64];
00071 int liegende_tasten_max[MAX_BOX];
00072 long last_note_id[MAX_BOX];
00073 bool logic_changed[MAX_BOX];
00074
00075 int laufzeit_abstand[MAX_BOX];
00076 int laufzeit_zentrum[MAX_BOX];
00077
00078 char tempstring[255];
00079
00080 void MutResetKeys()
00081 {
00082 for (int i = 0; i<MAX_BOX; i++) {
00083 if ( last_global_harmonie[i] && *last_global_harmonie[i] )
00084 *last_global_harmonie[i] = NULL;
00085
00086 if ( last_global_keyboard[i] && *last_global_keyboard[i] )
00087 *last_global_keyboard[i] = NULL;
00088
00089 if ( last_global_midi[i] && *last_global_midi[i] )
00090 *last_global_midi[i]=NULL;
00091
00092 liegende_tasten_max[i] = 0;
00093
00094 for (int j = 0; j < MAX_BREITE; j++)
00095 mut_box[i].pattern.tonigkeit[j] = 0;
00096
00097 keys_changed[i] = 0;
00098 logic_changed[i] = 0;
00099 }
00100
00101 keys_changed_sum = 0;
00102 }
00103
00104
00105 void GlobalReset()
00106 {
00107 for (int i = 0; i < MAX_BOX; i++) {
00108 tonesystem_memory[i] = tonesystem_init;
00109 mut_box[i].tonesystem = tonesystem_memory + i;
00110 }
00111 tonesystem_memory[MAX_BOX] = tonesystem_init;
00112 free_tonesystem = tonesystem_memory+MAX_BOX;
00113
00114 MutResetKeys ();
00115 }
00116
00117
00118 void update_pattern(int instr);
00119 void change_breite(int instr, int neu);
00120 void change_anker(int instr, int neu);
00121 void keyboard_analyse( int taste );
00122 void HarmonyAnalysis(int box, PATTERNN * pattern );
00123
00124 void execute_aktion (int box, struct do_aktion * aktion)
00125 {
00126 bool WasNewLogic = false;
00127
00128 for ( ; aktion; aktion = aktion -> next)
00129 {
00130 AktionenMessage(box, aktion->name);
00131 switch (aktion->aufruf_typ) {
00132 case aufruf_logik:
00133 execute_aktion (box, aktion->u.aufruf_logik.einstimmung);
00134 * last_global_keyboard[box] =
00135 * aktion->u.aufruf_logik.lokal_keyboard;
00136 * last_global_harmonie[box] =
00137 * aktion->u.aufruf_logik.lokal_harmonie;
00138 * last_global_midi[box] =
00139 * aktion->u.aufruf_logik.lokal_midi;
00140 WasNewLogic = true;
00141 break;
00142
00143 case aufruf_tonsystem:
00144 * mut_box[box].tonesystem =
00145 * aktion->u.aufruf_tonsystem.tonsystem;
00146 update_pattern(box);
00147
00148 #ifdef NOTES_CORRECT_SOFORT
00149 NotesCorrect(box);
00150
00151 #endif
00152 KEY_CHANGED(box);
00153
00154 break;
00155
00156 case aufruf_umst_taste_abs:
00157 change_anker(box,
00158 aktion->u.aufruf_umst_taste_abs.wert[box]);
00159
00160 update_pattern(box);
00161
00162 #ifdef NOTES_CORRECT_SOFORT
00163 NotesCorrect(box);
00164
00165 #endif
00166 KEY_CHANGED(box);
00167
00168 break;
00169
00170 case aufruf_umst_breite_abs:
00171 change_breite(box,
00172 aktion->u.aufruf_umst_breite_abs.wert[box]);
00173
00174 update_pattern(box);
00175
00176 #ifdef NOTES_CORRECT_SOFORT
00177 NotesCorrect(box);
00178
00179 #endif
00180 KEY_CHANGED(box);
00181
00182 break;
00183
00184 case aufruf_umst_wiederholung_abs:
00185 mut_box[box].tonesystem->periode =
00186 aktion->u.aufruf_umst_wiederholung_abs.faktor;
00187
00188 #ifdef NOTES_CORRECT_SOFORT
00189 NotesCorrect(box);
00190
00191 #endif
00192 KEY_CHANGED(box);
00193
00194 break;
00195
00196 case aufruf_umst_wiederholung_rel:
00197 mut_box[box].tonesystem->periode +=
00198 aktion->u.aufruf_umst_wiederholung_rel.faktor;
00199
00200 #ifdef NOTES_CORRECT_SOFORT
00201 NotesCorrect(box);
00202
00203 #endif
00204 KEY_CHANGED(box);
00205
00206 break;
00207
00208 case aufruf_umst_taste_rel: {
00209 int help;
00210 help = mut_box[box].tonesystem->anker;
00211
00212 switch (aktion->u.aufruf_umst_taste_rel.rechenzeichen) {
00213
00214 case '+':
00215 help += aktion->u.aufruf_umst_taste_rel.wert[box];
00216
00217 break;
00218
00219 case '-':
00220 help -= aktion->u.aufruf_umst_taste_rel.wert[box];
00221
00222 break;
00223 }
00224
00225 change_anker(box, help);
00226
00227 update_pattern(box);
00228 #ifdef NOTES_CORRECT_SOFORT
00229 NotesCorrect(box);
00230 #endif
00231 KEY_CHANGED(box);
00232 }
00233
00234 break;
00235
00236 case aufruf_umst_breite_rel: {
00237 int help;
00238 help = mut_box[box].tonesystem->breite;
00239
00240 switch (aktion->u.aufruf_umst_breite_rel.rechenzeichen) {
00241
00242 case '+':
00243 help += aktion->u.aufruf_umst_breite_rel.wert[box];
00244
00245 break;
00246
00247 case '-':
00248 help -= aktion->u.aufruf_umst_breite_rel.wert[box];
00249
00250 break;
00251
00252 case '*':
00253 help *= aktion->u.aufruf_umst_breite_rel.wert[box];
00254
00255 break;
00256
00257 case '/':
00258 help /= aktion->u.aufruf_umst_breite_rel.wert[box];
00259
00260 break;
00261 }
00262
00263 change_breite(box, help);
00264
00265 update_pattern(box);
00266 #ifdef NOTES_CORRECT_SOFORT
00267 NotesCorrect(box);
00268 #endif
00269 KEY_CHANGED(box);
00270 }
00271
00272 break;
00273
00274 case aufruf_umst_toene_veraendert: {
00275 long * ton_zeiger;
00276
00277 struct ton_einstell * lauf;
00278
00279 for (ton_zeiger = mut_box[box].tonesystem->ton,
00280 lauf = aktion->u.aufruf_umst_toene_veraendert.tonliste;
00281 lauf;
00282 lauf = lauf->next, ton_zeiger ++) {
00283
00284 switch (lauf->ton_einstell_typ) {
00285
00286 case einstell_stumm:
00287 * ton_zeiger = 0;
00288
00289 break;
00290
00291 case einstell_gleich:
00292
00293 break;
00294
00295 case einstell_absolut:
00296 * ton_zeiger = lauf->u.einstell_absolut.wert;
00297
00298 break;
00299
00300 case einstell_relativ:
00301 * ton_zeiger += lauf->u.einstell_relativ.wert;
00302
00303 break;
00304
00305 }
00306
00307 }
00308
00309 #ifdef NOTES_CORRECT_SOFORT
00310 NotesCorrect(box);
00311
00312 #endif
00313 KEY_CHANGED(box);
00314 }
00315 break;
00316
00317 case aufruf_umst_umst_case: {
00318 struct case_element * lauf;
00319 int i;
00320 i=aktion->u.aufruf_umst_umst_case.wert[box];
00321
00322 for (lauf = aktion->u.aufruf_umst_umst_case.umst_case;
00323 lauf;
00324 lauf = lauf->next) {
00325 if ( (i == lauf->case_wert) || (lauf->is_default)) {
00326 execute_aktion (box, lauf->case_aktion);
00327 return;
00328 }
00329 }
00330 }
00331 break;
00332
00333 case aufruf_midi_out: {
00334 struct midiliste * lauf;
00335 unsigned long data = 0, faktor = 1, n = 0;
00336 ;
00337
00338 for (lauf = aktion->u.aufruf_midi_out.out_liste;
00339 lauf && faktor ;
00340 lauf = lauf -> next) {
00341 data += faktor * (unsigned char) lauf->midi_code;
00342 faktor *= 0x100;
00343 n++;
00344 }
00345 MidiOut(box, data, n);
00346 }
00347 break;
00348
00349 case aufruf_umst_umst_bund:
00350 wxLogWarning(_("Unhandled case path: aufruf_umst_umst_bund"));
00351 break;
00352
00353 default:
00354 wxLogError(_("Unexpected action type: %d"), aktion->aufruf_typ);
00355 }
00356 }
00357
00358
00359 if ( WasNewLogic ) {
00360
00361 HarmonyAnalysis(box, &(mut_box[box].pattern));
00362 logic_changed[box] = true;
00363 }
00364
00365 #ifndef NOTES_CORRECT_SOFORT
00366 NotesCorrect(box);
00367 #endif
00368 }
00369
00370 void update_pattern(int box)
00371 {
00372 PATTERNN * temp_pattern = &(mut_box[box].pattern);
00373 tone_system * tonsys = mut_box[box].tonesystem;
00374 int i;
00375
00376 for (i=0;i<tonsys->breite;i++) temp_pattern->tonigkeit[i]=0;
00377
00378 for (i=0;i<liegende_tasten_max[box];i++)
00379 (temp_pattern->tonigkeit[GET_INDEX( liegende_tasten[box][i]
00380 ,tonsys )])++;
00381 }
00382
00383 void change_anker(int box, int neu)
00384 {
00385 tone_system * tonsys = mut_box[box].tonesystem;
00386 tone_system * temp = tonsys;
00387 int i;
00388 laufzeit_zentrum[box]-=neu-tonsys->anker;
00389
00390 while ( laufzeit_zentrum[box] < 0 )
00391 laufzeit_zentrum[box] += tonsys->breite;
00392
00393 laufzeit_zentrum[box]%=tonsys->breite;
00394
00395 while (neu<36)
00396 neu += tonsys->breite;
00397
00398 while (neu>96)
00399 neu -= tonsys->breite;
00400
00401 free_tonesystem->ton[0]=GET_FREQ(neu,tonsys);
00402
00403 for (i=1; i<tonsys->breite; i++)
00404 free_tonesystem->ton[i] =
00405 free_tonesystem->ton[0] + tonsys->ton[i]-tonsys->ton[0];
00406
00407 free_tonesystem->anker=neu;
00408 free_tonesystem->breite=tonsys->breite;
00409 free_tonesystem->periode=tonsys->periode;
00410 mut_box[box].tonesystem=free_tonesystem;
00411 free_tonesystem=temp;
00412 }
00413
00414 void change_breite(int box, int neu)
00415 {
00416 tone_system * tonsys = mut_box[box].tonesystem;
00417 int i;
00418
00419 if ( neu>0 && neu < MAX_BREITE ) {
00420 if ( neu > tonsys->breite )
00421 for (i = tonsys->breite; i < neu; i++)
00422 tonsys->ton[i]=GET_FREQ((tonsys->anker+i),tonsys);
00423 tonsys->periode =
00424 GET_FREQ(tonsys->anker+neu,tonsys) - GET_FREQ(tonsys->anker,tonsys);
00425 tonsys->breite=neu;
00426 }
00427 }
00428
00429
00430 int tiefste_taste(int box)
00431 {
00432 int i, min = 9999;
00433
00434 for (i = 0; i < liegende_tasten_max[box]; i++)
00435 if ( liegende_tasten[box][i] < min )
00436 min = liegende_tasten[box][i];
00437
00438 return min;
00439 }
00440
00441
00442 int hoechste_taste(int box)
00443 {
00444 int i, max = 0;
00445
00446 for (i = 0; i<liegende_tasten_max[box]; i++)
00447 if ( liegende_tasten[box][i] > max )
00448 max = liegende_tasten[box][i];
00449 return max;
00450 }
00451
00452
00453
00454 int compare_harmonie(int breite, int startindex, PATTERNN * laufzeit, PATTERNN * vergleich)
00455 {
00456 int i;
00457
00458 for (i=0;i<breite; i++,startindex++) {
00459 if ( vergleich->tonigkeit[i] ) {
00460
00461
00462
00463 if ( vergleich->tonigkeit[i]==1 &&
00464 laufzeit->tonigkeit[startindex%breite] )
00465
00466 return 0 ;
00467 if ( vergleich->tonigkeit[i]!=1 &&
00468 laufzeit->tonigkeit[startindex%breite]==0 )
00469
00470 return 0 ;
00471 }
00472 }
00473 return 1;
00474 }
00475
00476
00477 void HarmonyAnalysis(int box, PATTERNN * pattern )
00478 {
00479
00480 struct harmonie_ereignis *help;
00481 tone_system *tonsys = mut_box[box].tonesystem;
00482 int i;
00483
00484 for (help = first_harmonie[box]; help; help=help->next ) {
00485 switch ( help->ist_harmonieform ) {
00486
00487 case 0:
00488 if ( help->vortaste>=0 &&
00489 GET_INDEX(tiefste_taste(box),tonsys ) != help->vortaste ) {
00490
00491 } else {
00492 if ( help->nachtaste>=0 &&
00493 GET_INDEX(hoechste_taste(box),tonsys)!=help->nachtaste ) {
00494
00495 } else {
00496
00497
00498 if ( compare_harmonie(tonsys->breite,0,pattern,help->pattern) ) {
00499
00500 execute_aktion(box,help->aktion);
00501 return;
00502 }
00503 }
00504 }
00505
00506 break;
00507
00508 case 1:
00509 for (i=0; i<tonsys->breite; i++) {
00510 if ( help->vortaste>=0 &&
00511 GET_INDEX(tiefste_taste(box)-i, tonsys) != help->vortaste ) {
00512
00513 } else {
00514 if ( help->nachtaste>=0 &&
00515 GET_INDEX(hoechste_taste(box)-i, tonsys) != help->nachtaste ) {
00516
00517 } else {
00518
00519
00520 if (compare_harmonie(tonsys->breite, i, pattern, help->pattern)) {
00521
00522 laufzeit_abstand[box] = laufzeit_zentrum[box] = i;
00523 execute_aktion(box, help->aktion);
00524 return;
00525 }
00526 }
00527 }
00528 }
00529
00530 break;
00531
00532 case 2:
00533 execute_aktion(box, help->aktion);
00534
00535 break;
00536 }
00537 }
00538 }
00539
00540
00541 void AddKey( int box, int taste, int id)
00542 {
00543 liegende_tasten[box][liegende_tasten_max[box]++] = taste;
00544 mut_box[box].pattern.tonigkeit[GET_INDEX(taste,mut_box[box].tonesystem)]++;
00545 last_note_id[box] = (id << 16) + (box << 8) + taste;
00546 HarmonyAnalysis(box, &mut_box[box].pattern);
00547 last_note_id[box] = 0;
00548 KEY_CHANGED(box);
00549 }
00550
00551
00552 void DeleteKey( int box, int taste, int id)
00553 {
00554 for (int i=0; i<liegende_tasten_max[box]; i++)
00555 if ( liegende_tasten[box][i] == taste ) {
00556 liegende_tasten[box][i] =
00557 liegende_tasten[box][--liegende_tasten_max[box]];
00558 mut_box[box].pattern.tonigkeit[GET_INDEX(taste,mut_box[box].tonesystem)]--;
00559 last_note_id[box] = (id << 16) + (box << 8) + taste;
00560 HarmonyAnalysis(box, &mut_box[box].pattern);
00561 last_note_id[box] = 0;
00562 KEY_CHANGED(box);
00563 break;
00564 }
00565 }
00566
00567 void KeyboardIn(int box, const mutChar *keys)
00568 {
00569 aktuelle_keyboard_box = box;
00570 char TonSystem = 0;
00571
00572 for (size_t i= 0; i < mutStrLen(keys); i++) {
00573 mutChar c = keys[i];
00574
00575 if ( c == mutT('&') ) {
00576 TonSystem = 1;
00577 continue;
00578 }
00579
00580 if ( mutT('0') <= c && c <= mutT('z') ) {
00581 if ( TonSystem )
00582 KeyboardAnalyse(box, (int) c, 0);
00583 else
00584 KeyboardAnalyseSimple(box, (int) c);
00585 }
00586 TonSystem = 0;
00587 }
00588 }
00589
00590 void MidiAnalysis(int box, BYTE midiByte)
00591 {
00592 struct midi_ereignis * lauf;
00593
00594 if ( midiByte & 0x80 )
00595 midiByte &= 0xF0;
00596
00597 for (lauf = first_midi[box]; lauf; lauf=lauf->next) {
00598 if ( *(lauf->scan_pos) != midiByte )
00599 lauf->scan_pos = lauf->first_pos;
00600 else {
00601 lauf->scan_pos++;
00602 if ( *(lauf->scan_pos) == -1 )
00603 break;
00604 }
00605 }
00606
00607 if ( lauf )
00608 execute_aktion( box, lauf->aktion);
00609 }
00610
00611 void pascal _export KeyboardAnalyse(int box, int taste, char isLogic)
00612 {
00613 for (struct keyboard_ereignis *help = first_keyboard[box]; help ; help=help->next)
00614 if ( toupper(taste)==help->taste && isLogic == ( help->the_logik_to_expand != NULL ) ) {
00615 execute_aktion(box, help->aktion);
00616 return;
00617 }
00618 }
00619
00620 void keyboard_analyse( int taste )
00621 {
00622 KeyboardAnalyseSimple(aktuelle_keyboard_box, taste);
00623 }
00624
00625 void pascal _export KeyboardAnalyseSimple(int box, int taste)
00626 {
00627
00628 for (struct keyboard_ereignis *help = first_keyboard[box]; help ; help=help->next)
00629 if ( toupper(taste)==help->taste ) {
00630 execute_aktion(box, help->aktion);
00631 return;
00632 }
00633 }
00634
00635
00636
00637 void protokoll_aktuelles_tonsystem( int box )
00638 {
00639 tone_system * tonsys = mut_box[box].tonesystem;
00640 long freq;
00641 unsigned char * zugriff = (unsigned char*) & freq;
00642 int i;
00643 init_laufzeit_protokoll();
00644
00645 laufzeit_protokoll("Anker= %d",tonsys->anker);
00646 laufzeit_protokoll("Breite= %d",tonsys->breite);
00647 laufzeit_protokoll("Periode= %.1f cent",
00648 LONG_TO_CENT(tonsys->periode));
00649
00650 for (i=0;i<tonsys->breite;i++) {
00651 if ( (freq=tonsys->ton[i])!=0) {
00652 laufzeit_protokoll("%2d : %.1f Hz (%.2f)",
00653 i, LONG_TO_HERTZ(tonsys->ton[i]) ,
00654 (zugriff[3]+(((float)zugriff[2])/256.0)) );
00655 } else {
00656 laufzeit_protokoll("%2d : %%",i);
00657 }
00658 }
00659
00660 exit_laufzeit_protokoll( );
00661 }
00662
00663 #define SHOW_CHANNEL
00664 void protokoll_liegende_frequenzen( int box )
00665 {
00666 tone_system * tonsys = mut_box[box].tonesystem;
00667 int i, imax, lts[64], lt;
00668 long freq;
00669 unsigned char * zugriff = (unsigned char*) & freq;
00670 imax = liegende_tasten_max[box];
00671 bcopy(liegende_tasten[box], lts, imax*sizeof(int));
00672 init_laufzeit_protokoll();
00673
00674 for (i = 0; i < imax; i++) {
00675 lt = lts[i];
00676
00677 if ( (freq=GET_FREQ( lt ,tonsys ))!=0) {
00678 #ifndef SHOW_CHANNEL
00679 laufzeit_protokoll("%2d : %8.1f Hz (%6.2f)",
00680 lt,
00681 LONG_TO_HERTZ(freq),
00682 (zugriff[3]+(((float)zugriff[2])/256.0)) );
00683 #else
00684 laufzeit_protokoll("%2d : %8.1f Hz (%6.2f)[ch: %d]",
00685 lt,
00686 LONG_TO_HERTZ(freq),
00687 (zugriff[3]+(((float)zugriff[2])/256.0)), GetChannel(box, lt));
00688 #endif
00689 } else {
00690 laufzeit_protokoll("%2d : %%",lt);
00691 }
00692 }
00693
00694 exit_laufzeit_protokoll();
00695 }
00696
00697 void protokoll_aktuelle_relationen( int box )
00698 {
00699 tone_system * tonsys = mut_box[box].tonesystem;
00700 int i,j;
00701 init_laufzeit_protokoll();
00702
00703 for (i=0;i<tonsys->breite && tonsys->ton[i]==0;i++);
00704
00705
00706 laufzeit_protokoll("Reference [%d]",i);
00707
00708 for (j=i+1;j<tonsys->breite; j++) {
00709 if (tonsys->ton[j]!=0) {
00710 laufzeit_protokoll("%2d:%.1f cent",j,
00711 LONG_TO_CENT( tonsys->ton[j] -
00712 tonsys->ton[i] ) );
00713 } else {
00714 laufzeit_protokoll("%2d:%%",j);
00715 }
00716 }
00717
00718 exit_laufzeit_protokoll( );
00719 }
00720
00721 void protokoll_liegende_relationen( int box )
00722 {
00723 tone_system * tonsys = mut_box[box].tonesystem;
00724 int i;
00725 init_laufzeit_protokoll();
00726
00727
00728 for (i=0;i<(liegende_tasten_max[box]-1);i++) {
00729 if ( (GET_FREQ( liegende_tasten[box][i+1] , tonsys )) !=0 ) {
00730 laufzeit_protokoll("%.2f cent",
00731 LONG_TO_CENT( GET_FREQ(liegende_tasten[box][i+1], tonsys ) -
00732 GET_FREQ(liegende_tasten[box][i], tonsys) ));
00733 } else {
00734 laufzeit_protokoll(" %%");
00735 }
00736 }
00737
00738 exit_laufzeit_protokoll( );
00739 }
00740
00741
00742
00743 void FlushUpdateUI()
00744 {
00745 if ( keys_changed_sum && updatecallback ) {
00746 for (int i=0; i<MAX_BOX; i++) {
00747 if (keys_changed[i]) {
00748 updatecallback(i,logic_changed[i]);
00749 keys_changed[i]=0;
00750 logic_changed[i]=0;
00751 }
00752 }
00753 keys_changed_sum = 0;
00754 }
00755 }
00756
00757
00758
00759