~pbatch/patchwerk

patchwerk/examples/test_4.c -rw-r--r-- 5.9 KiB
9c265356 — paul plan9 additions from Sigrid 4 months ago
                                                                                
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include <stdlib.h>
#include <soundpipe.h>
#include "patchwerk.h"
#include "sine.h"
#include "biscale.h"
#include "sinosc.h"
#include "scaler.h"
#include "adder.h"
#include "noisy.h"

typedef struct {
    pw_patch *patch;
    pw_cable *out;
    int pos;
} user_data;

static void process(sp_data *sp, void *ptr)
{
    user_data *ud;
    ud = ptr;
    SPFLOAT out;

    if(ud->pos == 0) {
        pw_patch_compute(ud->patch);
    }

    out = pw_cable_get(ud->out, ud->pos);
    ud->pos = (ud->pos + 1) % BLKSIZE;
    sp_out(sp, 0, out);
}

static void bufferpool_status(pw_patch *patch)
{
    pw_stack *stack;
    pw_bufferpool *pool;

    stack = pw_patch_stack(patch);
    pool = pw_patch_pool(patch);
    printf("\tbuffer stack pos: %d\n", pw_stack_pos(stack));
    printf("\tactive buffers: %d\n", pw_bufferpool_nactive(pool));
}


/* 4 1 sinosc bdup 100 800 scaler 0.5 sine bswap noisy add */

int main(int argc, char *argv[])
{
    sp_data *sp;
    user_data ud;
    pw_node *node;
    pw_patch *patch;
    sinosc_d *lfo;
    sinosc_d *sinosc_1;
    noisy_d *noise;
    scaler_d *scaler;
    scaler_d *scaler_amp;
    adder_d *add;
    pw_stack *stack;

    sp_create(&sp);

    ud.pos = 0;
    ud.patch = malloc(pw_patch_size());
    pw_patch_init(ud.patch, BLKSIZE); 
    pw_patch_alloc(ud.patch, 8, 10);
    patch = ud.patch;
    stack = pw_patch_stack(patch);

    printf("Initial state\n");
    bufferpool_status(patch);
    /* Set up connections */
      
    /* LFO */
    printf("Adding LFO\n");
    pw_patch_new_node(patch, &node);

    /* node implicitly pushes value onto top of buffer stack */
    node_sinosc_v2(sp, node);
    lfo = pw_node_get_data(node);
    pw_cable_set_constant(lfo->amp, 1);
    pw_cable_set_constant(lfo->freq, 4);

    /* duplicate LFO value on the top stack, so the buffer can be used twice */
    pw_stack_dup(stack);
    /* this means that there are two items on the stack using only one buffer */
    bufferpool_status(patch);
    
    /* BISCALE (frequency) */
    printf("Adding BISCALE\n");

    
    /* pop LFO value off the stack, leavine one copy of the LFO buffer on
     * the stack.
     */
    pw_stack_pop(stack, NULL);

    /* Scaler will push a new value onto the top of the stack. 
     * Since LFO has been dup'd, it will not use that buffer.
     */
    pw_patch_new_node(patch, &node);
    node_scaler_v2(sp, node);

    scaler = pw_node_get_data(node);
    pw_cable_set_constant(scaler->min, 100);
    pw_cable_set_constant(scaler->max, 800);

    /* connect LFO to Biscale input */
    pw_cable_connect(lfo->out, scaler->in);
    bufferpool_status(patch);

    /* SINE */
    printf("Adding Sine\n");
    /* pop scaler value off stack, freeing the buffer it was writing to */
    pw_stack_pop(stack, NULL);

    pw_patch_new_node(patch, &node);

   
    /* The new sinosc will push an item to the buffer stack, reusing the buffer
     * used by the previous scaler.
     */
    node_sinosc_v2(sp, node);
    
    sinosc_1 = pw_node_get_data(node);
    pw_cable_set_constant(sinosc_1->amp, 0.5);
    pw_cable_set_constant(sinosc_1->freq, 880);
    
    /* connect biscale out to frequency */

    pw_cable_connect(scaler->out, sinosc_1->freq);
    bufferpool_status(patch);

    /* BISCALE (amplitude) */
    printf("adding another BISCALE\n");
    /* swap last two items on stack so that LFO is at top of the stack 
     * there are no copies left of the LFO left, so this buffer will be 
     * overwritten. 
     */
    pw_stack_swap(stack);

    pw_stack_pop(stack, NULL);

    pw_patch_new_node(patch, &node);
    /* The scaler pushes a value to the top of the stack, overwriting the 
     * buffer that the LFO wrote to.
     */
    node_scaler_v2(sp, node);

    scaler_amp = pw_node_get_data(node);
    pw_cable_set_constant(scaler_amp->min, 0);
    pw_cable_set_constant(scaler_amp->max, 0.3);

    bufferpool_status(patch);
    /* the LFO and the scaler happen to use the same buffer,
     * This means that the scaler is reading and immediately overwriting
     * from a single buffer automatically. 
     */
    pw_cable_connect(lfo->out, scaler_amp->in);

    /* NOISE */

    printf("Adding Noisy node\n");
    /* Pop the scaler value from the buffer stack. This will cause the
     * buffer to be overwritten.
     */
    pw_stack_pop(stack, NULL);
    pw_patch_new_node(patch, &node);

    /* This white noise node will push a value to the top of the buffer stack.
     * It will override the buffer previously used by the second scaler.
     */
    node_noisy(node);
    noise = pw_node_get_data(node);

    /* The scaler output and the noise output both use the same buffer.
     * The inner loop is reading from the buffer then immediately writing
     * a new value to it.
     */

    pw_cable_connect(scaler_amp->out, noise->amp); 

    /* There are now two values left on the stack now. The top item is
     * the modulated white noise, followed by the modulated sine wave.  
     */
    bufferpool_status(patch);

    /* Adder */
    printf("Adding Adder\n");

    /* pop the noise off the stack, as it is no longer being read after this */
    pw_stack_pop(stack, NULL);
    /* pop the sine off the stack, as it is no longer being read after this */
    pw_stack_pop(stack, NULL);

    /* create an adder node. This will sum two signals together. */
    pw_patch_new_node(patch, &node);
    node_adder(node);
    add = pw_node_get_data(node);
    bufferpool_status(patch);

    /* Connect both the noise and the sine as inputs. 
     * Analyzing the buffer stack, The adder is using the same buffer as the 
     * sine wave generator. It first reads the value before writing a new value
     * to it.
     */ 
    pw_cable_connect(sinosc_1->out, add->in1);
    pw_cable_connect(noise->out, add->in2);

    printf("Popping last value, setting output\n");
    pw_stack_pop(stack, NULL);
    bufferpool_status(patch);
    ud.out = add->out;
    sp_process(sp, &ud, process);

    pw_patch_destroy(patch);
    pw_patch_free_nodes(patch);

    free(ud.patch);
    sp_destroy(&sp);
    return 0;
}