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
|
#ifndef UTIL_H
#define UTIL_H
/* Mostly types, constants, and macros */
/* A simple singly linked list */
/* Push a node to the singly linked list. */
#define PUSH_NODE(NUM_VAR, POINTER, CUR, VALUE, TYPE) { \
(NUM_VAR)++; \
if (NUM_VAR > 1) { \
(POINTER) = MYALLOC(Node_t, 1); \
*(POINTER) = (CUR); \
(CUR) = (Node_t) { (Node_v) { .TYPE=(VALUE) }, (POINTER) }; \
} else { \
(CUR) = (Node_t) { (Node_v) { .TYPE=(VALUE) }, NULL }; \
} \
}
/* Pop one node out of the singly linked list. */
#define POP_NODE(NUM_VAR, X, CUR, NEXT, TYPE) { \
(NUM_VAR)--; \
X = CUR.value.TYPE; \
if (CUR.next) { \
NEXT = *(CUR.next); \
free(CUR.next); \
CUR = NEXT; \
} \
}
/* An empty node. */
#define EMPTY_NODE (Node_t) { (Node_v) { .n=0 }, NULL }
typedef union {
/* the typedef for NUMT is below, so I cannot use that alias. */
double n;
void *v; /* very evil */
} Node_v;
typedef struct Node {
Node_v value;
struct Node *next;
} Node_t;
/* macros */
#define MYALLOC(X, Y) ((X *) malloc(sizeof(X)*Y)) /* The most useful macro perhaps */
/* Constant macros */
#define SAMPLE_RATE 44100.0f
#define DEFAULT_OUTPUT_NAME "output.mp3"
#define STDP 440.0f
/* I don't want to use a global variable for this constant. */
#define STD_BASE 1.059463094359295f
/* TODO: Set Volume, and other settings in the sheet. */
/* These can now be changed in the sheet. */
#define BPM 120.0f
#define BEAT_DUR (60.0f / BPM)
/* Frequency modulation */
#define FM_FREQUENCY 2.0f
#define FM_AMP 0.02f
/* For ADSR */
#define ATTACK_P 0.01f
#define DECAY_P 0.495f
#define RELEASE_P 0.49f
#define SUSTAIN_P (1.0f-(ATTACK_P+DECAY_P+RELEASE_P))
#define SUSTAIN_LEVEL 0.7f
/* attribute macros */
#define AHC_ATTR __attribute__((__always_inline__, __hot__, __const__))
#define AH_ATTR __attribute__((__always_inline__, __hot__))
#define HC_ATTR __attribute__((__hot__, __const__))
#define H_ATTR __attribute__((__hot__))
#define UNUSED __attribute__((__unused__))
#define U_ATTR UNUSED
#define D_ATTR(X) __attribute__((__unused__, __deprecated__("This is deprecated.\n" \
"Please use " X \
" instead")))
#define UC_ATTR __attribute__((__unused__, __const__))
#define UH_ATTR __attribute__((__unused__, __hot__))
#define UHA_ATTR __attribute__((__unused__, __hot__, __always_inline__))
/* types */
typedef unsigned long LENT;
typedef double NUMT;
typedef NUMT Volume;
typedef NUMT Samples;
typedef NUMT Hertz;
typedef NUMT Seconds;
typedef NUMT Pulse;
typedef NUMT Beats;
typedef NUMT Semitones;
typedef Pulse *Wave;
typedef struct {
Wave w;
LENT n;
} WaveFrag;
/* supported instrument types */
typedef enum {
PIANO,
DRUMKICK
} InstrumentTypes;
/* some helper functions */
U_ATTR LENT max(LENT a, LENT b);
U_ATTR LENT min(LENT a, LENT b);
UNUSED long read_entire_file(const char *file_name, char **str);
U_ATTR WaveFrag mix_waves(WaveFrag *frags, LENT len);
HC_ATTR Hertz stoh(const Semitones st);
#endif
|