-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsampler.h
141 lines (130 loc) · 3.48 KB
/
sampler.h
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
#ifndef CSYNTH_SAMPLER_H
#define CSYNTH_SAMPLER_H
#include "../core/func.h"
#include "../core/gen.h"
#include "../util/error.h"
#define SAMPLE_RATE 44100 // 44.1 kHz
#define DISPLAY_RATE 10 // 10 FPS
#define CONTROL_RATE 100 // 100 FPS
#define COMPUTE_RATE 200 // 1000 FPS
#define VOLUME_MULTIPLIER 0.5
typedef int16_t sample_t;
/**
* @brief Sampler state
*/
typedef struct
{
/** @brief Array of output channels */
Gen **channels;
/** @brief Number of output channels */
size_t count;
/** @brief Sampling context passed into generator */
Eval eval;
} Sampler;
/**
* @brief Create a sampler with multiple channels.
*
* @param sample_rate Sample rate, e.g. 44100.
* @param count Number of channels.
* @param inputs Array of input functions.
* @return Sampler* Sampler instance.
*/
Sampler *sampler_create(size_t sample_rate, size_t count, Func **inputs)
{
Sampler *sampler = (Sampler *)malloc_(sizeof(Sampler));
if (sampler == NULL)
{
return error_null(csErrorMemoryAlloc);
}
Gen **channels = (Gen **)malloc_(count * sizeof(Gen *));
if (channels == NULL)
{
free_(sampler);
return error_null(csErrorMemoryAlloc);
}
for (size_t index = 0; index < count; index++)
{
Func *input = inputs[index];
Gen *channel = gen_create(input);
if (channel == NULL)
{
for (size_t i = 0; i < index; i++)
{
gen_free(channels[i]);
}
free_(channels);
free_(sampler);
return NULL;
}
channels[index] = channel;
}
double tick = 1.0 / (double)sample_rate;
Eval eval = {
.wall_tick = tick,
.compute_time = 1.0,
.compute_tick = COMPUTE_RATE * tick,
};
eval.params[EvalParamControlTick] = CONTROL_RATE * tick;
eval.params[EvalParamDisplayTick] = DISPLAY_RATE * tick;
eval.params[EvalParamPitchTick] = tick;
eval.params[EvalParamTempoTick] = tick;
eval.params[EvalParamSustainTick] = tick;
*sampler = (Sampler){
.channels = channels,
.count = count,
.eval = eval,
};
return sampler;
}
sample_t sampler_quantize(double output)
{
double scaled = output * VOLUME_MULTIPLIER;
double clip = scaled > 1.0 ? 1.0 : (scaled < -1.0 ? -1.0 : scaled);
return (sample_t)(clip * 32767);
}
void sampler_eval_next(Eval *eval)
{
eval->wall_time += eval->wall_tick;
eval->compute_time += eval->compute_tick;
if (eval->compute_time >= 1.0)
{
eval->compute_flag = true;
eval->compute_time -= 1.0;
}
else
{
eval->compute_flag = false;
}
}
void sampler_sample(Sampler *sampler, size_t count, sample_t *buffer)
{
for (size_t frame = 0; frame < count; frame++)
{
sampler_eval_next(&sampler->eval);
for (size_t index = 0; index < sampler->count; index++)
{
double output = gen_eval(sampler->channels[index], &sampler->eval);
*(buffer++) = sampler_quantize(output);
}
}
}
void sampler_free(Sampler *sampler)
{
for (size_t index = 0; index < sampler->count; index++)
{
gen_free(sampler->channels[index]);
}
free_(sampler->channels);
sampler->channels = NULL;
free_(sampler);
}
size_t sampler_gen_count(Sampler *sampler)
{
size_t sum = 0;
for (size_t index = 0; index < sampler->count; index++)
{
sum += gen_count(sampler->channels[index]);
}
return sum;
}
#endif // CSYNTH_SAMPLER_H