Util.cpp (7291B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 Util.cpp - Miscellaneous functions 5 Copyright (C) 2002-2005 Nasca Octavian Paul 6 Author: Nasca Octavian Paul 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 */ 13 14 #include "globals.h" 15 #include "Util.h" 16 #include <vector> 17 #include <cassert> 18 #include <cmath> 19 #include <cstdio> 20 #include <fstream> 21 22 #include <sys/types.h> 23 #include <sys/stat.h> 24 #include <fcntl.h> 25 #include <unistd.h> 26 #include <errno.h> 27 #include <string.h> 28 #ifdef HAVE_SCHEDULER 29 #include <sched.h> 30 #endif 31 32 #define errx(...) {} 33 #ifndef errx 34 #include <err.h> 35 #endif 36 37 #include <rtosc/rtosc.h> 38 39 namespace zyn { 40 41 bool isPlugin = false; 42 43 prng_t prng_state = 0x1234; 44 45 /* 46 * Transform the velocity according the scaling parameter (velocity sensing) 47 */ 48 float VelF(float velocity, unsigned char scaling) 49 { 50 float x; 51 x = powf(VELOCITY_MAX_SCALE, (64.0f - scaling) / 64.0f); 52 if((scaling == 127) || (velocity > 0.99f)) 53 return 1.0f; 54 else 55 return powf(velocity, x); 56 } 57 58 char *fast_strcpy(char *dest, const char *src, size_t buffersize) 59 { 60 *dest = 0; 61 return strncat(dest, src, buffersize-1); 62 } 63 64 /* 65 * Get the detune in cents 66 */ 67 float getdetune(unsigned char type, 68 unsigned short int coarsedetune, 69 unsigned short int finedetune) 70 { 71 float det = 0.0f, octdet = 0.0f, cdet = 0.0f, findet = 0.0f; 72 //Get Octave 73 int octave = coarsedetune / 1024; 74 if(octave >= 8) 75 octave -= 16; 76 octdet = octave * 1200.0f; 77 78 //Coarse and fine detune 79 int cdetune = coarsedetune % 1024; 80 if(cdetune > 512) 81 cdetune -= 1024; 82 83 int fdetune = finedetune - 8192; 84 85 switch(type) { 86 // case 1: is used for the default (see below) 87 case 2: 88 cdet = fabsf(cdetune * 10.0f); 89 findet = fabsf(fdetune / 8192.0f) * 10.0f; 90 break; 91 case 3: 92 cdet = fabsf(cdetune * 100.0f); 93 findet = powf(10, fabsf(fdetune / 8192.0f) * 3.0f) / 10.0f - 0.1f; 94 break; 95 case 4: 96 cdet = fabsf(cdetune * 701.95500087f); //perfect fifth 97 findet = 98 (powf(2, fabsf(fdetune / 8192.0f) * 12.0f) - 1.0f) / 4095 * 1200; 99 break; 100 //case ...: need to update N_DETUNE_TYPES, if you'll add more 101 default: 102 cdet = fabsf(cdetune * 50.0f); 103 findet = fabsf(fdetune / 8192.0f) * 35.0f; //almost like "Paul's Sound Designer 2" 104 break; 105 } 106 if(finedetune < 8192) 107 findet = -findet; 108 if(cdetune < 0) 109 cdet = -cdet; 110 111 det = octdet + cdet + findet; 112 return det; 113 } 114 115 116 bool fileexists(const char *filename) 117 { 118 struct stat tmp; 119 int result = stat(filename, &tmp); 120 if(result >= 0) 121 return true; 122 123 return false; 124 } 125 126 void set_realtime() 127 { 128 #ifdef HAVE_SCHEDULER 129 sched_param sc; 130 sc.sched_priority = 60; 131 //if you want get "sched_setscheduler undeclared" from compilation, 132 //you can safely remove the following line: 133 sched_setscheduler(0, SCHED_FIFO, &sc); 134 //if (err==0) printf("Real-time"); 135 #endif 136 } 137 138 139 140 #ifdef WIN32 141 #include <windows.h> 142 143 //https://stackoverflow.com/questions/5801813/c-usleep-is-obsolete-workarounds-for-windows-mingw 144 void os_usleep(long usec) 145 { 146 HANDLE timer; 147 LARGE_INTEGER ft; 148 149 ft.QuadPart = -(10*usec); // Convert to 100 nanosecond interval, negative value indicates relative time 150 151 timer = CreateWaitableTimer(NULL, TRUE, NULL); 152 SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); 153 WaitForSingleObject(timer, INFINITE); 154 CloseHandle(timer); 155 } 156 #else 157 158 void os_usleep(long length) 159 { 160 usleep(length); 161 } 162 #endif 163 164 //!< maximum length a pid has on any POSIX system 165 //!< this is an estimation, but more than 12 looks insane 166 constexpr std::size_t max_pid_len = 12; 167 168 //!< safe pid length guess, posix conform 169 std::size_t os_guess_pid_length() 170 { 171 const char* pid_max_file = "/proc/sys/kernel/pid_max"; 172 if(-1 == access(pid_max_file, R_OK)) { 173 return max_pid_len; 174 } 175 else { 176 std::ifstream is(pid_max_file); 177 if(!is.good()) 178 return max_pid_len; 179 else { 180 std::string s; 181 is >> s; 182 for(const auto& c : s) 183 if(c < '0' || c > '9') 184 return max_pid_len; 185 return std::min(s.length(), max_pid_len); 186 } 187 } 188 } 189 190 //!< returns pid padded, posix conform 191 std::string os_pid_as_padded_string() 192 { 193 char result_str[max_pid_len << 1]; 194 std::fill_n(result_str, max_pid_len, '0'); 195 std::size_t written = snprintf(result_str + max_pid_len, max_pid_len, 196 "%d", (int)getpid()); 197 // the below pointer should never cause segfaults: 198 return result_str + max_pid_len + written - os_guess_pid_length(); 199 } 200 201 std::string legalizeFilename(std::string filename) 202 { 203 for(int i = 0; i < (int) filename.size(); ++i) { 204 char c = filename[i]; 205 if(!(isdigit(c) || isalpha(c) || (c == '-') || (c == ' '))) 206 filename[i] = '_'; 207 } 208 return filename; 209 } 210 211 void invSignal(float *sig, size_t len) 212 { 213 for(size_t i = 0; i < len; ++i) 214 sig[i] *= -1.0f; 215 } 216 217 float SYNTH_T::numRandom() 218 { 219 return RND; 220 } 221 222 float interpolate(const float *data, size_t len, float pos) 223 { 224 assert(len > (size_t)pos + 1 && pos >= 0); 225 const unsigned int l_pos = (int)pos; 226 const unsigned int r_pos = l_pos + 1; 227 const float rightness = pos - (float)l_pos; 228 return data[l_pos] + (data[r_pos] - data[l_pos]) * rightness; 229 } 230 231 float cinterpolate(const float *data, size_t len, float pos) 232 { 233 const unsigned int i_pos = (int)pos; 234 const unsigned int l_pos = i_pos % len; 235 const unsigned int r_pos = (l_pos + 1) < len ? l_pos + 1 : 0; 236 const float rightness = pos - (float)i_pos; 237 return data[l_pos] + (data[r_pos] - data[l_pos]) * rightness; 238 } 239 240 char *rtosc_splat(const char *path, std::set<std::string> v) 241 { 242 char argT[v.size()+1]; 243 rtosc_arg_t arg[v.size()]; 244 unsigned i=0; 245 for(auto &vv : v) { 246 argT[i] = 's'; 247 arg[i].s = vv.c_str(); 248 i++; 249 } 250 argT[v.size()] = 0; 251 252 size_t len = rtosc_amessage(0, 0, path, argT, arg); 253 char *buf = new char[len]; 254 rtosc_amessage(buf, len, path, argT, arg); 255 return buf; 256 } 257 258 void expanddirname(std::string &dirname) { 259 if (dirname.empty()) 260 return; 261 262 // if the directory name starts with a ~ and the $HOME variable is 263 // defined in the environment, replace ~ by the content of $HOME 264 if (dirname.at(0) == '~') { 265 char *home_dirname = getenv("HOME"); 266 if (home_dirname != NULL) { 267 dirname = std::string(home_dirname) + dirname.substr(1); 268 } 269 } 270 271 #ifdef ZYN_DATADIR 272 { 273 std::string var = "$ZYN_DATADIR"; 274 size_t pos = dirname.find(var); 275 if (pos != std::string::npos) { 276 dirname.replace(pos, var.length(), ZYN_DATADIR); 277 } 278 } 279 #endif 280 281 normalizedirsuffix(dirname); 282 } 283 284 void normalizedirsuffix(std::string &dirname) { 285 if(((dirname[dirname.size() - 1]) != '/') 286 && ((dirname[dirname.size() - 1]) != '\\')) 287 dirname += "/"; 288 } 289 290 }