-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathtest-pbpeffects.c
179 lines (159 loc) · 5.13 KB
/
test-pbpeffects.c
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
#define _DEFAULT_SOURCE
#include "../llsmrt.h"
#include "libpyin/pyin.h"
#include "verify-utils.h"
#ifdef USE_PTHREAD
#include <pthread.h>
#include <unistd.h>
#endif
#include <sys/time.h>
static double get_time() {
struct timeval t;
gettimeofday(&t, NULL);
return (t.tv_sec + (t.tv_usec / 1000000.0)) * 1000.0;
}
llsm_rtsynth_buffer* rtbuffer = NULL;
int nfrm = 0;
int nx = 0;
int latency = 0;
llsm_chunk* chunk = NULL;
FP_TYPE* y = NULL;
int synth_finish = 0;
#ifdef USE_PTHREAD
static void* synthesis_thread(void* ptr) {
printf("Synthesis thread: starting.\n");
for(int i = 0; i < nfrm; i ++) {
// llsm_rtsynth_buffer_feed blocks when the buffer is full.
llsm_rtsynth_buffer_feed(rtbuffer, chunk -> frames[i]);
}
printf("Synthesis thread: task completed.\n");
synth_finish = 1;
return NULL;
}
static void* reading_thread(void* ptr) {
printf("Reading thread: starting.\n");
int count = 0;
while(count < nx) {
FP_TYPE tmp = 0;
int status = llsm_rtsynth_buffer_fetch(rtbuffer, & tmp);
if(synth_finish) break;
if(status == 0) {
// llsm_rtsynth_buffer_fetch does not block.
// So give it a bit of time waiting for more samples to come.
usleep(10);
continue;
}
if(count >= latency) {
y[count - latency] = tmp;
}
count ++;
}
printf("Reading thread: task completed.\n");
return NULL;
}
#endif
// Pick a number that does not collide with any of the existing indices.
#define LLSM_FRAME_GROWLSTRENGTH 15
typedef struct {
int period_count;
FP_TYPE osc;
} growl_effect;
static void fgrowl_effect(llsm_gfm* gfm, FP_TYPE* delta_t, void* info_,
llsm_container* src_frame) {
growl_effect* info = info_;
FP_TYPE* ptr = llsm_container_get(src_frame, LLSM_FRAME_GROWLSTRENGTH);
FP_TYPE strength = ptr == NULL ? 1.0 : *ptr;
info -> period_count ++;
FP_TYPE lfo = sin(info -> period_count * 2 * M_PI / 50);
info -> osc += 2 * M_PI / (6 + lfo);
FP_TYPE osc = sin(info -> osc);
*delta_t = gfm -> T0 * 0.01 * randn(0, 1.0) * strength;
gfm -> Fa *= 1.0 - osc * 0.5 * strength;
gfm -> Rk *= 1.0 + osc * 0.3 * strength;
// reduce the modulation on H1 energy
gfm -> Ee *= 1.0 - osc * 0.5 * strength;
}
int main(int argc, char** argv) {
int fs = 0;
int nbit = 0;
FP_TYPE* x = wavread("test/are-you-ready.wav", & fs, & nbit, & nx);
int nhop = 128;
pyin_config param = pyin_init(nhop);
param.fmin = 50.0;
param.fmax = 500.0;
param.trange = 24;
param.bias = 2;
param.nf = ceil(fs * 0.025);
FP_TYPE* f0 = pyin_analyze(param, x, nx, fs, & nfrm);
llsm_aoptions* opt_a = llsm_create_aoptions();
opt_a -> thop = (FP_TYPE)nhop / fs;
opt_a -> npsd = 128;
opt_a -> rel_winsize = 4.0;
opt_a -> maxnhar = 400;
opt_a -> maxnhar_e = 5;
llsm_soptions* opt_s = llsm_create_soptions(fs);
chunk = llsm_analyze(opt_a, x, nx, fs, f0, nfrm, NULL);
llsm_chunk_tolayer1(chunk, 2048);
llsm_chunk_phasepropagate(chunk, -1);
opt_s -> use_l1 = 1;
int n_effect_begin = 2.0 / opt_a -> thop;
int n_effect_end = 4.4 / opt_a -> thop;
int n_fade = 20;
growl_effect growl_info = {0, 0};
for(int i = 0; i < nfrm; i ++) {
llsm_container_attach(chunk -> frames[i], LLSM_FRAME_HM, NULL, NULL, NULL);
if(i > n_effect_begin && i < n_effect_end) {
FP_TYPE* strength = llsm_create_fp(1.0);
llsm_container_attach(chunk -> frames[i], LLSM_FRAME_PBPSYN,
llsm_create_int(1), llsm_delete_int, llsm_copy_int);
if(i < n_effect_begin + n_fade)
*strength = (FP_TYPE)(i - n_effect_begin) / n_fade;
if(i > n_effect_end - n_fade)
*strength = (FP_TYPE)(n_effect_end - i) / n_fade;
llsm_container_attach(chunk -> frames[i], LLSM_FRAME_PBPEFF,
llsm_create_pbpeffect(fgrowl_effect, & growl_info),
llsm_delete_pbpeffect, llsm_copy_pbpeffect);
llsm_container_attach(chunk -> frames[i], LLSM_FRAME_GROWLSTRENGTH,
strength, llsm_delete_fp, llsm_copy_fp);
}
}
llsm_chunk_phasepropagate(chunk, 1);
rtbuffer = llsm_create_rtsynth_buffer(opt_s, chunk -> conf, 4096);
latency = llsm_rtsynth_buffer_getlatency(rtbuffer);
y = calloc(nx, sizeof(FP_TYPE));
double t0 = get_time();
# ifdef USE_PTHREAD
printf("Main thread: launching threads.\n");
pthread_t threads[2];
pthread_create(& threads[0], NULL, & synthesis_thread, NULL);
pthread_create(& threads[1], NULL, & reading_thread, NULL);
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
# else
int count = 0;
for(int i = 0; i < nfrm; i ++) {
llsm_rtsynth_buffer_feed(rtbuffer, chunk -> frames[i]);
while(count < nx) {
FP_TYPE tmp = 0;
int status = llsm_rtsynth_buffer_fetch(rtbuffer, & tmp);
if(status == 0) break;
if(count >= latency) {
y[count - latency] = tmp;
}
count ++;
}
}
# endif
llsm_delete_rtsynth_buffer(rtbuffer);
double t1 = get_time();
wavwrite(y, nx, opt_s -> fs, 24, "test/test-pbpeffects.wav");
printf("Synthesis speed (llsmrt): %f ms, %fx real-time.\n", t1 - t0,
1000.0 / (t1 - t0) * ((FP_TYPE)nx / opt_s -> fs));
free(y);
llsm_delete_chunk(chunk);
llsm_delete_aoptions(opt_a);
llsm_delete_soptions(opt_s);
free(f0);
free(x);
return 0;
}