2 ZynAddSubFX - a software synthesizer
4 WatchPoint.cpp - Synthesis State Watcher
5 Copyright (C) 2015-2015 Mark McCurry
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of version 2 of the GNU General Public License
9 as published by the Free Software Foundation.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License (version 2 or later) for more details.
16 You should have received a copy of the GNU General Public License (version 2)
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "WatchPoint.h"
23 #include "../Misc/Util.h"
25 #include <rtosc/thread-link.h>
29 WatchPoint::WatchPoint(WatchManager
*ref
, const char *prefix
, const char *id
)
30 :active(false), samples_left(0), reference(ref
)
34 fast_strcpy(identity
, prefix
, sizeof(identity
));
36 strncat(identity
, id
, sizeof(identity
)-1);
39 bool WatchPoint::is_active(void)
41 //Either the watchpoint is already active or the watchpoint manager has
42 //received another activation this frame
46 if(reference
&& reference
->active(identity
)) {
55 bool WatchPoint::is_empty(void)
57 //return reference->is_empty(identity);
61 FloatWatchPoint::FloatWatchPoint(WatchManager
*ref
, const char *prefix
, const char *id
)
62 :WatchPoint(ref
, prefix
, id
)
65 VecWatchPoint::VecWatchPoint(WatchManager
*ref
, const char *prefix
, const char *id
)
66 :WatchPoint(ref
, prefix
, id
)
69 WatchManager::WatchManager(thrlnk
*link
)
70 :write_back(link
), new_active(false)
72 memset(active_list
, 0, sizeof(active_list
));
73 memset(sample_list
, 0, sizeof(sample_list
));
74 memset(prebuffer_sample
, 0, sizeof(prebuffer_sample
));
75 memset(data_list
, 0, sizeof(data_list
));
76 memset(deactivate
, 0, sizeof(deactivate
));
77 memset(prebuffer
, 0, sizeof(prebuffer
));
78 memset(trigger
, 0, sizeof(trigger
));
79 memset(prebuffer_done
, 0, sizeof(prebuffer_done
));
80 memset(call_count
,0,sizeof(call_count
));
84 void WatchManager::add_watch(const char *id
)
86 //Don't add duplicate watchs
87 for(int i
=0; i
<MAX_WATCH
; ++i
)
88 if(!strcmp(active_list
[i
], id
))
90 //Apply to a free slot
91 for(int i
=0; i
<MAX_WATCH
; ++i
) {
92 if(!active_list
[i
][0]) {
93 fast_strcpy(active_list
[i
], id
, MAX_WATCH_PATH
);
97 //printf("\n added watchpoint ID %s\n",id);
103 void WatchManager::del_watch(const char *id
)
105 //Queue up the delete
106 for(int i
=0; i
<MAX_WATCH
; ++i
)
107 if(!strcmp(active_list
[i
], id
))
108 return (void) (deactivate
[i
] = true);
111 void WatchManager::tick(void)
113 //Try to send out any vector stuff
114 for(int i
=0; i
<MAX_WATCH
; ++i
) {
117 if(strstr(active_list
[i
], "noteout") != NULL
)
118 framesize
= MAX_SAMPLE
-1;
119 if(sample_list
[i
] >= framesize
&& call_count
[i
]==0) {
120 char arg_types
[MAX_SAMPLE
+1] = {};
121 rtosc_arg_t arg_val
[MAX_SAMPLE
];
122 for(int j
=0; j
<sample_list
[i
]; ++j
) {
124 arg_val
[j
].f
= data_list
[i
][j
];
126 write_back
->writeArray(active_list
[i
], arg_types
, arg_val
);
127 deactivate
[i
] = true;
131 //Cleanup internal data
134 //Clear deleted slots
135 for(int i
=0; i
<MAX_WATCH
; ++i
) {
137 memset(active_list
[i
], 0, MAX_SAMPLE
);
139 memset(data_list
[i
], 0, sizeof(float)*MAX_SAMPLE
);
140 memset(prebuffer
[i
], 0, sizeof(float)*(MAX_SAMPLE
/2));
141 deactivate
[i
] = false;
143 prebuffer_done
[i
] = false;
144 prebuffer_sample
[i
] = 0;
149 bool WatchManager::active(const char *id
) const
153 if(new_active
|| true)
154 for(int i
=0; i
<MAX_WATCH
; ++i
)
155 if(!strcmp(active_list
[i
], id
))
161 bool WatchManager::trigger_active(const char *id
) const
163 for(int i
=0; i
<MAX_WATCH
; ++i
)
164 if(!strcmp(active_list
[i
], id
))
169 int WatchManager::samples(const char *id
) const
171 for(int i
=0; i
<MAX_WATCH
; ++i
)
172 if(!strcmp(active_list
[i
], id
))
173 return sample_list
[i
];
177 void WatchManager::satisfy(const char *id
, float f
)
179 //printf("trying to satisfy '%s'\n", id);
181 write_back
->write(id
, "f", f
);
185 void WatchManager::satisfy(const char *id
, float *f
, int n
)
188 for(int i
=0; i
<MAX_WATCH
; ++i
)
189 if(!strcmp(active_list
[i
], id
))
195 int space
= MAX_SAMPLE
- sample_list
[selected
];
197 if(space
>= n
|| !trigger
[selected
])
200 //special case to capture the time+level pairs that come from
203 trigger
[selected
] = true;
205 if(space
&& (call_count
[selected
]==0 || n
== 2)){
206 for(int i
=0; i
<space
; i
++){
207 const float prev
= prebuffer
[selected
][(prebuffer_sample
[selected
]+MAX_SAMPLE
/2-1)%(MAX_SAMPLE
/2)];
208 if(!trigger
[selected
]){
209 prebuffer
[selected
][prebuffer_sample
[selected
]%(MAX_SAMPLE
/2)] = f
[i
];
210 prebuffer_sample
[selected
]++;
211 //printf("\n before trigger %s prebuffer at index %d %f \n",active_list[selected],prebuffer_sample[selected],prebuffer[selected][prebuffer_sample[selected]%(MAX_SAMPLE/2)]);
213 if(!trigger
[selected
] && prebuffer_sample
[selected
] >= (MAX_SAMPLE
/2)){
214 if (prev
<= 0 && f
[i
] > 0){
215 //printf("\n trigger at %s prebuffer at index %f %d f[i] %f \n",active_list[selected],prebuffer[selected][prebuffer_sample[selected]%(MAX_SAMPLE/2)-2],prebuffer_sample[selected],f[i]);
216 trigger
[selected
] = true;
217 for(int j
= 0; j
< (MAX_SAMPLE
/2); ++j
){
218 data_list
[selected
][sample_list
[selected
]] = prebuffer
[selected
][prebuffer_sample
[selected
]%(MAX_SAMPLE
/2)];
219 sample_list
[selected
]++;
220 prebuffer_sample
[selected
]++;
222 prebuffer_done
[selected
] = true;
223 space
= MAX_SAMPLE
- sample_list
[selected
];
228 trigger_other(selected
);
232 if(trigger
[selected
] && !prebuffer_done
[selected
]){
233 data_list
[selected
][sample_list
[selected
]] = f
[i
];
234 sample_list
[selected
]++;
237 if(prebuffer_done
[selected
])
238 prebuffer_done
[selected
] = false;
241 call_count
[selected
]++;
244 void WatchManager::trigger_other(int selected
){
245 for(int k
=0; k
<MAX_WATCH
; ++k
){
246 if(selected
!= k
&& !trigger
[k
] && prebuffer_sample
[k
]>(MAX_SAMPLE
/2) ){
249 strcpy(tmp
, active_list
[selected
]);
250 strcpy(tmp1
, active_list
[k
]);
251 if(strlen(active_list
[k
]) < strlen(active_list
[selected
]))
252 tmp
[strlen(tmp
)-1] =0;
253 else if (strlen(active_list
[k
]) > strlen(active_list
[selected
]))
254 tmp1
[strlen(tmp1
)-1] =0;
255 //printf("\n compare tmp1 %s with tmp %s \n",tmp1,tmp);
256 if(!strcmp(tmp1
,tmp
)){
258 // printf("\n putting prebuffer size of %d into %s watchpoint \n",prebuffer_sample[k]%(MAX_SAMPLE/2),active_list[k]);
259 // printf("\n value of first buffer %f \n",prebuffer[k][prebuffer_sample[k]%(MAX_SAMPLE/2)]);
260 for(int j
= prebuffer_sample
[k
]%(MAX_SAMPLE
/2); j
< (MAX_SAMPLE
/2); ++j
){
261 data_list
[k
][sample_list
[k
]] = prebuffer
[k
][j
];
264 for(int j
= 0; j
< prebuffer_sample
[selected
]%(MAX_SAMPLE
/2); ++j
){
265 data_list
[k
][sample_list
[k
]] = prebuffer
[k
][j
];
268 //prebuffer_done[k] = true;
269 //printf("\n t Trigger for %s happen at sample %d \n",active_list[k],sample_list[k] );