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
161
162
163
164
165
166
167
168
169
|
/* Copyright (c) 2001-2003 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* squeak and squeal: sequencing utilities, a prototype version
(the main, 'sq' part of the library) */
/* LATER move everything not needed in mifi to squeal */
#ifndef __SQ_H__
#define __SQ_H__
/* Generic buffer structure, the `base' for t_squeve, t_squmpi and t_squax */
typedef struct _squb
{
uint32 b_length; /* length of data currently used (in items) */
uchar *b_data; /* data buffer */
size_t b_bufsize; /* allocated size of data buffer (in bytes) */
} t_squb;
/* Generic event structure. Designed as an interface to squeak routines,
and not to be kept in arrays or lists (use sequence containers instead).
Data buffer is automatically allocated and resized by those routines. */
typedef struct _squeve
{
uint32 e_length; /* set for any event type! */
uchar *e_data;
size_t e_bufsize;
uint32 e_delay;
} t_squeve;
/* tempo map element */
typedef struct _squmpo
{
t_float te_onset; /* ticks or microseconds from start of sequence */
uint32 te_value; /* microseconds per beat */
} t_squmpo;
typedef struct _squmpi
{
uint32 m_ntempi;
t_squmpo *m_map;
size_t m_bufsize; /* allocated size of m_map array in bytes */
} t_squmpi;
/* track/subtrack map element */
typedef struct _squack
{
int tr_id; /* according to target template */
uint32 tr_nevents; /* number of events (in this track or pre-total) */
t_symbol *tr_name; /* track name */
void *tr_head; /* pointer to first event */
} t_squack;
typedef struct _squax
{
uint32 m_ntracks;
t_squack *m_map;
size_t m_bufsize; /* allocated size of m_map array in bytes */
} t_squax;
/* generic type of callback routines used to read/write
sequence containers through t_squiter */
typedef int (*t_squiterhook)(void *it);
#define SQUITER_SEEKHOOK 0
#define SQUITER_INCRHOOK 1
#define SQUITER_GETEVEHOOK 2
#define SQUITER_SETEVEHOOK 3
#define SQUITER_GETTIMHOOK 4
#define SQUITER_SETTIMHOOK 5
#define SQUITER_GETTARHOOK 6
#define SQUITER_SETTARHOOK 7
#define SQUITER_NHOOKS 8
/* LATER move these typedefs to sq.c, if still not used globally */
typedef int (*t_squiter_seekhook)(void *it, int offset);
typedef void (*t_squiter_incrhook)(void *it);
typedef void (*t_squiter_getevehook)(void *it, t_squeve *evp, int *ret);
typedef void (*t_squiter_setevehook)(void *it, t_squeve *evp, int *ret);
typedef t_float (*t_squiter_gettimhook)(void *it, int *ret);
typedef void (*t_squiter_settimhook)(void *it, t_float v, int *ret);
typedef t_symbol (*t_squiter_gettarhook)(void *it, int *ret);
typedef void (*t_squiter_settarhook)(void *it, t_symbol *s, int *ret);
/* elements might be 'atoms' or whole events, whatever suits better */
typedef struct _squiter
{
void *i_owner;
int i_nelems;
void *i_sequence; /* first element pointer */
void *i_element; /* current element pointer */
int i_index; /* current element index */
t_squiterhook i_hooks[SQUITER_NHOOKS];
} t_squiter;
/* This is a good candidate for a derivation hierarchy. */
typedef struct _sq
{
t_squiter *s_myiter;
t_squax *s_mytracks;
t_squmpi *s_mytempi; /* use shortcuts #defined below */
void *s_auxeve; /* auxiliary event */
uint32 s_nevents; /* total number of events */
FILE *s_fp; /* hmm... */
int s_autoalloc:1; /* set if auto-allocated */
int s_eof:1; /* reading: set in case of early eof (error) */
int s_newtrack:1; /* reading: set if first event in a track */
int s_anapass:1; /* read/write: set during analysis (pass #1) */
uchar s_nframes; /* fps if nonzero, else use metrical time */
uint16 s_nticks; /* number of ticks per beat or per frame */
uint16 s_format; /* `ismultitrack' flag, LATER add other formats */
uint32 s_time; /* current time in ticks */
uint32 s_tempo; /* current tempo, or last one encountered in a file */
int s_trackid; /* LATER remove? */
uint16 s_track; /* current track number */
/* fields below are specific to midifile streams */
uchar s_status; /* current running status, | channel in writing */
uchar s_channel; /* current channel, not used in writing */
uint16 s_hdtracks; /* number of tracks declared in a midifile header */
uint32 s_alltracks; /* total number of nonempty tracks */
/* (s_ntracks counts `in range' nonempty tracks) */
float s_timecoef; /* msecs->ticks, used in writing only */
uint32 s_bytesleft; /* nbytes remaining to be read from current track,
or number of bytes written to a track so far */
} t_sq;
#define s_ntempi s_mytempi->m_ntempi
#define s_tempomap s_mytempi->m_map
#define s_tempo_onset(ndx) s_mytempi->m_map[ndx].te_onset
#define s_tempo_value(ndx) s_mytempi->m_map[ndx].te_value
#define s_ntracks s_mytracks->m_ntracks
#define s_trackmap s_mytracks->m_map
#define s_track_id(ndx) s_mytracks->m_map[ndx].tr_id
#define s_track_nevents(ndx) s_mytracks->m_map[ndx].tr_nevents
#define s_track_name(ndx) s_mytracks->m_map[ndx].tr_name
#define s_track_head(ndx) s_mytracks->m_map[ndx].tr_head
/* prototypes of public interface routines */
size_t squb_checksize(void *buf, size_t reqcount, size_t elsize);
#define squiter_inrange(it) ((it)->i_index < (it)->i_nelems)
void *squiter_new(t_sq *x);
t_squiter_seekhook squiter_seekhook(t_squiter *x);
t_squiter_incrhook squiter_incrhook(t_squiter *x);
t_squiter_getevehook squiter_getevehook(t_squiter *x);
t_squiter_setevehook squiter_setevehook(t_squiter *x);
t_squiter_gettimhook squiter_gettimhook(t_squiter *x);
t_squiter_settimhook squiter_settimhook(t_squiter *x);
t_squiter_gettarhook squiter_gettarhook(t_squiter *x);
t_squiter_settarhook squiter_settarhook(t_squiter *x);
void squmpi_sort(t_sq *x);
t_squmpo *squmpi_add(t_sq *x);
void squmpo_reset(t_squmpo *x);
t_squack *squax_add(t_sq *x);
void squack_reset(t_squack *x);
float sq_ticks2msecs(t_sq *x, uint32 tempo);
float sq_msecs2ticks(t_sq *x, uint32 tempo);
void sq_fold_time(t_sq *x);
void sq_unfold_time(t_sq *x);
t_sq *sq_new(void);
void sq_reset(t_sq *x);
void sq_free(t_sq *x);
#endif
|