[SCM] calf/master: + Only builds LADSPA and/or JACK versions when prerequisites are met+other configure fixes (unfortunately, still uses -O2) + Better GUI in JACK version + Command-line handling fixes (copy-pasting too fast!) + First attempt at benchmarking framework, more will follow! + Fixed bugs in direct II form of biquad filters

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:36:42 UTC 2013


The following commit has been merged in the master branch:
commit e12a572cac768608787ccb8e82184c7f68858dc1
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date:   Sun Dec 2 22:18:37 2007 +0000

    + Only builds LADSPA and/or JACK versions when prerequisites are met+other configure fixes (unfortunately, still uses -O2)
    + Better GUI in JACK version
    + Command-line handling fixes (copy-pasting too fast!)
    + First attempt at benchmarking framework, more will follow!
    + Fixed bugs in direct II form of biquad filters
    
    
    
    git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@5 78b06b96-2940-0410-b7fc-879d825d01d8

diff --git a/config.h.in b/config.h.in
index 5e08aed..6f38196 100644
--- a/config.h.in
+++ b/config.h.in
@@ -9,18 +9,21 @@
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have the <jack/jack.h> header file. */
+#undef HAVE_JACK_JACK_H
+
 /* Define to 1 if you have the <ladspa.h> header file. */
 #undef HAVE_LADSPA_H
 
-/* Define to 1 if you have the `jack' library (-ljack). */
-#undef HAVE_LIBJACK
-
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
 /* Define to 1 if you have the `memset' function. */
 #undef HAVE_MEMSET
 
+/* Define to 1 if you have the <phat/phatknob.h> header file. */
+#undef HAVE_PHAT_PHATKNOB_H
+
 /* Define to 1 if you have the `pow' function. */
 #undef HAVE_POW
 
@@ -45,6 +48,9 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
diff --git a/configure.in b/configure.in
index f65ab9b..59fa169 100644
--- a/configure.in
+++ b/configure.in
@@ -2,32 +2,64 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT([calf],[0.0.4],[wdev at foltman.com])
+AC_INIT([calf],[0.0.5],[wdev at foltman.com])
 AC_CONFIG_SRCDIR([config.h.in])
 AC_CONFIG_HEADER([config.h])
 
-AM_INIT_AUTOMAKE([std-options])
+AM_INIT_AUTOMAKE(1.8)
+
+if test "x$prefix" = "xNONE"; then 
+  prefix=$ac_default_prefix
+fi
 
 # Checks for programs.
 AC_PROG_CXX
 AC_PROG_CC
+AC_PROG_CPP
 AC_PROG_INSTALL
 AC_PROG_LIBTOOL
 
 # Checks for libraries.
 PKG_PROG_PKG_CONFIG
-PKG_CHECK_MODULES(GUI_DEPS, glib-2.0 >= 2.10.0 gtk+-2.0 >= 2.12.0 phat >= 0.4.1 jack >= 0.103.0)
-AC_CHECK_LIB([jack], [jack_port_new])
 
-CXXFLAGS="$CXXFLAGS -ffast-math $GUI_DEPS_CFLAGS"
-LDFLAGS="$LDFLAGS $GUI_DEPS_LIBS"
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([memory.h stdint.h stdlib.h ladspa.h time.h])
+
+AC_CHECK_HEADER(ladspa.h, LADSPA_FOUND="yes", LADSPA_FOUND="no")
+
+AC_CHECK_HEADERS([jack/jack.h], have_jack_header=yes, have_jack_header=no)
+
+if test "$have_jack_header" = "yes"; then
+  PKG_CHECK_MODULES(JACK_DEPS, jack >= 0.103.0,
+    AC_CHECK_LIB([jack], [jack_port_new], JACK_FOUND="yes", JACK_FOUND="no"),
+    JACK_FOUND="no")
+else
+  JACK_FOUND="no"
+fi
 
 AC_SUBST(GUI_DEPS_CFLAGS)
 AC_SUBST(GUI_DEPS_LIBS)
+AC_SUBST(JACK_DEPS_CFLAGS)
+AC_SUBST(JACK_DEPS_LIBS)
 
-# Checks for header files.
-AC_HEADER_STDC
-AC_CHECK_HEADERS([memory.h stdint.h stdlib.h ladspa.h])
+if test "$JACK_FOUND" = "yes"; then
+  PKG_CHECK_MODULES(GUI_DEPS, gtk+-2.0 >= 2.4.0 phat >= 0.4.1, 
+    [
+      CFLAGS="$CFLAGS $GUI_DEPS_CFLAGS $JACK_DEPS_CFLAGS"
+      CPPFLAGS="$CPPFLAGS $GUI_DEPS_CFLAGS $JACK_DEPS_CFLAGS"
+      AC_CHECK_HEADERS([phat/phatknob.h], 
+        JACK_ENABLED="yes", 
+        JACK_ENABLED="no (phat library is too old, SVN version required)")
+    ],
+    JACK_ENABLED="no (GTK+ or phat is missing or too old)"
+  )
+else
+  JACK_ENABLED="no"
+fi
+
+AM_CONDITIONAL(USE_LADSPA, test "$LADSPA_FOUND" = "yes")
+AM_CONDITIONAL(USE_JACK, test "$JACK_ENABLED" = "yes")
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_HEADER_STDBOOL
@@ -64,4 +96,12 @@ AC_CHECK_FUNCS([floor memset pow])
 AC_CONFIG_FILES([Makefile
                  src/Makefile
                  src/calf/Makefile])
+AC_MSG_RESULT([
+    Calf configured
+
+    LADSPA enabled:         $LADSPA_FOUND
+    JACK host enabled:      $JACK_ENABLED
+    
+    Installation prefix:    $prefix
+])
 AC_OUTPUT
diff --git a/src/Makefile.am b/src/Makefile.am
index f5bfc19..a298e41 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,15 +6,29 @@ SUBDIRS = calf
 
 ladspadir = $(with_ladspa_dir)
 
-bin_PROGRAMS = calfjackhost calfmakerdf
+bin_PROGRAMS = 
 
+noinst_PROGRAMS = calfbenchmark
+noinst_LTLIBRARIES = libcalf.la libcalfstatic.la
+
+AM_CXXFLAGS = -O3 -ffast-math -march=pentium4 -finline-limit=8
+
+if USE_JACK
+AM_CXXFLAGS += -DUSE_JACK=1
+bin_PROGRAMS += calfjackhost 
 calfjackhost_SOURCES = jackhost.cpp
-calfjackhost_LDADD = libcalfstatic.la
+calfjackhost_LDADD = libcalfstatic.la $(JACK_DEPS_LIBS) $(GUI_DEPS_LIBS)
+endif
 
+if USE_LADSPA
+AM_CXXFLAGS += -DUSE_LADSPA=1
+bin_PROGRAMS += calfmakerdf
 calfmakerdf_SOURCES = makerdf.cpp
 calfmakerdf_LDADD = libcalfstatic.la
+endif
 
-noinst_LTLIBRARIES = libcalf.la libcalfstatic.la
+calfbenchmark_SOURCES = benchmark.cpp
+calfbenchmark_LDADD = 
 
 libcalf_la_SOURCES = modules.cpp giface.cpp
 libcalf_la_LDFLAGS = -rpath $(ladspadir) -version-info 0:0:0
@@ -26,16 +40,20 @@ clean-local:
 	$(RM) -f calfjackhost *~
 
 install-data-hook:
+if USE_LADSPA
 	install -d -m 755 $(DESTDIR)$(with_ladspa_dir)
 	install -d -m 755 $(DESTDIR)$(with_ladspa_rdf_dir)
 	install -c -m 755 $(top_builddir)/src/.libs/libcalf.so.0.0.0 $(DESTDIR)$(with_ladspa_dir)/calf.so
 	$(DESTDIR)$(bindir)/calfmakerdf > $(DESTDIR)$(with_ladspa_rdf_dir)/calf.rdf
+endif
 
 #remove calf.so, calf.rdf and - if empty - ladspa dir in usr/share
 uninstall-hook:
+if USE_LADSPA
 	$(RM) -f $(DESTDIR)$(with_ladspa_dir)/calf.so
 	$(RM) -f $(DESTDIR)$(with_ladspa_rdf_dir)/calf.rdf
 	rmdir $(DESTDIR)$(with_ladspa_rdf_dir)
+endif
 
 #install:
 #	$(INSTALL) calfjackhost $(bindir)
diff --git a/src/benchmark.cpp b/src/benchmark.cpp
new file mode 100644
index 0000000..071f5c9
--- /dev/null
+++ b/src/benchmark.cpp
@@ -0,0 +1,189 @@
+#include <getopt.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <config.h>
+#include <calf/giface.h>
+#include <calf/modules.h>
+#include <calf/benchmark.h>
+
+using namespace std;
+using namespace dsp;
+
+template<int BUF_SIZE>
+struct empty_benchmark
+{
+    void prepare()
+    {
+    }
+    void cleanup()
+    {
+    }
+    double scaler() { return BUF_SIZE; }
+};
+
+struct filter_lp24dB_benchmark
+{
+    enum { BUF_SIZE = 256 };
+    float buffer[BUF_SIZE];
+    float result;
+    dsp::biquad<float> biquad, biquad2;
+    void prepare()
+    {
+        for (int i = 0; i < BUF_SIZE; i++)
+            buffer[i] = i;
+        biquad.set_lp_rbj(2000, 0.7, 44100);
+        biquad2.set_lp_rbj(2000, 0.7, 44100);
+        result = 0;
+    }
+    void cleanup() { result = buffer[BUF_SIZE - 1]; }
+    double scaler() { return BUF_SIZE; }
+};
+
+struct filter_24dB_lp_twopass_d1: public filter_lp24dB_benchmark
+{
+    void run()
+    {
+        for (int i = 0; i < BUF_SIZE; i++)
+            buffer[i] = biquad.process_d1(buffer[i]);
+        for (int i = 0; i < BUF_SIZE; i++)
+            buffer[i] = biquad2.process_d1(buffer[i]);
+    }
+};
+
+struct filter_24dB_lp_onepass_d1: public filter_lp24dB_benchmark
+{
+    void run()
+    {
+        for (int i = 0; i < BUF_SIZE; i++)
+            buffer[i] = biquad2.process_d1(biquad.process_d2(buffer[i]));
+    }
+};
+
+struct filter_12dB_lp_d1: public filter_lp24dB_benchmark
+{
+    void run()
+    {
+        for (int i = 0; i < BUF_SIZE; i++)
+            buffer[i] = biquad.process_d1(buffer[i]);
+    }
+};
+
+struct filter_24dB_lp_twopass_d2: public filter_lp24dB_benchmark
+{
+    void run()
+    {
+        for (int i = 0; i < BUF_SIZE; i++)
+            buffer[i] = biquad.process_d1(buffer[i]);
+        for (int i = 0; i < BUF_SIZE; i++)
+            buffer[i] = biquad2.process_d1(buffer[i]);
+    }
+};
+
+struct filter_24dB_lp_onepass_d2: public filter_lp24dB_benchmark
+{
+    void run()
+    {
+        for (int i = 0; i < BUF_SIZE; i++)
+            buffer[i] = biquad2.process_d2(biquad.process_d2(buffer[i]));
+    }
+};
+
+struct filter_12dB_lp_d2: public filter_lp24dB_benchmark
+{
+    void run()
+    {
+        for (int i = 0; i < BUF_SIZE; i++)
+            buffer[i] = biquad.process_d2(buffer[i]);
+    }
+};
+
+#define ALIGN_TEST_RUN 1024
+
+struct __attribute__((aligned(8))) alignment_test: public empty_benchmark<ALIGN_TEST_RUN>
+{
+    char __attribute__((aligned(8))) data[ALIGN_TEST_RUN * sizeof(double) + sizeof(double)];
+    float result;
+
+    virtual double *get_ptr()=0;
+    void prepare()
+    {
+        memset(data, 0, sizeof(data));
+        result = 0;
+    }
+    void cleanup()
+    {
+        result = 0;
+        double *p = get_ptr();
+        for (int i=0; i < ALIGN_TEST_RUN; i++)
+            result += p[i];
+    }
+};
+
+struct aligned_double: public alignment_test
+{    
+    virtual double *get_ptr() { return (double *)data; }
+    void run()
+    {
+        double *ptr = (double *)data;
+        for (int i=0; i < ALIGN_TEST_RUN; i++)
+            ptr[i] += 1 + i;
+    }
+};
+
+struct __attribute__((aligned(8))) misaligned_double: public alignment_test
+{
+    virtual double *get_ptr() { return (double *)(data+4); }
+    void run()
+    {
+        double *ptr = (double *)(data + 4);
+        for (int i=0; i < ALIGN_TEST_RUN; i++)
+            ptr[i] += 1 + i;
+    }
+};
+
+const char *unit = NULL;
+
+static struct option long_options[] = {
+    {"help", 0, 0, 'h'},
+    {"version", 0, 0, 'v'},
+    {"unit", 1, 0, 'u'},
+    {0,0,0,0},
+};
+
+int main(int argc, char *argv[])
+{
+    while(1) {
+        int option_index;
+        int c = getopt_long(argc, argv, "u:hv", long_options, &option_index);
+        if (c == -1)
+            break;
+        switch(c) {
+            case 'h':
+            case '?':
+                printf("Benchmark suite Calf plugin pack\nSyntax: %s [--help] [--version] [--unit biquad|alignment]\n", argv[0]);
+                return 0;
+            case 'v':
+                printf("%s\n", PACKAGE_STRING);
+                return 0;
+            case 'u':
+                unit = optarg;
+                break;
+        }
+    }
+    
+    if (!unit || !strcmp(unit, "biquad")) {
+        do_simple_benchmark<filter_24dB_lp_twopass_d1>();
+        do_simple_benchmark<filter_24dB_lp_onepass_d1>();
+        do_simple_benchmark<filter_12dB_lp_d1>();
+        do_simple_benchmark<filter_24dB_lp_twopass_d2>();
+        do_simple_benchmark<filter_24dB_lp_onepass_d2>();
+        do_simple_benchmark<filter_12dB_lp_d2>();
+    }
+    
+    if (!unit || !strcmp(unit, "alignment")) {
+        do_simple_benchmark<misaligned_double>();
+        do_simple_benchmark<aligned_double>();
+    }
+
+    return 0;
+}
diff --git a/src/calf/Makefile.am b/src/calf/Makefile.am
index 2508e0f..68ef4b6 100644
--- a/src/calf/Makefile.am
+++ b/src/calf/Makefile.am
@@ -1,3 +1,3 @@
 calfdir = $(includedir)/calf
 
-calf_HEADERS = audio_fx.h biquad.h buffer.h delay.h fixed_point.h giface.h inertia.h modules.h onepole.h primitives.h wave.h
+calf_HEADERS = audio_fx.h benchmark.h biquad.h buffer.h delay.h fixed_point.h giface.h inertia.h modules.h onepole.h primitives.h wave.h
diff --git a/src/calf/benchmark.h b/src/calf/benchmark.h
new file mode 100644
index 0000000..e6835d1
--- /dev/null
+++ b/src/calf/benchmark.h
@@ -0,0 +1,156 @@
+/* Calf DSP Library
+ * Reusable performance measurement classes.
+ *
+ * Copyright (C) 2007 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __CALF_BENCHMARK_H
+#define __CALF_BENCHMAR_H
+
+#include <time.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include "primitives.h"
+#include <algorithm>
+#include <typeinfo>
+
+namespace dsp {
+#if 0
+}; to keep editor happy
+#endif
+
+
+class median_stat
+{
+public:
+    double *data;
+    unsigned int pos, count;
+    bool sorted;
+    
+    median_stat() {
+        data = NULL;
+        pos = 0;
+        count = 0;
+        sorted = false;
+    }
+    void start(int items) {
+        if (data)
+            delete []data;
+        data = new double[items];
+        pos = 0;
+        count = items;
+        sorted = false;
+    }
+    void add(double value)
+    {
+        assert(pos < count);
+        data[pos++] = value;
+    }
+    void end()
+    {
+        std::sort(&data[0], &data[count]);
+        sorted = true;
+    }
+    float get()
+    {
+        assert(sorted);
+        return data[count >> 1];
+    }
+};
+
+// USE_RDTSC is for testing on my own machine, a crappy 1.6GHz Pentium 4 - it gives less headaches than clock() based measurements
+#define USE_RDTSC 0
+#define CLOCK_SPEED (1.6 * 1000.0 * 1000.0 * 1000.0)
+
+#if USE_RDTSC
+inline uint64_t rdtsc()
+{
+    unsigned long long int x;
+    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
+    return x;
+}
+#endif
+
+template<typename Target, class Stat>
+class simple_benchmark
+{
+public:
+    Target target;
+    Stat &stat;
+
+    simple_benchmark(const Target &_target, Stat &_stat)
+    : target(_target)
+    , stat(_stat)
+    {
+    }
+    
+    int measure(int runs, int repeats)
+    {
+        int priority = getpriority(PRIO_PROCESS, getpid());
+        stat.start(runs);
+        if (setpriority(PRIO_PROCESS, getpid(), -20) < 0)
+            fprintf(stderr, "Warning: could not set process priority, measurements can be worthless\n");
+        for (int i = 0; i < runs; i++) {
+            target.prepare();
+            // XXXKF measuring CPU time with clock() sucks, 
+#if USE_RDTSC
+            uint64_t start = rdtsc();
+#else
+            clock_t start = ::clock();
+#endif
+            for (int j = 0; j < repeats; j++) {
+                target.run();
+            }
+#if USE_RDTSC
+            uint64_t end = rdtsc();
+            double elapsed = double(end - start) / (CLOCK_SPEED * repeats * target.scaler());
+#else
+            clock_t end = ::clock();
+            double elapsed = double(end - start) / (double(CLOCKS_PER_SEC) * repeats * target.scaler());
+#endif
+            stat.add(elapsed);
+            target.cleanup();
+            // printf("elapsed = %f start = %d end = %d diff = %d\n", elapsed, start, end, end - start);
+        }
+        setpriority(PRIO_PROCESS, getpid(), priority);
+        stat.end();
+    }
+    
+    float get_stat()
+    {
+        return stat.get();
+    }
+};
+
+template<class T>
+void do_simple_benchmark(int runs = 5, int repeats = 50000)
+{
+    dsp::median_stat stat;
+    dsp::simple_benchmark<T, dsp::median_stat> benchmark(T(), stat);
+    
+    benchmark.measure(runs, repeats);
+    
+    printf("%-30s: %f/sec, %f/CDsr, value = %f\n", typeid(T).name(), 1.0 / stat.get(), 1.0 / (44100 * stat.get()), benchmark.target.result);
+}
+
+
+#if 0
+{ to keep editor happy
+#endif
+}
+
+#endif
diff --git a/src/calf/biquad.h b/src/calf/biquad.h
index b597583..4c13e28 100644
--- a/src/calf/biquad.h
+++ b/src/calf/biquad.h
@@ -217,7 +217,7 @@ public:
     // direct II form with two state variables
     inline T process_d2(T in)
     {
-        T tmp = in - y1 * b1 - y2 * b2;
+        T tmp = in - w1 * b1 - w2 * b2;
         T out = tmp * a0 + w1 * a1 + w2 * a2;
         w2 = w1;
         w1 = tmp;
@@ -225,9 +225,10 @@ public:
     }
     
     // direct II form with two state variables, lowpass version
+    // interesting fact: this is actually slower than the general version!
     inline T process_d2_lp(T in)
     {
-        T tmp = in - y1 * b1 - y2 * b2;
+        T tmp = in - w1 * b1 - w2 * b2;
         T out = (tmp + w1 + w1 + w2) * a0;
         w2 = w1;
         w1 = tmp;
diff --git a/src/calf/giface.h b/src/calf/giface.h
index b88cc71..5a38774 100644
--- a/src/calf/giface.h
+++ b/src/calf/giface.h
@@ -23,8 +23,12 @@
 
 #include <stdint.h>
 #include <stdlib.h>
+#if USE_LADSPA
 #include <ladspa.h>
+#endif
+#if USE_JACK
 #include <jack/jack.h>
+#endif
 #include <exception>
 #include <string>
 
@@ -58,7 +62,7 @@ enum parameter_flags
   PF_CTLO_HORIZ = 0x010000,
   PF_CTLO_VERT = 0x020000,
   
-  PF_UNITS = 0xFF000000,
+  PF_UNITMASK = 0xFF000000,
   PF_UNIT_DB = 0x01000000,
   PF_UNIT_COEF = 0x02000000,
   PF_UNIT_HZ = 0x03000000,
@@ -68,11 +72,12 @@ enum parameter_flags
 
 struct parameter_properties
 {
-  float def_value, min, max, step;
-  uint32_t flags;
-  const char **choices;
-  float from_01(float value01);
-  float to_01(float value);
+    float def_value, min, max, step;
+    uint32_t flags;
+    const char **choices;
+    float from_01(float value01) const;
+    float to_01(float value) const;
+    std::string to_string(float value) const;
 };
 
 struct midi_event {
@@ -111,6 +116,8 @@ struct ladspa_info
     const char *plugin_type;
 };
 
+#if USE_LADSPA
+
 extern std::string generate_ladspa_rdf(const ladspa_info &info, parameter_properties *params, const char *param_names[], unsigned int count, unsigned int ctl_ofs);
 
 template<class Module>
@@ -242,6 +249,8 @@ struct ladspa_wrapper
     };
 };
 
+#endif
+
 struct audio_exception: public std::exception
 {
     const char *text;
@@ -253,6 +262,8 @@ public:
     virtual ~audio_exception() throw () {}
 };
 
+#if USE_JACK
+
 class jack_host_base {
 public:
     typedef int (*process_func)(jack_nframes_t nframes, void *p);
@@ -419,6 +430,8 @@ public:
     virtual parameter_properties* get_param_props() { return Module::param_props; }
 };
 
+#endif
+
 };
 
 #endif
diff --git a/src/giface.cpp b/src/giface.cpp
index e589356..3eddd2d 100644
--- a/src/giface.cpp
+++ b/src/giface.cpp
@@ -18,16 +18,16 @@
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+#include <config.h>
 #include <assert.h>
 #include <memory.h>
-#include <jack/jack.h>
 #include <calf/giface.h>
 #include <calf/modules.h>
 
 using namespace synth;
 using namespace std;
 
-float parameter_properties::from_01(float value01)
+float parameter_properties::from_01(float value01) const
 {
     switch(flags & PF_SCALEMASK)
     {
@@ -46,7 +46,7 @@ float parameter_properties::from_01(float value01)
     }
 }
 
-float parameter_properties::to_01(float value)
+float parameter_properties::to_01(float value) const
 {
     switch(flags & PF_SCALEMASK)
     {
@@ -67,11 +67,30 @@ float parameter_properties::to_01(float value)
     }
 }
 
+std::string parameter_properties::to_string(float value) const
+{
+    char buf[32];
+    if ((flags & PF_SCALEMASK) == PF_SCALE_PERC) {
+        sprintf(buf, "%g%%", 99.0 * value);
+        return string(buf);
+    }
+    sprintf(buf, "%g", value);
+    
+    switch(flags & PF_UNITMASK) {
+    case PF_UNIT_DB: return string(buf) + " dB";
+    case PF_UNIT_HZ: return string(buf) + " Hz";
+    case PF_UNIT_SEC: return string(buf) + " s";
+    case PF_UNIT_MSEC: return string(buf) + " ms";
+    }
+    return string(buf);
+}
+
 static std::string i2s(int value)
 {
     char buf[32];
     sprintf(buf, "%d", value);
-    return buf;
+    
+    return string(buf);
 }
 
 static string f2s(double value)
@@ -95,9 +114,11 @@ static string rdf_escape(const string &src)
     return dest;
 }
 
+#if USE_LADSPA
+
 static std::string unit_to_string(parameter_properties &props)
 {
-    uint32_t flags = props.flags & PF_UNITS;
+    uint32_t flags = props.flags & PF_UNITMASK;
     
     switch(flags) {
         case PF_UNIT_DB:
@@ -164,3 +185,5 @@ std::string synth::generate_ladspa_rdf(const ladspa_info &info, parameter_proper
     rdf += "  </ladspa:" + plugin_type + ">\n";
     return rdf;
 }
+
+#endif
diff --git a/src/jackhost.cpp b/src/jackhost.cpp
index fc48978..f6481f6 100644
--- a/src/jackhost.cpp
+++ b/src/jackhost.cpp
@@ -35,6 +35,7 @@ struct jack_host_param
 {
     jack_host_gui *gui;
     int param_no;
+    GtkWidget *label;
 };
 
 class jack_host_gui
@@ -48,7 +49,7 @@ public:
     jack_host_param *params;
 
     jack_host_gui(GtkWidget *_toplevel);
-    void create(synth::jack_host_base *_host);
+    void create(synth::jack_host_base *_host, const char *title);
     static void knob_value_changed(PhatKnob *widget, gpointer value);
     static void combo_value_changed(GtkComboBox *widget, gpointer value);
 };
@@ -63,11 +64,13 @@ void jack_host_gui::knob_value_changed(PhatKnob *widget, gpointer value)
 {
     jack_host_param *jhp = (jack_host_param *)value;
     jack_host_base &jh = *jhp->gui->host;
+    const parameter_properties &props = jh.get_param_props()[jhp->param_no];
     int nparam = jhp->param_no;
-    float cvalue = jh.get_param_props()[jhp->param_no].from_01 (phat_knob_get_value (widget));
+    float cvalue = props.from_01 (phat_knob_get_value (widget));
     jh.get_params()[nparam] = cvalue;
     // printf("%d -> %f\n", nparam, cvalue);
     jh.set_params();
+    gtk_label_set_text (GTK_LABEL (jhp->label), props.to_string(cvalue).c_str());
 }
 
 void jack_host_gui::combo_value_changed(GtkComboBox *widget, gpointer value)
@@ -79,7 +82,7 @@ void jack_host_gui::combo_value_changed(GtkComboBox *widget, gpointer value)
     jh.set_params();
 }
 
-void jack_host_gui::create(synth::jack_host_base *_host)
+void jack_host_gui::create(synth::jack_host_base *_host, const char *title)
 {
     host = _host;
     param_count = host->get_param_count();
@@ -90,11 +93,16 @@ void jack_host_gui::create(synth::jack_host_base *_host)
         params[i].param_no = i;
     }
 
-    table = gtk_table_new (param_count, 2, FALSE);
+    table = gtk_table_new (param_count + 1, 3, FALSE);
     
+    GtkWidget *title_label = gtk_label_new ("");
+    gtk_label_set_markup (GTK_LABEL (title_label), (string("<b>")+title+"</b>").c_str());
+    gtk_table_attach (GTK_TABLE (table), title_label, 0, 3, 0, 1, GTK_EXPAND, GTK_EXPAND, 2, 2);
+
     for (int i = 0; i < param_count; i++) {
         GtkWidget *label = gtk_label_new (host->get_param_names()[host->get_input_count() + host->get_output_count() + i]);
-        gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, i + 1, GTK_EXPAND, GTK_EXPAND, 2, 2);
+        gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+        gtk_table_attach (GTK_TABLE (table), label, 0, 1, i + 1, i + 2, GTK_FILL, GTK_EXPAND, 2, 2);
         
         parameter_properties &props = host->get_param_props()[i];
         
@@ -108,15 +116,25 @@ void jack_host_gui::create(synth::jack_host_base *_host)
                 gtk_combo_box_append_text (GTK_COMBO_BOX (widget), props.choices[j]);
             gtk_combo_box_set_active (GTK_COMBO_BOX (widget), (int)host->get_params()[i] - (int)props.min);
             gtk_signal_connect (GTK_OBJECT (widget), "changed", G_CALLBACK (combo_value_changed), (gpointer)&params[i]);
+            gtk_table_attach (GTK_TABLE (table), widget, 1, 3, i + 1, i + 2, GTK_EXPAND, GTK_EXPAND, 0, 0);
         }
         else
         {
-            widget  = phat_knob_new_with_range (host->get_param_props()[i].to_01 (host->get_params()[i]), 0, 1, 0.01);
-            gtk_signal_connect (GTK_OBJECT (widget), "value-changed", G_CALLBACK (knob_value_changed), (gpointer)&params[i]);
+            GtkWidget *knob = phat_knob_new_with_range (host->get_param_props()[i].to_01 (host->get_params()[i]), 0, 1, 0.01);
+            gtk_signal_connect (GTK_OBJECT (knob), "value-changed", G_CALLBACK (knob_value_changed), (gpointer)&params[i]);
+            gtk_table_attach (GTK_TABLE (table), knob, 1, 2, i + 1, i + 2, GTK_EXPAND, GTK_EXPAND, 0, 0);
+
+            widget  = gtk_label_new ("");
+            gtk_label_set_width_chars (GTK_LABEL (widget), 12);
+            gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+            gtk_table_attach (GTK_TABLE (table), widget, 2, 3, i + 1, i + 2, GTK_FILL, GTK_EXPAND, 0, 0);
+            params[i].label = widget;
+            // gtk_widget_set_size_request (widget, widget->allocation.width, widget->allocation.height);
+            // gtk_widget_set_size_request (widget, 100, 10);
+            
+            knob_value_changed (PHAT_KNOB (knob), (gpointer)&params[i]);
         }
-        gtk_table_attach (GTK_TABLE (table), widget, 1, 2, i, i + 1, GTK_EXPAND, GTK_EXPAND, 0, 0);
     }
-    
     gtk_container_add (GTK_CONTAINER (toplevel), table);
 }
 
@@ -130,12 +148,13 @@ void destroy(GtkWindow *window, gpointer data)
     gtk_main_quit();
 }
 
-void make_gui(jack_host_base *jh)
+void make_gui(jack_host_base *jh, const char *title, const char *effect)
 {
     GtkWidget *toplevel = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_title (GTK_WINDOW (toplevel), title);
         
     gui = new jack_host_gui(toplevel);
-    gui->create(jh);
+    gui->create(jh, effect);
 
     gtk_signal_connect (GTK_OBJECT(toplevel), "destroy", G_CALLBACK(destroy), NULL);
     gtk_widget_show_all(toplevel);
@@ -152,10 +171,10 @@ static struct option long_options[] = {
     {0,0,0,0},
 };
 
-char *effect_name = "flanger";
-char *client_name = "calfhost";
-char *input_name = "input";
-char *output_name = "output";
+const char *effect_name = "flanger";
+const char *client_name = "calfhost";
+const char *input_name = "input";
+const char *output_name = "output";
 
 int main(int argc, char *argv[])
 {
@@ -167,7 +186,10 @@ int main(int argc, char *argv[])
             break;
         switch(c) {
             case 'h':
-                printf("Syntax: %s [--effect reverb|flanger|filter] [--client <name>] [--input <name>] [--output <name>] [--help] [--version]\n", argv[0]);
+            case '?':
+                printf("JACK host for Calf effects\n"
+                    "Syntax: %s [--effect reverb|flanger|filter] [--client <name>] [--input <name>] [--output <name>] [--help] [--version]\n", 
+                    argv[0]);
                 return 0;
             case 'v':
                 printf("%s\n", PACKAGE_STRING);
@@ -199,7 +221,7 @@ int main(int argc, char *argv[])
             return 1;
         }
         jh->open(client_name, input_name, output_name);
-        make_gui(jh);
+        make_gui(jh, client_name, effect_name);
         gtk_main();
         delete gui;
         jh->close();
diff --git a/src/makerdf.cpp b/src/makerdf.cpp
index d01b6d3..729a622 100644
--- a/src/makerdf.cpp
+++ b/src/makerdf.cpp
@@ -2,7 +2,6 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <config.h>
-#include <jack/jack.h>
 #include <calf/giface.h>
 #include <calf/modules.h>
 
@@ -11,10 +10,6 @@ using namespace std;
 static struct option long_options[] = {
     {"help", 0, 0, 'h'},
     {"version", 0, 0, 'v'},
-    {"client", 1, 0, 'c'},
-    {"effect", 1, 0, 'e'},
-    {"input", 1, 0, 'i'},
-    {"output", 1, 0, 'o'},
     {0,0,0,0},
 };
 
@@ -22,11 +17,12 @@ int main(int argc, char *argv[])
 {
     while(1) {
         int option_index;
-        int c = getopt_long(argc, argv, "c:e:i:o:hv", long_options, &option_index);
+        int c = getopt_long(argc, argv, "hv", long_options, &option_index);
         if (c == -1)
             break;
         switch(c) {
             case 'h':
+            case '?':
                 printf("LADSPA RDF generator for Calf plugin pack\nSyntax: %s [--help] [--version]\n", argv[0]);
                 return 0;
             case 'v':
diff --git a/src/modules.cpp b/src/modules.cpp
index 7365502..bd55a3c 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -20,7 +20,9 @@
  */
 #include <assert.h>
 #include <memory.h>
+#if USE_JACK
 #include <jack/jack.h>
+#endif
 #include <calf/giface.h>
 #include <calf/modules.h>
 
@@ -36,11 +38,13 @@ parameter_properties amp_audio_module::param_props[] = {
 
 static synth::ladspa_info amp_info = { 0x847c, "Amp", "Calf Const Amp", "Krzysztof Foltman", copyright, "AmplifierPlugin" };
 
+#if USE_LADSPA
 synth::ladspa_wrapper<amp_audio_module> amp(amp_info);
+#endif
 
 ////////////////////////////////////////////////////////////////////////////
 
-const char *flanger_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Min. delay", "Mod. depth", "Mod. rate", "Feedback", "Amount"};
+const char *flanger_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Minimum delay", "Modulation depth", "Modulation rate", "Feedback", "Amount"};
 
 parameter_properties flanger_audio_module::param_props[] = {
     { 0.1,      0.1, 10, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL },
@@ -52,11 +56,13 @@ parameter_properties flanger_audio_module::param_props[] = {
 
 static synth::ladspa_info flanger_info = { 0x847d, "Flanger", "Calf Flanger", "Krzysztof Foltman", copyright, "FlangerPlugin" };
 
+#if USE_LADSPA
 synth::ladspa_wrapper<flanger_audio_module> flanger(flanger_info);
+#endif
 
 ////////////////////////////////////////////////////////////////////////////
 
-const char *reverb_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Dec. time", "HF Damp", "Amount"};
+const char *reverb_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Decay time", "HF Damp", "Amount"};
 
 parameter_properties reverb_audio_module::param_props[] = {
     { 1.5,      1.0,  4.0, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_SEC, NULL },
@@ -66,11 +72,13 @@ parameter_properties reverb_audio_module::param_props[] = {
 
 static synth::ladspa_info reverb_info = { 0x847e, "Reverb", "Calf Reverb", "Krzysztof Foltman", copyright, "ReverbPlugin" };
 
+#if USE_LADSPA
 synth::ladspa_wrapper<reverb_audio_module> reverb(reverb_info);
+#endif
 
 ////////////////////////////////////////////////////////////////////////////
 
-const char *filter_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Cutoff", "Resonance", "Mode", "Inertia"};
+const char *filter_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Frequency", "Resonance", "Mode", "Inertia"};
 
 const char *filter_choices[] = {
     "12dB/oct Lowpass",
@@ -83,17 +91,20 @@ const char *filter_choices[] = {
 
 parameter_properties filter_audio_module::param_props[] = {
     { 2000,      10,20000, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL },
-    { 0.707,  0.707,   20,  1.1, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL },
+    { 0.707,  0.707,   20,  1.1, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL },
     { 0,          0,    5,    1, PF_ENUM | PF_CTL_COMBO, filter_choices },
-    { 20,         5,  100,    1, PF_INT | PF_SCALE_LOG | PF_CTL_KNOB, NULL},
+    { 20,         5,  100,    1, PF_INT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL},
 };
 
 static synth::ladspa_info filter_info = { 0x847f, "Filter", "Calf Filter", "Krzysztof Foltman", copyright, "FilterPlugin" };
 
+#if USE_LADSPA
 synth::ladspa_wrapper<filter_audio_module> filter(filter_info);
+#endif
 
 ////////////////////////////////////////////////////////////////////////////
 
+#if USE_LADSPA
 extern "C" {
 
 const LADSPA_Descriptor *ladspa_descriptor(unsigned long Index)
@@ -118,3 +129,4 @@ std::string synth::get_builtin_modules_rdf()
     
     return rdf;
 }
+#endif

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list