⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 seqread.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************               seqread.c -- Phase 1 of adagio compilation... this module parses adagio programs and builds a linked list structure consisting of notes and control changes in time order. Copyright 1989 Carnegie Mellon University*****************************************************************************//******************************************************************************       Change Log*  Date     | Change*-----------+-----------------------------------------------------------------* 31-Dec-85 | Created changelog* 31-Dec-85 | Add c:\ to include directives* 31-Dec-85 | Added standard command scanner, metronome variable, need to add *           | cmdline_help procedure* 31-Dec-85 | Call intr_init* 31-Dec-85 | Set musictrace from command line via -trace* 31-Dec-85 | Added -poll*  1-Jan-86 | Put error messages out to stderr*  1-Jan-86 | Set IsAT.     Can be later overridden by -at and -xt switches,*           | currently only used for diagnostics (may be needed for*           | compatibles, who knows?  In which case remove the tests which*           | confirm the type of processor)*  1-Jan-86 | <rgd/jmn> Removed dur-adjusted message*  1-Jan-86 | Added miditrace* 18-Jan-86 | Shortened durations by 1/200 s to avoid roundoff problems --*           | see buildnote for details.*  3-Mar-86 | Allow octave and accidentals in either order after pitch name.*           | Default octave is now one that gets nearest previous pitch,*           |  the tritone (half an octave) interval is descending by default.*           | Special commands handled by table search, !Rate command added*           |  to scale all times by a percentage (50 = half speed).*  9-Mar-86 | Use space to limit amount of storage allocation.    Otherwise*           |    exhausting storage in phase1 caused phase2 to fail.* 12-Mar-86 | Broke off command line parser into adagio.c, only parser remains* 24-Mar-86 | Changed representation from note_struct to event_struct*           | Parse M, N, O, X, and Y as control change commands* 23-May-86 | Added , and ; syntax: "," means "N0\n", ";" means "\n"* 16-Jul-86 | modify to only call toupper/lower with upper/lower case as*           |  parameter to be compatible with standard C functions*  7-Aug-86 | fixed bug with default pitches and rests*  5-Jul-87 | F.H: Introduced new memory handling from Mac version.*           |    Changed:    init()*           |       ins_event()*           |       ins_ctrl()*           |       ins_note()*           |    Deleted:    reverse()*           |       nalloc()*           |    Introduced:    event_alloc()*           |       phase1_FreeMem()*           |       system.h & system.c dependencies* 10-Feb-88 | fixed parseend to accept blanks and tabs,*           | fixed rate scaling of durations* 11-Jun-88 | commented out gprintf of \n to ERROR after parsing finished.* 13-Oct-88 | JCD : exclusive AMIGA version.* 13-Apr-89 | JCD : New portable version.* 31-Jan-90 | GWL : Cleaned up for LATTICE* 30-Jun-90 | RBD : further changes*  2-Apr-91 | JDW : further changes* 30-Jun-91 | RBD : parse '+' and '/' in durations, * after space is comment* 28-Apr-03 |  DM : changes for portability*****************************************************************************/#include "switches.h"#include <stdio.h>#include <string.h>#include "cext.h"#include "cmdline.h"#include "midifns.h" /* to get time_type */#include "timebase.h"#include "moxc.h"    /* to get debug declared */#include "seq.h"#include "seqread.h"#include "userio.h"/* ctype.h used to be included only by UNIX and AMIGA,   surely everyone wants this? */#include "ctype.h"#ifndef toupper/* we're already taking precautions, so inline version of toupper is ok: */#define toupper(c) ((c)-'a'+'A')/* CAUTION: AZTEC V5.0 defines an inline version of toupper called _toupper,   but they got it wrong! */#endif/* cmtcmd.h references amiga message ports */#ifdef AMIGA#ifdef LATTICE#include "amiga.h"#endif#include "exec/exec.h"#endif#include "cmtcmd.h"/* public stuff */extern long space;    /* remaining free bytes */extern int abort_flag;/**************************************************************************** The following are used to simulate fixed point with the radix point 8 bits from the right:****************************************************************************/#define precise(x) (((time_type) x) << 8)#define seqround(x) ((((time_type) x) + 128) >> 8)#define trunc(x) (((time_type) x) >> 8)#define nullstring(s) (s[0] == EOS)/***************************************************************************** Routines local to this module:****************************************************************************/private void            do_a_rest();private time_type       doabsdur();private int             doabspitch();private void            doclock();private void            docomment();private void            doctrl();private void            dodef();private time_type       dodur();private void            doerror();private int             doloud();void            domacro();private void            donextdur();private int             dopitch();private void            doprogram();private void            dorate();private void            doset();private void            dospecial();private time_type       dosymdur();private void            dotempo();private void            dotime();private void            dovoice();private void            fferror();private void            init();private int             issymbol();private void            marker();private void            parseend();private void            parsefield();private boolean         parsenote();private boolean         parseparm();private int             scan();private int             scan1();private long            scanint();private void            scansymb();private long            scansgnint();/***************************************************************************** data structures for parser lookup tables****************************************************************************/struct durt {    /* duration translation table */    char symbol;    time_type value;};#define durtable_len 7struct durt durtable[durtable_len] = {    {'W', 4800L},    {'H', 2400L},    {'Q', 1200L},    {'I', 600L},    {'S', 300L},    {'%', 150L},    {'^', 75L}};struct loudt {    /* loudness translation table */    char symbol[4];    int value;};struct loudt loudtable[] = {    {"PPP", 20},    {"PP\0", 26},    {"P\0\0", 34},    {"MP\0", 44},    {"MF\0", 58},    {"F\0\0", 75},    {"FF\0", 98},    {"FFF", 127}};char too_many_error[] = "Too many parameters";private char *ssymbols[] = {"TEMPO", "RATE", "CSEC", "MSEC",                             "SETI", "SETV", "CALL", "RAMP",                            "CLOCK", "DEF", "END"};#define sym_tempo 0#define sym_rate 1#define sym_csec 2#define sym_msec 3#define sym_seti 4#define sym_setv 5#define sym_call 6#define sym_ramp 7#define sym_clock 8#define sym_def 9#define sym_end 10/* number of symbols */#define sym_n 11#define linesize 100private char line[linesize];    /* the input line */private char token[linesize];    /* a token scanned from the input line */private boolean pitch_flag;    /* set when a pitch is indicated *//* (if controls changes are given, only allocate a note event if     *  a pitch was specified -- i.e. when pitch_flag is set)     */private boolean rest_flag;    /* set when a rest (R) is found *//* this flag is NOT inherited by the next line */private boolean symbolic_dur_flag;/* TRUE if last dur was not absolute         * (if this is set, then the default duration is changed         *  accordingly when the tempo is changed.)         */#define nctrl 8private boolean ctrlflag[nctrl];/* TRUE if control change was present         * ctrlflag[0] TRUE if ANY control change         * was present         */private int ctrlval[nctrl];/* the new value of the control */#define nmacroctrl 10short macctrlx;                 /* index into the following: */short macctrlnum[nmacroctrl];   /* macro ctrl number, e.g. for ~4(67), or                                 * number of parameters for a symbolic macro */short macctrlparmx[nmacroctrl]; /* ctrl value for ctrl change, or index of                                 * parameters for symbolic macro */short macctrlparms[nmacroctrl*nmacroparms]; /* parameters for symbolic macros */short macctrlnextparm;def_type macctrldef[nmacroctrl]; /* definition for symbolic macro */private time_type time_scale; /* 1000 if centisec, 100 if millisec *//* note: user_specified_time * (time_scale / rate) = millisec *//******************************************************************************    variables private to this module*****************************************************************************/private boolean end_flag = FALSE;    /* set "true" when "!END" is seen *//*****************************************************************************               state variables* Because each line of an Adagio score inherits properties from the previous* line, it makes sense to implement the parser as a collection of routines* that make small changes to some global state.     For example, pitch is a* global variable.  When the field G4 is encountered, the dopitch routine* assigns the pitch number for G4 to the variable pitch.  After all fields* are processed, these variables describe the current note and contain the* default parameters for the next note as well.** Global variables that are used in this way by the parsing rountines are:****************************************************************************/private intlinex,    /* index of the next character to be scanned */lineno,    /* current line number */fieldx,    /* index of the current character within a field */pitch,    /* pitch of note */loud,    /* loudness of note */voice,    /* voice (midi channel) of note */artic;  /* articulation (a percentage of duration) */private boolean ndurp;  /* set when a next (N) is indicated *//* (next time defaults to the current time plus duration unless     *  overridden by a next (N) command whose presence is signalled     *  by ndurp.)     */private time_typethetime,    /* the starting time of the note */rate,    /* time rate -- scales time and duration, default = 100 */ntime,    /* the starting time of the next note */dur,    /* the duration of the note */tempo,    /* the current tempo */start,    /* the reference time (time of last !tempo or !rate cmd) */ticksize; /* set by !clock command, zero for no clock */private int pitchtable[7] = {     69, 71, 60, 62, 64, 65, 67 };extern char score_na[name_length];private seq_type the_score;  /* this is the score we are parsing *//* def_append -- append a byte to the current definition *//* * The def data structure: *     [code][offset][code][offset]...[0][length][data][data][data]... * where code is 1:nmacroparms for %n, *               nmacroparms+1 for %v, *               nmacroparms+2:nmacroparms*2+1 for ^n * and offset is the byte offset (from the offset byte) to the data *      where the parameter should be substituted * and length is the number of data bytes */boolean def_append(def, nparms, data)  unsigned char def[];  int nparms;  int data;{    int base = (nparms << 1) + 1;       /* this byte is the length */    /* first parameter has to be able to reference last byte: */    if ((def[base])++ >= (254 - (nparms << 1))) {        fferror("Data too long");        return FALSE;    }    def[base + def[base]] = data;    return TRUE;}def_type def_lookup(symbol)  char *symbol;{    def_type defn = seq_dictionary(the_score);    while (defn) {        if (strcmp(defn->symbol, symbol) == 0) {            return defn;        }        defn = defn->next;    }    return NULL;}void def_parm(def, nparms, code)  unsigned char def[];  int nparms;  int code;{    int i, j;    /* in order to insert a 2-byte parameter descriptor, the offsets from     * previous descriptors (that precede the data) need to be increased by 2:     */    for (i = 1; i < (nparms << 1); i += 2) {        def[i] += 2;    }    /* now i is index of length; work backwards from the last byte, moving     * everything up by 2 bytes to make room for the new descriptor:     */    for (j = i + def[i] + 2; j > i; j--) {        def[j] = def[j - 2];    }    /* now i is index of offset; insert the descriptor code (first byte)     * and the offset to the parameter location in the message (second byte)     */    def[i - 1] = code;    def[i] = def[i + 2] + 2;}/*****************************************************************************               do_a_rest* Effect: parses a rest (R) command****************************************************************************/private void do_a_rest(){    if (token[fieldx])        fferror("Nothing expected after rest");    rest_flag = TRUE;}/*****************************************************************************               doabsdur* Effect: parses an absolute dur (U) command****************************************************************************/private time_type doabsdur(){    time_type result=1000L;    register char c;    if (isdigit(token[fieldx])) {        result = precise(scanint());        /* allow comma or paren for use in parameter lists */        if ((c = token[fieldx]) && (c != ',') && (c != ')') && (c != '+')) {            fferror("U must be followed by digits only");        }        if (time_scale == 1000) result *= 10; /* convert to ms */    } else fferror("No digit after U");    return result;}/*****************************************************************************               doabspitch* Effect: parses an absolute pitch (P) command****************************************************************************/private int doabspitch(){    int result = 60;    int startx = fieldx;    register char c;    int savex;    if (isdigit (token[fieldx])) {        result = (int) scanint();        /* allow comma or paren for abspitch in parameter */        if ((c = token[fieldx]) && c != ',' && c != ')')            fferror("P must be followed by digits only");        else if (result < minpitch) {            savex = fieldx;            fieldx = startx;            fferror("Minimum pitch of 0 will be used");            result = minpitch;            fieldx = savex;        } else if (result > maxpitch) {            savex = fieldx;            fieldx = startx;            fferror("Maximum pitch of 127 will be used");            result = maxpitch;            fieldx = savex;        }    } else fferror("No digits after P");    return result;}/* doartic -- compute an articulation factor *//*  NOTE: artic is a percentage that scales the duration  of notes but not the time to the next note onset. It  is applied to the final computed duration after all  other scaling is applied. */private void doartic(){    if (isdigit(token[fieldx])) {        artic = (int) scanint();        if (token[fieldx])            fferror("Only digits were expected here");    } else fferror("No digits after /");}/* docall -- parse a call in the form !CALL fn(p1,p2,p3) *//**/private void docall(){    boolean error_flag = TRUE;    ndurp = FALSE;    linex += scan();    if (token[0] == 0) fferror("Function name expected");    else {        char symbol[100];        struct symb_descr *desc;        long value[SEQ_MAX_PARMS];        int i=0;        scansymb(symbol);        if (fieldx == 1) fferror("Routine name expected");        else if (token[fieldx] != '(') fferror("Open paren expected");        else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -