WatchPoint.cpp (9085B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 WatchPoint.cpp - Synthesis State Watcher 5 Copyright (C) 2015-2015 Mark McCurry 6 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. 10 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. 15 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 19 20 */ 21 22 #include "WatchPoint.h" 23 #include "../Misc/Util.h" 24 #include <cstring> 25 #include <rtosc/thread-link.h> 26 27 namespace zyn { 28 29 WatchPoint::WatchPoint(WatchManager *ref, const char *prefix, const char *id) 30 :active(false), samples_left(0), reference(ref) 31 { 32 identity[0] = 0; 33 if(prefix) 34 fast_strcpy(identity, prefix, sizeof(identity)); 35 if(id) 36 strncat(identity, id, sizeof(identity)-1); 37 } 38 39 bool WatchPoint::is_active(void) 40 { 41 //Either the watchpoint is already active or the watchpoint manager has 42 //received another activation this frame 43 if(active) 44 return true; 45 46 if(reference && reference->active(identity)) { 47 active = true; 48 samples_left = 1; 49 return true; 50 } 51 52 return false; 53 } 54 55 bool WatchPoint::is_empty(void) 56 { 57 //return reference->is_empty(identity); 58 return true; 59 } 60 61 FloatWatchPoint::FloatWatchPoint(WatchManager *ref, const char *prefix, const char *id) 62 :WatchPoint(ref, prefix, id) 63 {} 64 65 VecWatchPoint::VecWatchPoint(WatchManager *ref, const char *prefix, const char *id) 66 :WatchPoint(ref, prefix, id) 67 {} 68 69 WatchManager::WatchManager(thrlnk *link) 70 :write_back(link), new_active(false) 71 { 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)); 81 82 } 83 84 void WatchManager::add_watch(const char *id) 85 { 86 //Don't add duplicate watchs 87 for(int i=0; i<MAX_WATCH; ++i) 88 if(!strcmp(active_list[i], id)) 89 return; 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); 94 new_active = true; 95 sample_list[i] = 0; 96 call_count[i] = 0; 97 //printf("\n added watchpoint ID %s\n",id); 98 break; 99 } 100 } 101 } 102 103 void WatchManager::del_watch(const char *id) 104 { 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); 109 } 110 111 void WatchManager::tick(void) 112 { 113 //Try to send out any vector stuff 114 for(int i=0; i<MAX_WATCH; ++i) { 115 int framesize = 2; 116 call_count[i] = 0; 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) { 123 arg_types[j] = 'f'; 124 arg_val[j].f = data_list[i][j]; 125 } 126 write_back->writeArray(active_list[i], arg_types, arg_val); 127 deactivate[i] = true; 128 } 129 } 130 131 //Cleanup internal data 132 new_active = false; 133 134 //Clear deleted slots 135 for(int i=0; i<MAX_WATCH; ++i) { 136 if(deactivate[i]) { 137 memset(active_list[i], 0, MAX_SAMPLE); 138 sample_list[i] = 0; 139 memset(data_list[i], 0, sizeof(float)*MAX_SAMPLE); 140 memset(prebuffer[i], 0, sizeof(float)*(MAX_SAMPLE/2)); 141 deactivate[i] = false; 142 trigger[i] = false; 143 prebuffer_done[i] = false; 144 prebuffer_sample[i] = 0; 145 } 146 } 147 } 148 149 bool WatchManager::active(const char *id) const 150 { 151 assert(this); 152 assert(id); 153 if(new_active || true) 154 for(int i=0; i<MAX_WATCH; ++i) 155 if(!strcmp(active_list[i], id)) 156 return true; 157 158 return false; 159 } 160 161 bool WatchManager::trigger_active(const char *id) const 162 { 163 for(int i=0; i<MAX_WATCH; ++i) 164 if(!strcmp(active_list[i], id)) 165 return trigger[i]; 166 return false; 167 } 168 169 int WatchManager::samples(const char *id) const 170 { 171 for(int i=0; i<MAX_WATCH; ++i) 172 if(!strcmp(active_list[i], id)) 173 return sample_list[i]; 174 return 0; 175 } 176 177 void WatchManager::satisfy(const char *id, float f) 178 { 179 //printf("trying to satisfy '%s'\n", id); 180 if(write_back) 181 write_back->write(id, "f", f); 182 del_watch(id); 183 } 184 185 void WatchManager::satisfy(const char *id, float *f, int n) 186 { 187 int selected = -1; 188 for(int i=0; i<MAX_WATCH; ++i) 189 if(!strcmp(active_list[i], id)) 190 selected = i; 191 192 if(selected == -1) 193 return; 194 195 int space = MAX_SAMPLE - sample_list[selected]; 196 197 if(space >= n || !trigger[selected]) 198 space = n; 199 200 //special case to capture the time+level pairs that come from 201 //envelopes/LFOs 202 if(n == 2) 203 trigger[selected] = true; 204 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)]); 212 } 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]++; 221 } 222 prebuffer_done[selected] = true; 223 space = MAX_SAMPLE - sample_list[selected]; 224 if(n >= i+space) 225 space = i+space; 226 else 227 space = n; 228 trigger_other(selected); 229 } 230 } 231 232 if(trigger[selected] && !prebuffer_done[selected]){ 233 data_list[selected][sample_list[selected]] = f[i]; 234 sample_list[selected]++; 235 } 236 237 if(prebuffer_done[selected]) 238 prebuffer_done[selected] = false; 239 } 240 } 241 call_count[selected]++; 242 } 243 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) ){ 247 char tmp[128]; 248 char tmp1[128]; 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)){ 257 trigger[k] = true; 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]; 262 sample_list[k]++; 263 } 264 for(int j = 0; j < prebuffer_sample[selected]%(MAX_SAMPLE/2); ++j){ 265 data_list[k][sample_list[k]] = prebuffer[k][j]; 266 sample_list[k]++; 267 } 268 //prebuffer_done[k] = true; 269 //printf("\n t Trigger for %s happen at sample %d \n",active_list[k],sample_list[k] ); 270 } 271 } 272 } 273 } 274 275 276 }