summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRJ Skerry-Ryan <rryan@mixxx.org>2018-10-15 21:42:01 -0700
committerRJ Skerry-Ryan <rryan@mixxx.org>2018-10-15 21:42:01 -0700
commit7e4d9f9f03816ed2d3a85d098d5da251340949ec (patch)
tree1a6decfb5a977301fe1366d8c76dd6ea409b2bcf /lib
parentdb8cc6a441e39e4307040649f7816331241c8c3b (diff)
parent9c12473b8edfbf3c814faa38c05e82c20babbca3 (diff)
Merge branch 'master' into remove-vamp
Diffstat (limited to 'lib')
-rw-r--r--lib/fidlib/CHANGELOG7
-rw-r--r--lib/fidlib/COPYING (renamed from lib/fidlib-0.9.10/COPYING)0
-rw-r--r--lib/fidlib/COPYING_LIB (renamed from lib/fidlib-0.9.10/COPYING_LIB)0
-rw-r--r--lib/fidlib/fidlib.c (renamed from lib/fidlib-0.9.10/fidlib.c)625
-rw-r--r--lib/fidlib/fidlib.h (renamed from lib/fidlib-0.9.10/fidlib.h)4
-rw-r--r--lib/fidlib/fidmkf.h (renamed from lib/fidlib-0.9.10/fidmkf.h)375
-rw-r--r--lib/fidlib/fidrf_cmdlist.h (renamed from lib/fidlib-0.9.10/fidrf_cmdlist.h)18
-rw-r--r--lib/fidlib/fidrf_combined.h (renamed from lib/fidlib-0.9.10/fidrf_combined.h)2
-rw-r--r--lib/fidlib/fidrf_jit.h (renamed from lib/fidlib-0.9.10/fidrf_jit.h)2
-rw-r--r--lib/gmock-1.7.0/include/gmock/gmock-spec-builders.h4
-rwxr-xr-xlib/hidapi-0.8.0-rc1/windows/hid.c4
-rw-r--r--lib/libebur128-1.1.0/test/tests.c218
-rw-r--r--lib/libebur128/.gitignore (renamed from lib/libebur128-1.1.0/.gitignore)0
-rw-r--r--lib/libebur128/CMakeLists.txt (renamed from lib/libebur128-1.1.0/CMakeLists.txt)12
-rw-r--r--lib/libebur128/COPYING (renamed from lib/libebur128-1.1.0/COPYING)0
-rw-r--r--lib/libebur128/README.md (renamed from lib/libebur128-1.1.0/README.md)32
-rw-r--r--lib/libebur128/cmake/utils.cmake (renamed from lib/libebur128-1.1.0/cmake/utils.cmake)0
-rw-r--r--lib/libebur128/doc/license/R128Scan.txt (renamed from lib/libebur128-1.1.0/doc/license/R128Scan.txt)0
-rw-r--r--lib/libebur128/doc/license/queue.txt (renamed from lib/libebur128-1.1.0/doc/license/queue.txt)0
-rw-r--r--lib/libebur128/ebur128/CMakeLists.txt (renamed from lib/libebur128-1.1.0/ebur128/CMakeLists.txt)50
-rw-r--r--lib/libebur128/ebur128/ebur128.c (renamed from lib/libebur128-1.1.0/ebur128/ebur128.c)567
-rw-r--r--lib/libebur128/ebur128/ebur128.def26
-rw-r--r--lib/libebur128/ebur128/ebur128.h (renamed from lib/libebur128-1.1.0/ebur128/ebur128.h)130
-rw-r--r--lib/libebur128/ebur128/libebur128.pc.cmake11
-rw-r--r--lib/libebur128/ebur128/queue/sys/queue.h (renamed from lib/libebur128-1.1.0/ebur128/queue/sys/queue.h)0
-rw-r--r--lib/libebur128/test/CMakeLists.txt (renamed from lib/libebur128-1.1.0/test/CMakeLists.txt)0
-rw-r--r--lib/libebur128/test/minimal-example.c (renamed from lib/libebur128-1.1.0/test/minimal-example.c)0
-rw-r--r--lib/libebur128/test/tests.c426
-rw-r--r--lib/qm-dsp/dsp/segmentation/cluster_segmenter.c2
-rw-r--r--lib/qm-dsp/dsp/signalconditioning/DFProcess.cpp1
-rw-r--r--lib/qm-dsp/dsp/tempotracking/DownBeat.cpp2
-rw-r--r--lib/qm-dsp/dsp/tempotracking/TempoTrack.h2
-rw-r--r--lib/qm-dsp/ext/kissfft/CHANGELOG4
-rw-r--r--lib/qm-dsp/ext/kissfft/kiss_fft.c2
-rw-r--r--lib/reverb/Reverb.cc312
-rw-r--r--lib/reverb/Reverb.h132
-rw-r--r--lib/reverb/basics.h54
-rw-r--r--lib/reverb/dsp/IIR1.h (renamed from lib/reverb/dsp/OnePole.h)48
-rw-r--r--lib/reverb/dsp/Sine.h39
-rw-r--r--lib/soundtouch-1.9.2/BPMDetect.cpp371
-rw-r--r--lib/soundtouch-1.9.2/BPMDetect.h164
-rw-r--r--lib/soundtouch-1.9.2/soundtouch_config.h15
-rw-r--r--lib/soundtouch-2.1.0.tar.bz2bin0 -> 459394 bytes
-rw-r--r--lib/soundtouch/AAFilter.cpp (renamed from lib/soundtouch-1.9.2/AAFilter.cpp)16
-rw-r--r--lib/soundtouch/AAFilter.h (renamed from lib/soundtouch-1.9.2/AAFilter.h)7
-rw-r--r--lib/soundtouch/BPMDetect.cpp572
-rw-r--r--lib/soundtouch/BPMDetect.h205
-rw-r--r--lib/soundtouch/COPYING.TXT (renamed from lib/soundtouch-1.9.2/COPYING.TXT)2
-rw-r--r--lib/soundtouch/FIFOSampleBuffer.cpp (renamed from lib/soundtouch-1.9.2/FIFOSampleBuffer.cpp)15
-rw-r--r--lib/soundtouch/FIFOSampleBuffer.h (renamed from lib/soundtouch-1.9.2/FIFOSampleBuffer.h)9
-rw-r--r--lib/soundtouch/FIFOSamplePipe.h (renamed from lib/soundtouch-1.9.2/FIFOSamplePipe.h)28
-rw-r--r--lib/soundtouch/FIRFilter.cpp (renamed from lib/soundtouch-1.9.2/FIRFilter.cpp)20
-rw-r--r--lib/soundtouch/FIRFilter.h (renamed from lib/soundtouch-1.9.2/FIRFilter.h)7
-rw-r--r--lib/soundtouch/InterpolateCubic.cpp (renamed from lib/soundtouch-1.9.2/InterpolateCubic.cpp)4
-rw-r--r--lib/soundtouch/InterpolateCubic.h (renamed from lib/soundtouch-1.9.2/InterpolateCubic.h)4
-rw-r--r--lib/soundtouch/InterpolateLinear.cpp (renamed from lib/soundtouch-1.9.2/InterpolateLinear.cpp)4
-rw-r--r--lib/soundtouch/InterpolateLinear.h (renamed from lib/soundtouch-1.9.2/InterpolateLinear.h)8
-rw-r--r--lib/soundtouch/InterpolateShannon.cpp (renamed from lib/soundtouch-1.9.2/InterpolateShannon.cpp)4
-rw-r--r--lib/soundtouch/InterpolateShannon.h (renamed from lib/soundtouch-1.9.2/InterpolateShannon.h)4
-rw-r--r--lib/soundtouch/PeakFinder.cpp (renamed from lib/soundtouch-1.9.2/PeakFinder.cpp)17
-rw-r--r--lib/soundtouch/PeakFinder.h (renamed from lib/soundtouch-1.9.2/PeakFinder.h)11
-rw-r--r--lib/soundtouch/README.html914
-rw-r--r--lib/soundtouch/RateTransposer.cpp (renamed from lib/soundtouch-1.9.2/RateTransposer.cpp)35
-rw-r--r--lib/soundtouch/RateTransposer.h (renamed from lib/soundtouch-1.9.2/RateTransposer.h)22
-rw-r--r--lib/soundtouch/STTypes.h (renamed from lib/soundtouch-1.9.2/STTypes.h)16
-rw-r--r--lib/soundtouch/SoundTouch.cpp (renamed from lib/soundtouch-1.9.2/SoundTouch.cpp)154
-rw-r--r--lib/soundtouch/SoundTouch.h (renamed from lib/soundtouch-1.9.2/SoundTouch.h)91
-rw-r--r--lib/soundtouch/TDStretch.cpp (renamed from lib/soundtouch-1.9.2/TDStretch.cpp)131
-rw-r--r--lib/soundtouch/TDStretch.h (renamed from lib/soundtouch-1.9.2/TDStretch.h)16
-rw-r--r--lib/soundtouch/cpu_detect.h (renamed from lib/soundtouch-1.9.2/cpu_detect.h)7
-rw-r--r--lib/soundtouch/cpu_detect_x86.cpp (renamed from lib/soundtouch-1.9.2/cpu_detect_x86.cpp)8
-rw-r--r--lib/soundtouch/mmx_optimized.cpp (renamed from lib/soundtouch-1.9.2/mmx_optimized.cpp)21
-rw-r--r--lib/soundtouch/readme.md50
-rw-r--r--lib/soundtouch/soundtouch_config.h3
-rw-r--r--lib/soundtouch/sse_optimized.cpp (renamed from lib/soundtouch-1.9.2/sse_optimized.cpp)7
-rw-r--r--lib/xwax/lut_win32.cpp2
76 files changed, 4200 insertions, 1875 deletions
diff --git a/lib/fidlib/CHANGELOG b/lib/fidlib/CHANGELOG
new file mode 100644
index 0000000000..831de46ee3
--- /dev/null
+++ b/lib/fidlib/CHANGELOG
@@ -0,0 +1,7 @@
+*************************************************************
+*** This is a forked and patched version of Fidlib 0.9.10 ***
+*************************************************************
+
+* Thu Apr 19 2018 Uwe Klotz <uklotz@mixxx.org>
+- Thread-safe invocation of code for generating filters
+- Fix compiler warnings
diff --git a/lib/fidlib-0.9.10/COPYING b/lib/fidlib/COPYING
index d60c31a97a..d60c31a97a 100644
--- a/lib/fidlib-0.9.10/COPYING
+++ b/lib/fidlib/COPYING
diff --git a/lib/fidlib-0.9.10/COPYING_LIB b/lib/fidlib/COPYING_LIB
index b1e3f5a263..b1e3f5a263 100644
--- a/lib/fidlib-0.9.10/COPYING_LIB
+++ b/lib/fidlib/COPYING_LIB
diff --git a/lib/fidlib-0.9.10/fidlib.c b/lib/fidlib/fidlib.c
index 619325287c..8dcef23b01 100644
--- a/lib/fidlib-0.9.10/fidlib.c
+++ b/lib/fidlib/fidlib.c
@@ -23,7 +23,7 @@
//
// Robert Bristow-Johnson's EQ cookbook formulae:
// http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
-//
+//
#define VERSION "0.9.10"
@@ -35,7 +35,7 @@
// specify the filter, or it can be used with the frequency or
// frequency range missing, in which case default values are
// picked up from values passed directly to the routine.
-//
+//
// The spec consists of a series of letters usually followed by
// the order of the filter and then by any other parameters
// required, preceded by slashes. For example:
@@ -69,15 +69,15 @@
// okay= fid_list_filters_buf(buf, buf+sizeof(buf));
//
// // Calculate the response of the filter at a given frequency
-// // (frequency is given as a proportion of the sampling rate, in
-// // the range 0 to 0.5). If phase is returned, then this is
+// // (frequency is given as a proportion of the sampling rate, in
+// // the range 0 to 0.5). If phase is returned, then this is
// // given in the range 0 to 1 (for 0 to 2*pi).
// resp= fid_response(filt, freq);
// resp= fid_response_pha(filt, freq, &phase);
//
// // Estimate the signal delay caused by a particular filter, in samples
// delay= fid_calc_delay(filt);
-//
+//
// // Run a given filter (this will do JIT filter compilation if this is
// // implemented for this processor / OS)
// run= fid_run_new(filt, &funcp);
@@ -93,7 +93,7 @@
// fid_run_freebuf(fbuf1);
// fid_run_free(run);
//
-// // If you need to allocate your own buffers separately for some
+// // If you need to allocate your own buffers separately for some
// // reason, then do it this way:
// run= fid_run_new(filt, &funcp);
// len= fid_run_bufsize(run);
@@ -109,30 +109,30 @@
// free(fbuf1);
// fid_run_free(run);
//
-// // Convert an arbitrary filter into a new filter which is a single
-// // IIR/FIR pair. This is done by convolving the coefficients. This
-// // flattened filter will give the same result, in theory. However,
-// // in practice this will be less accurate, especially in cases where
-// // the limits of the floating point format are being reached (e.g.
+// // Convert an arbitrary filter into a new filter which is a single
+// // IIR/FIR pair. This is done by convolving the coefficients. This
+// // flattened filter will give the same result, in theory. However,
+// // in practice this will be less accurate, especially in cases where
+// // the limits of the floating point format are being reached (e.g.
// // subtracting numbers with small highly significant differences).
// // The routine also ensures that the IIR first coefficient is 1.0.
// filt2= fid_flatten(filt);
// free(filt);
//
// // Parse an entire filter-spec string possibly containing several FIR,
-// // IIR and predefined filters and return it as a FidFilter at the given
+// // IIR and predefined filters and return it as a FidFilter at the given
// // location. Stops at the first ,; or unmatched )]} character, or the end
// // of the string. Returns a strdup'd error string on error, or else 0.
// err= fid_parse(double rate, char **pp, FidFilter **ffp);
//
-// // Set up your own fatal-error handler (default is to dump a message
+// // Set up your own fatal-error handler (default is to dump a message
// // to STDERR and exit on fatal conditions)
// fid_set_error_handler(&my_error_func);
//
// // Get the version number of the library as a string (e.g. "1.0.0")
// txt= fid_version();
//
-// // Design a filter and reduce it to a list of all the non-const
+// // Design a filter and reduce it to a list of all the non-const
// // coefficients, which is returned in the given double[]. The number
// // of coefficients expected must be provided (as a check).
// #define N_COEF <whatever>
@@ -148,11 +148,11 @@
// free(full); free(min);
//
// // Create a FidFilter based on coefficients provided in the
-// // given double array.
+// // given double array.
// static double array[]= { 'I', 3, 1.0, 0.55, 0.77, 'F', 3, 1, -2, 1, 0 };
// filt= fid_cv_array(array);
//
-// // Join a number of filters into a single filter (and free them too,
+// // Join a number of filters into a single filter (and free them too,
// // if the first argument is 1)
// filt= fid_cat(0, filt1, filt2, filt3, filt4, 0);
//
@@ -172,15 +172,15 @@
// elements, or whatever). This is followed by a short bitmap
// which indicates which of the coefficients are constants,
// aiding code-generation. Next comes the count of the following
-// coefficients, as an int. (These header fields normally takes 8
-// bytes, the same as a double, but this might depend on the
-// platform). Then follow the coefficients, as doubles. The next
-// sub-filter follows on straight after that. The end of the list
+// coefficients, as an int. (These header fields normally takes 8
+// bytes, the same as a double, but this might depend on the
+// platform). Then follow the coefficients, as doubles. The next
+// sub-filter follows on straight after that. The end of the list
// is marked by 8 zero bytes, meaning typ==0, cbm==0 and len==0.
//
// The filter can be read with the aid of the FidFilter structure
-// (giving typ, cbm, len and val[] elements) and the FFNEXT()
-// macro: using ff= FFNEXT(ff) steps to the next FidFilter
+// (giving typ, cbm, len and val[] elements) and the FFNEXT()
+// macro: using ff= FFNEXT(ff) steps to the next FidFilter
// structure along the chain.
//
// Note that within the sub-filters, coefficients are listed in
@@ -263,7 +263,7 @@ extern FidFilter *mkfilter(char *, ...);
#if defined(T_MINGW) || defined(T_MSVC)
#define STATIC_INLINE static __inline
#else
- #define STATIC_INLINE static inline
+ #define STATIC_INLINE static inline
#endif
// MinGW and MSVC fixes
@@ -275,7 +275,7 @@ extern FidFilter *mkfilter(char *, ...);
#define snprintf _snprintf
#endif
// Not sure if we strictly need this still
- STATIC_INLINE double
+ STATIC_INLINE double
my_asinh(double val) {
return log(val + sqrt(val*val + 1.0));
}
@@ -289,7 +289,7 @@ extern FidFilter *mkfilter(char *, ...);
static void (*error_handler)(char *err)= 0;
-static void
+static void
error(char *fmt, ...) {
char buf[1024];
va_list ap;
@@ -311,7 +311,7 @@ strdupf(char *fmt, ...) {
int len;
va_start(ap, fmt);
len= vsnprintf(buf, sizeof(buf), fmt, ap);
- if (len < 0 || len >= sizeof(buf)-1)
+ if (len < 0 || len >= (int)sizeof(buf)-1)
error("strdupf exceeded buffer");
rv= strdup(buf);
if (!rv) error("Out of memory");
@@ -367,7 +367,7 @@ cmulr(double *aa, double fact) {
// Complex conjugate: aa= aa*
//
-STATIC_INLINE void
+STATIC_INLINE void
cconj(double *aa) {
aa[1]= -aa[1];
}
@@ -389,18 +389,18 @@ cdiv(double *aa, double *bb) {
// Complex reciprocal: aa= 1/aa
//
-STATIC_INLINE void
+STATIC_INLINE void
crecip(double *aa) {
double fact= 1.0 / (aa[0] * aa[0] + aa[1] * aa[1]);
aa[0] *= fact;
aa[1] *= -fact;
-}
-
+}
+
//
// Complex assign: aa= bb
//
-STATIC_INLINE void
+STATIC_INLINE void
cass(double *aa, double *bb) {
memcpy(aa, bb, 2*sizeof(double)); // Assigning doubles is really slow
}
@@ -409,7 +409,7 @@ cass(double *aa, double *bb) {
// Complex assign: aa= (rr + ii*j)
//
-STATIC_INLINE void
+STATIC_INLINE void
cassz(double *aa, double rr, double ii) {
aa[0]= rr;
aa[1]= ii;
@@ -419,7 +419,7 @@ cassz(double *aa, double rr, double ii) {
// Complex add: aa += bb
//
-STATIC_INLINE void
+STATIC_INLINE void
cadd(double *aa, double *bb) {
aa[0] += bb[0];
aa[1] += bb[1];
@@ -429,7 +429,7 @@ cadd(double *aa, double *bb) {
// Complex add: aa += (rr + ii*j)
//
-STATIC_INLINE void
+STATIC_INLINE void
caddz(double *aa, double rr, double ii) {
aa[0] += rr;
aa[1] += ii;
@@ -439,7 +439,7 @@ caddz(double *aa, double rr, double ii) {
// Complex subtract: aa -= bb
//
-STATIC_INLINE void
+STATIC_INLINE void
csub(double *aa, double *bb) {
aa[0] -= bb[0];
aa[1] -= bb[1];
@@ -449,7 +449,7 @@ csub(double *aa, double *bb) {
// Complex subtract: aa -= (rr + ii*j)
//
-STATIC_INLINE void
+STATIC_INLINE void
csubz(double *aa, double rr, double ii) {
aa[0] -= rr;
aa[1] -= ii;
@@ -459,7 +459,7 @@ csubz(double *aa, double rr, double ii) {
// Complex negate: aa= -aa
//
-STATIC_INLINE void
+STATIC_INLINE void
cneg(double *aa) {
aa[0]= -aa[0];
aa[1]= -aa[1];
@@ -503,7 +503,7 @@ evaluate(double *rv, double *coef, int n_coef, double *in) {
// Housekeeping
//
-void
+void
fid_set_error_handler(void (*rout)(char*)) {
error_handler= rout;
}
@@ -521,7 +521,7 @@ fid_version() {
// phase between 0 and two-pi.
//
-double
+double
fid_response_pha(FidFilter *filt, double freq, double *phase) {
double top[2], bot[2];
double theta= freq * 2 * M_PI;
@@ -533,16 +533,16 @@ fid_response_pha(FidFilter *filt, double freq, double *phase) {
bot[1]= 0;
zz[0]= cos(theta);
zz[1]= sin(theta);
-
+
while (filt->len) {
double resp[2];
int cnt= filt->len;
evaluate(resp, filt->val, cnt, zz);
if (filt->typ == 'I')
- cmul(bot, resp);
+ cmul(bot, resp);
else if (filt->typ == 'F')
cmul(top, resp);
- else
+ else
error("Unknown filter type %d in fid_response_pha()", filt->typ);
filt= FFNEXT(filt);
}
@@ -567,7 +567,7 @@ fid_response_pha(FidFilter *filt, double freq, double *phase) {
// can be inlined.
//
-double
+double
fid_response(FidFilter *filt, double freq) {
double top[2], bot[2];
double theta= freq * 2 * M_PI;
@@ -579,16 +579,16 @@ fid_response(FidFilter *filt, double freq) {
bot[1]= 0;
zz[0]= cos(theta);
zz[1]= sin(theta);
-
+
while (filt->len) {
double resp[2];
int cnt= filt->len;
evaluate(resp, filt->val, cnt, zz);
if (filt->typ == 'I')
- cmul(bot, resp);
+ cmul(bot, resp);
else if (filt->typ == 'F')
cmul(top, resp);
- else
+ else
error("Unknown filter type %d in fid_response()", filt->typ);
filt= FFNEXT(filt);
}
@@ -605,13 +605,13 @@ fid_response(FidFilter *filt, double freq) {
// are complete. This involves running test impulses through the
// filter several times. The estimated delay in samples is
// returned.
-//
+//
// Delays longer than 8,000,000 samples are not handled well, as
// the code drops out at this point rather than get stuck in an
// endless loop.
//
-int
+int
fid_calc_delay(FidFilter *filt) {
FidRun *run;
FidFunc *dostep;
@@ -626,20 +626,20 @@ fid_calc_delay(FidFilter *filt) {
// a reference point much further ahead in the impulse response.
f1= fid_run_newbuf(run);
f2= fid_run_newbuf(run);
-
+
tot= fabs(dostep(f1, 1.0));
tot100= fabs(dostep(f2, 1.0));
tot100 += fabs(dostep(f2, 0.0));
tot100 += fabs(dostep(f2, 0.0));
tot100 += fabs(dostep(f2, 0.0));
-
+
for (cnt= 1; cnt < 0x1000000; cnt++) {
tot += fabs(dostep(f1, 0.0));
tot100 += fabs(dostep(f2, 0.0));
tot100 += fabs(dostep(f2, 0.0));
tot100 += fabs(dostep(f2, 0.0));
tot100 += fabs(dostep(f2, 0.0));
-
+
if (tot/tot100 >= 0.999) break;
}
fid_run_freebuf(f1);
@@ -649,7 +649,7 @@ fid_calc_delay(FidFilter *filt) {
tot50= tot100/2;
f1= fid_run_newbuf(run);
tot= fabs(dostep(f1, 1.0));
- for (cnt= 0; tot < tot50; cnt++)
+ for (cnt= 0; tot < tot50; cnt++)
tot += fabs(dostep(f1, 0.0));
fid_run_freebuf(f1);
@@ -657,7 +657,7 @@ fid_calc_delay(FidFilter *filt) {
fid_run_free(run);
return cnt;
}
-
+
//
// 'mkfilter'-derived code
@@ -679,7 +679,7 @@ stack_filter(int order, int n_head, int n_val, ...) {
int a, b, len;
if (order == 0) return rv;
-
+
// Copy from ap
va_start(ap, n_val);
p= q= rv;
@@ -687,7 +687,7 @@ stack_filter(int order, int n_head, int n_val, ...) {
p->typ= va_arg(ap, int);
p->cbm= va_arg(ap, int);
p->len= va_arg(ap, int);
- for (b= 0; b<p->len; b++)
+ for (b= 0; b<p->len; b++)
p->val[b]= va_arg(ap, double);
p= FFNEXT(p);
}
@@ -695,16 +695,16 @@ stack_filter(int order, int n_head, int n_val, ...) {
// Check length
len= ((char*)p)-((char*)q);
- if (len != FFCSIZE(n_head-1, n_val))
+ if (len != (int)FFCSIZE(n_head-1, n_val))
error("Internal error; bad call to stack_filter(); length mismatch (%d,%d)",
len, FFCSIZE(n_head-1, n_val));
-
+
// Make as many additional copies as necessary
while (order-- > 0) {
memcpy(p, q, len);
p= (FidFilter*)(len + (char*)p);
}
-
+