home *** CD-ROM | disk | FTP | other *** search
- /*
- * Programm: AM (Algorithmische Musik)
- * Aufgabe : Nach Parametern zufällig MIDI-Events erzeugen, sync. durch
- * Prg "Takt"
- *
- * Version : 1.1
- *
- * Aufruf : AM [-w] [<file [>nil:]]
- * -w = mit Parameterfenster
- *
- * Auto: make AM
- *
- */
-
-
- #include "AM.h"
- #include <exec/execbase.h>
- #include <dos/dosextens.h>
- #include <midi/kawai_k1.h>
- #include <string.h>
- #include <stdio.h>
- //#include <stdlib.h> und
- //#include <math.h> klappt nicht!
-
-
- #if 0
- # define D(debug) debug
- #else
- # define D(debug)
- #endif
-
- #define abbruch SIGBREAKF_CTRL_C
-
-
- //------------------------- Daten anderer Module...
-
-
- extern struct ExecBase *SysBase;
- extern struct Library *DOSBase;
-
-
- //------------------------- Code anderer Module...
-
-
- extern BOOL startwindow( void ); // Subtask für GUI starten
- extern void closewindow( void ); // Subtask stoppen
-
-
- //------------------------- Daten dieses Moduls...
-
-
- struct MidiBase *MidiBase = NULL;
- struct MSource *src = NULL;
- struct MRoute *outroute = NULL;
-
- struct MRouteInfo outinfo = {
- /* SysExs und alle ChannelMsgs passieren diese Route */
- MMF_SYSEX+MMF_CHAN, // MsgFlags; s. midi.h
- -1, // ChanFlags; -1 = alle
- 0, // ChanOffset; Kanalverschiebung der Route
- 0, // NoteOffset; Tonhöhenversch. " "
- { 0,0,0,0 }, // SysExMatch; SysEx-Filter
- { 0,0,0,0 } }; // CtrlMatch; Controller-Filter
-
-
- struct MsgPort *taktport = NULL;
- struct TaktMsg taktmsg;
- long taktsig=0, taktmask=0;
-
-
- long channel = 0, // 0..15
- instr = -1, // -1 = keine Änderung
- freqmitte = 63, freqabw = 48, // mitte ± abw
- volmitte = 63, volabw = 48; // mitte ± abw
- double pausen = 0.40, // Pausenhäufigkeit
- tonaus = 0.30, // NoteOff-Wahrsch.
- volblend = 0.1; // Ein-/Ausblenden
- char skala[13] = "999999999999", // Standard = Chromatisch
- cskala[12][13]; // Standard = Leer
-
-
- BOOL mitFenster = FALSE; // Flag für Parameter-Window
-
-
- //------------------------- Code dieses Moduls...
-
-
- void init( void );
- void closedown( void );
- void nextton( void );
-
-
- LONG Printf( UBYTE *format, ... )
- {
- return( VPrintf(format, (LONG *)((long)&format + 4L)) );
- }
-
-
- main( int argc, char *argv[] )
- {
- long sgns;
-
- if( argc > 1 )
- {
- if( argv[1][0]=='-' && argv[1][1]=='w' )
- mitFenster = TRUE;
- }
- init();
-
- while(1)
- {
-
- sgns = Wait( abbruch | taktmask );
-
- if( sgns & taktmask )
- {
- D(PutStr("TAKT!\n"));
-
- nextton();
- SetSignal( 0, taktmask );
- }
-
- if( sgns & abbruch )
- {
- closedown();
- }
-
- }
- }
-
-
- void dump_param( void )
- {
- char buf[8];
- long i;
- void ftoa( double val, char *buf, int prec, int type );
-
- Printf( "Kanal=%ld\n", channel );
- Printf( "Instr=%ld\n", instr );
- Printf( "FreqMitte=%ld\n", freqmitte );
- Printf( "FreqAbw=%ld\n", freqabw );
- Printf( "VolMitte=%ld\n", volmitte );
- Printf( "VolAbw=%ld\n", volabw );
- ftoa( pausen, buf, 2, 1 );
- Printf( "Pausen=%s\n", buf );
- ftoa( tonaus, buf, 2, 1 );
- Printf( "TonAus=%s\n", buf );
- Printf( "Skala=%s\n", skala );
-
- for( i=0; i<=11; i++ )
- {
- if( cskala[i][0] )
- Printf( "CSkala=%02ld:%s\n", i, cskala[i] );
- }
-
- Printf( "Ende\n", NULL );
- }
-
-
- BOOL parse_param( char *par )
- {
- static char key[64];
- char *ks = key;
- double atof( char * );
- long atol( char * );
-
- // Keyword parsen
- while( *par != '\0' && *par != '=' )
- *ks++ = *par++;
- *ks = '\0';
- // par hinter '=' positionieren
- par++;
-
- if( stricmp(key,"KANAL")==0 )
- channel = atol(par);
- else if( stricmp(key,"INSTR")==0 )
- instr = atol(par);
- else if( stricmp(key,"FREQMITTE")==0 )
- freqmitte = atol(par);
- else if( stricmp(key,"FREQABW")==0 )
- freqabw = atol(par);
- else if( stricmp(key,"VOLMITTE")==0 )
- volmitte = atol(par);
- else if( stricmp(key,"VOLABW")==0 )
- volabw = atol(par);
- else if( stricmp(key,"PAUSEN")==0 )
- pausen = atof(par);
- else if( stricmp(key,"TONAUS")==0 )
- tonaus = atof(par);
- else if( stricmp(key,"SKALA")==0 )
- strncpy( skala, par, 12 );
- else if( stricmp(key,"CSKALA")==0 )
- strncpy( cskala[atol(par)], par+3, 12 );
- else
- return FALSE; // Unbekanntes Keyword -> Ende
-
- // OK
- return TRUE;
- }
-
-
- void read_param( void )
- {
- char buf[512];
-
- memset( cskala, 0, sizeof(cskala) );
- D(PutStr( "Bitte Parameter eingeben:\n" ));
-
- while( gets(buf) )
- if( !parse_param(buf) )
- return; // Eingabe-Ende durch unbekanntes Keyword
- }
-
-
- void init( void )
- {
- struct MsgPort *p;
- char buf[16];
- void sran( double );
- void ProgChange( int );
-
- D(PutStr("init\n"));
-
- // Parameter einlesen
- read_param();
-
- // die Midi.library brauchen wir
- MidiBase = OpenLibrary( MIDINAME, MIDIVERSION );
- if( !MidiBase ) {
- PutStr("Benötigt midi.library!\n");
- closedown(); }
-
- // eine Midi-Datenquelle kreieren
- sprintf( buf, "AMSource%03ld",
- ((struct Process *)SysBase->ThisTask)->pr_TaskNum );
- src = CreateMSource( buf, NULL );
-
- // und diese auf MidiOut routen
- outroute = MRouteSource(src, "MidiOut", &outinfo);
-
- taktport = CreateMsgPort();
- taktmsg.tm_msg.mn_ReplyPort = taktport;
- taktmsg.tm_msg.mn_Length = sizeof taktmsg;
-
- taktsig = AllocSignal(-1);
- taktmask = 1L << taktsig;
-
- taktmsg.tm_op = OP_ADD;
- taktmsg.tm_task = SysBase->ThisTask;
- taktmsg.tm_sig = taktmask;
-
- Forbid();
- if( p = FindPort("TAKT") )
- PutMsg( p, &taktmsg );
- Permit();
-
- if( p )
- {
- D(PutStr("OP_ADD abgeschickt\n"));
- WaitPort( taktport );
- GetMsg( taktport );
- if( taktmsg.tm_task )
- {
- PutStr("Kein Taktslot mehr frei!\n");
- closedown();
- }
- }
- else
- {
- PutStr("Takt läuft nicht!\n");
- closedown();
- }
- D(PutStr("OP_ADD ok\n"));
-
- sran( (double) clock() );
- if( instr >= 0 ) ProgChange( instr );
-
- // GUI starten (goodie - egal ob ok)
- if( mitFenster )
- {
- D(PutStr("startwindow...\n"));
- startwindow();
- }
- }
-
-
- void closedown( void )
- {
- struct MsgPort *p;
- void AllNotesOff( void );
-
- D(PutStr("closedown\n"));
- closewindow();
-
- AllNotesOff();
- if(outroute) DeleteMRoute(outroute);
- if(src) DeleteMSource(src);
- if(MidiBase) CloseLibrary(MidiBase);
-
- taktmsg.tm_op = OP_REM;
- taktmsg.tm_task = SysBase->ThisTask;
-
- Forbid();
- if( p = FindPort("TAKT") )
- PutMsg( p, &taktmsg );
- Permit();
-
- if( p )
- {
- WaitPort( taktport );
- GetMsg( taktport );
- }
-
- FreeSignal( taktsig );
- DeleteMsgPort( taktport );
-
- // die (evtl. geänderten) Parameter ausgeben
- dump_param();
-
- exit(0);
- }
-
-
- void NoteOn( int note, int vel ) // Ton einschalten
- {
- UBYTE msg[3];
-
- msg[0] = MS_NOTEON | channel;
- msg[1] = note;
- msg[2] = vel;
- PutMidiMsg(src, msg);
- }
-
- void NoteOff( int note ) // Ton ausschalten */
- {
- UBYTE msg[3];
-
- msg[0] = MS_NOTEOFF | channel;
- msg[1] = note;
- msg[2] = 64;
- PutMidiMsg(src, msg);
- }
-
- void AllNotesOff( void ) // Alle Töne ausschalten
- {
- UBYTE msg[3];
-
- msg[0] = MS_MODE | channel;
- msg[1] = MM_ALLOFF;
- msg[2] = 0;
- PutMidiMsg(src, msg);
- }
-
- void ProgChange( int nr ) // Sound wechseln
- {
- UBYTE msg[3];
-
- msg[0] = MS_PROG | channel;
- msg[1] = nr;
- msg[2] = 0;
- PutMidiMsg(src, msg);
- }
-
-
- void nextton( void )
- {
- static int last_note = 0;
- int vel;
- char *akt_skala;
- double r, ran();
- // ran() ist aus unerfindlichen Gründen hier negativ
-
- // ...wenn hier kein Kommentar steht... oder manchmal... oder...
-
- // ach scheiss drauf
- r = fabs(ran());
- D(printf("%lf\n",r));
-
- if( r > pausen )
- {
- // neue Note...
- D(PutStr("nextnote\n"));
- NoteOff( last_note );
-
- // Nächste erlaubte Note suchen (Skala)
- if( *(akt_skala = cskala[ last_note % 12 ]) == 0 )
- akt_skala = skala;
-
- last_note = freqmitte + 2 * freqabw * (0.50 - fabs(ran()));
- while( akt_skala[ last_note % 12 ] == '0' ) ++last_note;
-
- // Lautstärkegewichtung entsprechend Skala
- vel = volmitte + 2 * volabw * (0.50 - fabs(ran()));
- vel *= ( akt_skala[ last_note % 12 ] - '0' ) / 9.0;
-
- // Einblendung:
- if( volblend < 1.0 )
- {
- vel *= volblend;
- volblend += 0.1;
- }
-
- D(printf("key=%d, vel=%d\n",last_note,vel));
- NoteOn( last_note, vel );
- }
- else
- {
- // Pause: Ton evtl. ausschalten?
- D(PutStr("pause\n"));
-
- if( fabs(ran()) < tonaus )
- {
- NoteOff( last_note );
- }
- }
- }
-