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

📄 seq.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 3 页
字号:
/* seq.c -- implement adagio scores as abstract data type *//******************************************************************************       Change Log*  Date | Change*-----------+-----------------------------------------------------------------*  2-Apr-91 | JDW : further changes* 16-Feb-92 | GWL : use reg_timebase in seq_play()* 28-Apr-03 |  DM : false->FALSE, true->TRUE, portability changes* 19-May-03 | RBD : no longer assume seq->current remains untouched between *           |       note inserts*****************************************************************************/#include "stdio.h"#include "cext.h"#include "userio.h"#include "midicode.h"#include "midifns.h"#include "timebase.h"#include "moxc.h"#include "seq.h"#include "string.h"extern int moxcdebug;extern timebase_type default_base;boolean seq_print = FALSE;      /* debugging print switch */seq_type sequence;      /* this is a global to be accessed by routines called                         * from the sequence *//* clock state: */time_type clock_ticksize;       /* millisec per tick shifted 16 bits */boolean clock_running = FALSE;  /* TRUE if clock is running */boolean external_midi_clock = FALSE;boolean suppress_midi_clock = FALSE;private void insert_event();private void process_event();private char *chunk_alloc();private void clock_tick();private void ramp_event(seq_type seq, event_type event, unsigned int value,    unsigned int to_value, int increment, time_type step, int n);/*private*/ void send_macro();/* chunk_alloc -- allocate data for a sequence *//* * NOTE: This assumes one chunk is already allocated. * The first chunk holds shared sequence information in  * the info struct, and by convention this is always in * the first chunk. */private char *chunk_alloc(seq_type seq, int size){    chunk_type chunk = seq->chunklist->u.info.last_chunk;    /* gprintf(TRANS, "chunk_alloc: seq %lx size %d\n", seq, size); */    if (size & 1) size++;	/* make it even */    if (chunk->free + size >= CHUNK_SIZE) {        chunk_type new_chunk = chunk_create(FALSE);        if (!chunk) {            gprintf(FATAL, "Out of memory while reading seq\n");            return NULL;        }        /* add new_chunk to chunk chain */        seq->chunklist->u.info.last_chunk = new_chunk;        chunk->next = new_chunk;        chunk = new_chunk;    }    chunk->free += size;    return &(chunk->u.data[chunk->free - size]);}/* chunk_create -- create a new chunk for seq data *//* * If this is the first chunk, set first_flag to reserve * space for the info structure. */chunk_type chunk_create(boolean first_flag){    chunk_type result = (chunk_type) memget(sizeof(chunk_node));    if (result) {        result->next = NULL;        result->u.info.refcount = 1;  /* pre-initialize for caller */        result->free = 0;        if (first_flag) {            result->free = sizeof(struct info_struct);            result->u.info.last_chunk = result;            result->u.info.dictionary = NULL;            result->u.info.eventlist = NULL;             result->u.info.ctrlcount = 0;            result->u.info.notecount = 0;            result->u.info.duration = 0;            result->u.info.used_mask = 0;        }    }    /* gprintf(TRANS, "chunk_create: got %lx (size %d)\n", */                   /* result, sizeof(chunk_node)); */    return result;}/* clock_tick -- advance the clock and send a tick *//**/private void clock_tick(seq, fraction)  seq_type seq;  time_type fraction;{    int delay;    fraction += clock_ticksize;    delay = fraction >> 16;    fraction &= 0xFFFF;    if (seq->runflag && clock_ticksize && seq->note_enable) {        midi_clock();        cause((delay_type)delay, clock_tick, seq, fraction);    } else {        clock_running = FALSE;        midi_stop();        midi_clock(); /* stop takes effect on next clock, so provide one */    }}private void cycle(seq)  seq_type seq;{    seq_reset(seq);    seq_play(seq);}/*****************************************************************************               event_create* Inputs:*    seq_type seq: the seq to hold the event*    int size: the size of the event in bytes*    time_type etime: the time of the event*    int eline: the line number of the event* Returns:*    event_type: a new event structure or*               NULL if there is not enough memory left* Effect:*    allocates memory from the chunk, then heap as needed* Implementation:*    to reduce the per block storage overhead, we allocate memory in*    large chunks and do our own allocation.  Allocate from first*    chunk first.  If full, allocate a new chunk.* WARNING: this implementation assumes that individual events are never freed!!****************************************************************************/private event_type event_create(seq, size, etime, eline)  seq_type seq;  int size;  time_type etime;  int eline;{    event_type result = (event_type) chunk_alloc(seq, size);    if (result) {        result->ntime = etime;        result->nline = eline;        /* since we know the time, we can insert now: */        insert_event(seq, result);        seq_duration(seq) = MAX(seq_duration(seq), etime);    }    return result;}/* insert_call -- add a call event to the seq *//**/event_type insert_call(seq, ctime, cline, voice, addr, value, n)  seq_type seq;  time_type ctime;  int cline;  int voice;  int (*addr)();  long value[SEQ_MAX_PARMS];  int n;{    int i;    register event_type event = event_create(seq, callsize, ctime, cline);    if (seq_print) {        gprintf(TRANS,             "call(%lx): time %ld, line %d, voice %d, fn %lx,\n\tvalues:",            event, ctime, cline, voice, addr);        for (i = 0; i < n; i++) gprintf(TRANS, " %ld", value[i]);        gprintf(TRANS, "\n");    }    if (event) {        seq_used_mask(seq) |= 1 << (voice - 1);        event->nvoice = ctrl_voice(ESC_CTRL, voice);        event->value = CALL_VALUE;        event->u.call.routine = addr;        /* save the arguments */        for (i = 0; i < n; i++) event->u.call.args.a[i] = value[i];        seq_ctrlcount(seq)++;    }    return event;       }  /* insert_clock -- add a clock cmd to the seq *//**/event_type insert_clock(seq, ctime, cline, ticksize)  seq_type seq;  time_type ctime;  int cline;  time_type ticksize;{    register event_type event = event_create(seq, clocksize, ctime, cline);    if (seq_print) {        gprintf(TRANS, "clock(%lx): time %ld, line %d\n", event, ctime, cline);    }    if (event) {        event->nvoice = ctrl_voice(ESC_CTRL, 1);        event->value = CLOCK_VALUE;        event->u.clock.ticksize = ticksize;        seq_ctrlcount(seq)++;    }    return event;}/* insert_ctrl -- add a control to the seq *//**/event_type insert_ctrl(seq, ctime, cline, ctrl, voice, value)  seq_type seq;  time_type ctime;  int cline;  int ctrl;  int voice;  int value;{    register event_type event = event_create(seq, ctrlsize, ctime, cline);    if (seq_print) {        gprintf(TRANS,            "ctrl(%lx): time %ld, line %d, ctrl %d, voice %d, value %d\n",            event, ctime, cline, ctrl, voice, value);    }    if (event) {        seq_used_mask(seq) |= 1 << (voice - 1);        event->nvoice = ctrl_voice(ctrl, voice);        event->value = value;        seq_ctrlcount(seq)++;    }    return event;}/* insert_ctrlramp -- add a control ramp event to the seq *//**/event_type insert_ctrlramp(seq, rtime, rline, voice, step, dur, ctrl, v1, v2)  seq_type seq;  time_type rtime;  int rline;  int voice;  time_type step;  time_type dur;  int ctrl;  int v1, v2;{    register event_type event = event_create(seq, ctrlrampsize, rtime, rline);    if (seq_print) {        gprintf(TRANS,             "ctrlramp(%lx): time %ld, line %d, step %ld, dur %ld, ctrl %d, voice %d\n",            event, rtime, rline, step, dur, ctrl, voice);        gprintf(TRANS, "\tfrom %d to %d\n", v1, v2);    }    if (event) {        seq_used_mask(seq) |= 1 << (voice - 1);        event->nvoice = ctrl_voice(ESC_CTRL, voice);        event->value = CTRLRAMP_VALUE;        if (dur <= 0) dur = 1L; /* don't allow zero duration */        event->u.ramp.dur = dur;        event->u.ramp.ctrl = ctrl;        if (step <= 0) step = 1; /* don't allow zero step size */        event->u.ramp.step = (short) step;        event->u.ramp.u.ctrl.from_value = v1;        event->u.ramp.u.ctrl.to_value = v2;        seq_ctrlcount(seq)++;        seq_duration(seq) = MAX(seq_duration(seq), rtime + dur);    }    return event;}/* insert_def -- add a definition to the dictionary *//**/def_type insert_def(seq, symbol, definition, deflen)  seq_type seq;  char *symbol;  unsigned char *definition;  int deflen;{    int i;    def_type defn = (def_type) chunk_alloc(seq, sizeof(def_node));    defn->symbol = chunk_alloc(seq, strlen(symbol) + 1);    defn->definition = (unsigned char *) chunk_alloc(seq, deflen);    strcpy(defn->symbol, symbol);    for (i = 0; i < deflen; i++) {        defn->definition[i] = definition[i];    }    defn->next = seq_dictionary(seq);    seq_dictionary(seq) = defn;    if (seq_print) {        gprintf(TRANS, "def(%ld): symbol %s defn \n", defn, symbol);        for (i = 0; i < deflen; i++) gprintf(TRANS, "%x", definition[i]);        gprintf(TRANS, "\n");    }    return defn;}/* insert_deframp -- add a def ramp event to the seq *//**/event_type insert_deframp(seq, rtime, rline, voice, step, dur,                          def, nparms, parms, parm_num, to_value)  seq_type seq;  time_type rtime;  int rline;  int voice;  time_type step;  time_type dur;  def_type def;  int nparms;           /* number of parameters for macro */  short parms[];        /* actual parameter vector */  int parm_num;         /* which of the actual parameters to ramp */  int to_value;         /* final destination of ramp */{    register event_type event = event_create(seq, deframpsize, rtime, rline);    if (seq_print) {        int i;        gprintf(TRANS,             "deframp(%ld): time %ld, line %d, voice %d, step %ld, dur %ld\n",            event, rtime, rline, voice, step, dur);        gprintf(TRANS, "def %ld, parms");        for (i = 0; i < nparms; i++) gprintf(TRANS, " %d", parms[i]);        gprintf(TRANS, "parm_num %d to %d\n", parm_num, to_value);    }    if (event) {        int i;        seq_used_mask(seq) |= 1 << (voice - 1);        event->nvoice = ctrl_voice(ESC_CTRL, voice);        event->value = DEFRAMP_VALUE;        if (dur <= 0) dur = 1L; /* don't allow zero duration */        event->u.ramp.dur = dur;        event->u.ramp.ctrl = 0;        if (step <= 0) step = 1; /* don't allow zero step size */        event->u.ramp.step = (short) step;        event->u.ramp.u.def.definition = def->definition;         for (i = 0; i < nmacroparms; i++) {            event->u.ramp.u.def.parameter[i] = (i < nparms ? parms[i] : 0);        }        event->u.ramp.u.def.parm_num = parm_num;        event->u.ramp.u.def.to_value = to_value;        seq_ctrlcount(seq)++;        seq_duration(seq) = MAX(seq_duration(seq), rtime + dur);    }    return event;}/*****************************************************************************               insert_event* Inputs:*    seq_type seq: where to put the event*    event_type event: the event to insert* Effect:*    inserts event into the event list*    NOTE: it is inserted *after* previously inserted events with the same time* Implementation:*    adagio files often contain many independent voices.  Although each voice*    consists of events in sequence, the voices need not be inter-twined in*    the input file.  Rather, all the events of voice 1 appear followed by all*    the events of voice 2, and so forth.  As phase one merges these event*    sequences, it must make many passes over an increasingly long list of*    events: expensive if we always start from the beginning of the list!*    we can exploit the fact that each voice is sequential by starting the*    search for the proper point of insertion at the last event inserted.*    the variable "last_event" is used to remember this hint.  We could*    also snapshot "last_event" in "ref_event" when a !tempo or !rate*    command occurs as another hint, but we don't.****************************************************************************/private void insert_event(seq, event)  seq_type seq;  register event_type event;{    event_type *evlptr = &(seq_eventlist(seq));    if ((*evlptr == NULL) ||        (event->ntime < (*evlptr)->ntime)) {        /* insert at the head of the list */        event->next = *evlptr;        *evlptr = event;        seq->current = event;    } else {        /* insert somewhere after the head of the list         * do not assume: current is not NULL.  Although we always leave		 * it set, the client may access the sequence before the next		 * insert.         */        register event_type previous;

⌨️ 快捷键说明

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