File: seqinterf.c

package info (click to toggle)
nyquist 3.20%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 58,008 kB
  • sloc: ansic: 74,743; lisp: 17,929; java: 10,723; cpp: 6,690; sh: 171; xml: 58; makefile: 40; python: 15
file content (160 lines) | stat: -rw-r--r-- 4,795 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/* seqinterf.c -- interface to sequence data type for XLISP */

#include "switches.h"
#include "xlisp.h"
#include "stdio.h"
#include "cext.h"
#include "userio.h"
#include "midifns.h"
#include "timebase.h"
#include "moxc.h"
#include "seq.h"
#include "seqinterf.h"
#include "seqmwrite.h"

/* seq_next -- advance to the next event, return TRUE if found */
/**/
boolean seq_next(seq_type seq)
{
    if (seq->current) {
        seq->current = seq->current->next;
    }
    return seq->current != NULL;
}


/* seq_get -- get event data for the current event */
/**/
void seq_get(seq_type seq, long *eventtype, long *ntime, long *line, long *chan,
             long *value1, long *value2, long *dur)
{
    event_type ev = seq->current;
    if (!ev) *eventtype = SEQ_DONE;
    else if (is_note(ev)) {
        if (ev->value != NO_PITCH) {
            *eventtype = SEQ_NOTE;
            *ntime = ev->ntime;
            *line = ev->nline;
            *chan = vc_voice(ev->nvoice) - 1;
            *value1 = ev->value;
            *value2 = ev->u.note.ndur & 0xFF;
            *dur = ev->u.note.ndur >> 8;
        } else {
            *eventtype = SEQ_OTHER;
        }
    } else {
        *eventtype = SEQ_CTRL;
        *ntime = ev->ntime;
        *line = ev->nline;
        *chan = vc_voice(ev->nvoice) - 1;
        *value2 = ev->value;
        
        switch (vc_ctrl(ev->nvoice)) {
          case PSWITCH_CTRL:
            *value1 = PORTASWITCH;
            break;
          case MODWHEEL_CTRL:
            *value1 = MODWHEEL;
            break;
          case TOUCH_CTRL:
            *eventtype = SEQ_CPRESS;
            break;
          case VOLUME_CTRL:
            *value1 = VOLUME;
            break;
          case BEND_CTRL:
            // for historical reasons, value is one byte and bend is one byte.
            // the true bend precision is -127 to +127, but this is multiplied
            // by 64 to give a 14-bit range of about -8K to +8K:
            *eventtype = SEQ_BEND;
            *value2 = ev->value << 6;
            break;
          case PROGRAM_CTRL:
            *eventtype = SEQ_PRGM;
            break;
          case ESC_CTRL:
            switch (ev->value) {
              case CALL_VALUE:
              case CLOCK_VALUE:
              case MACRO_VALUE:
              case CTRLRAMP_VALUE:
              case DEFRAMP_VALUE:
              case SETI_VALUE:
                *eventtype = SEQ_OTHER;
                break;
              case MACCTRL_VALUE:
                *value1 = ev->u.macctrl.ctrl_number;
                *value2 = ev->u.macctrl.value;
                break;
              default:
                xlabort("unexpected ESC_CTRL value\n");
                break;
            }
            break;
          default:
            xlabort("unexpected seq data\n");
            break;
        }
    }
}


/* seq_insert_note -- create and insert a note in sequence */
/*     only differs from insert_note in that channels are zero-based */
void seq_insert_note(seq_type seq, time_type ntime, int nline, int chan,
                     int pitch, time_type dur, int loud)
{
    insert_note(seq, ntime, nline, chan + 1, pitch, dur, loud);
}


/* seq_insert_ctrl -- create and insert a control, bend, program, etc. */
void seq_insert_ctrl(seq_type seq, long time, long line, long ctrltype,
                     long chan, long ctrlnum, long value)
{
    chan = (chan & 0x0F) + 1;
    switch (ctrltype) {
      case SEQ_CTRL: {
        // for historical (pre-midi) reasons, seq has some special cases
        // for certain control numbers. These are detected here.
        int ctrl = 0;
        switch (ctrlnum) {
          case PORTASWITCH: ctrl = PSWITCH_CTRL; break;
          case MODWHEEL: ctrl = MODWHEEL_CTRL; break;
          case VOLUME: ctrl = VOLUME_CTRL; break;
        }
        if (ctrl) {
            insert_ctrl(seq, time, line, ctrl, chan, value);
        } else {
            insert_macctrl(seq, time, line, ctrlnum, chan, value);
        }
        break;
      } 
      case SEQ_PRGM:
        insert_ctrl(seq, time, line, PROGRAM_CTRL, chan, value);
        break;
      case SEQ_CPRESS:
        insert_ctrl(seq, time, line, TOUCH_CTRL, chan, value);
        break;
      case SEQ_BEND:
        insert_ctrl(seq, time, line, BEND_CTRL, chan, value);
        break;
      default:
        break;
    }
}


/* seq_xlwrite_smf -- invoke seq_write_smf and mark file as closed */
void seq_xlwrite_smf(seq_type seq, LVAL outfile)
{
    if (streamp(outfile)) {
        if (getfile(outfile) == NULL) {
            xlfail("file for seq_write_smf not open");
        }
        seq_write_smf(seq, getfile(outfile));
        setfile(outfile, NULL); /* mark file as closed */
    } else {
        xlerror("seq_write_smf 2nd arg must be a STREAM", outfile);
    }
}