zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

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 }