Changeset 267

Show
Ignore:
Timestamp:
08/18/08 14:43:44 (4 years ago)
Author:
ath
Message:

Update the built-in copy of RubberBand? to 1.2 and fix the server accordingly.

Location:
trunk
Files:
6 added
4 removed
46 modified
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/fm_server/configure

    r257 r267  
    2526825268    else 
    2526925269        if test -n "$PKG_CONFIG" && \ 
    25270     { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"rubberband fftw3 samplerate\"") >&5 
    25271   ($PKG_CONFIG --exists --print-errors "rubberband fftw3 samplerate") 2>&5 
     25270    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"rubberband = 1.2 fftw3 samplerate\"") >&5 
     25271  ($PKG_CONFIG --exists --print-errors "rubberband = 1.2 fftw3 samplerate") 2>&5 
    2527225272  ac_status=$? 
    2527325273  echo "$as_me:$LINENO: \$? = $ac_status" >&5 
    2527425274  (exit $ac_status); }; then 
    25275   pkg_cv_RUBBERBAND_CFLAGS=`$PKG_CONFIG --cflags "rubberband fftw3 samplerate" 2>/dev/null` 
     25275  pkg_cv_RUBBERBAND_CFLAGS=`$PKG_CONFIG --cflags "rubberband = 1.2 fftw3 samplerate" 2>/dev/null` 
    2527625276else 
    2527725277  pkg_failed=yes 
     
    2528625286    else 
    2528725287        if test -n "$PKG_CONFIG" && \ 
    25288     { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"rubberband fftw3 samplerate\"") >&5 
    25289   ($PKG_CONFIG --exists --print-errors "rubberband fftw3 samplerate") 2>&5 
     25288    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"rubberband = 1.2 fftw3 samplerate\"") >&5 
     25289  ($PKG_CONFIG --exists --print-errors "rubberband = 1.2 fftw3 samplerate") 2>&5 
    2529025290  ac_status=$? 
    2529125291  echo "$as_me:$LINENO: \$? = $ac_status" >&5 
    2529225292  (exit $ac_status); }; then 
    25293   pkg_cv_RUBBERBAND_LIBS=`$PKG_CONFIG --libs "rubberband fftw3 samplerate" 2>/dev/null` 
     25293  pkg_cv_RUBBERBAND_LIBS=`$PKG_CONFIG --libs "rubberband = 1.2 fftw3 samplerate" 2>/dev/null` 
    2529425294else 
    2529525295  pkg_failed=yes 
     
    2531025310fi 
    2531125311        if test $_pkg_short_errors_supported = yes; then 
    25312                 RUBBERBAND_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "rubberband fftw3 samplerate"` 
     25312                RUBBERBAND_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "rubberband = 1.2 fftw3 samplerate"` 
    2531325313        else 
    25314                 RUBBERBAND_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "rubberband fftw3 samplerate"` 
     25314                RUBBERBAND_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "rubberband = 1.2 fftw3 samplerate"` 
    2531525315        fi 
    2531625316        # Put the nasty error message in config.log where it belongs 
    2531725317        echo "$RUBBERBAND_PKG_ERRORS" >&5 
    2531825318 
    25319         { { echo "$as_me:$LINENO: error: Package requirements (rubberband fftw3 samplerate) were not met: 
     25319        { { echo "$as_me:$LINENO: error: Package requirements (rubberband = 1.2 fftw3 samplerate) were not met: 
    2532025320 
    2532125321$RUBBERBAND_PKG_ERRORS 
     
    2532825328See the pkg-config man page for more details. 
    2532925329" >&5 
    25330 echo "$as_me: error: Package requirements (rubberband fftw3 samplerate) were not met: 
     25330echo "$as_me: error: Package requirements (rubberband = 1.2 fftw3 samplerate) were not met: 
    2533125331 
    2533225332$RUBBERBAND_PKG_ERRORS 
  • trunk/fm_server/configure.ac

    r257 r267  
    6565AC_SUBST(SAMPLERATE_CFLAGS) 
    6666 
    67 PKG_CHECK_MODULES(RUBBERBAND, rubberband fftw3 samplerate) 
     67PKG_CHECK_MODULES(RUBBERBAND, rubberband = 1.2 fftw3 samplerate) 
    6868AC_SUBST(RUBBERBAND_LIBS) 
    6969AC_SUBST(RUBBERBAND_CFLAGS) 
  • trunk/fm_server/src/fm_effect_rubber/Makefile.am

    r238 r267  
    33 
    44libfm_effect_rubber_la_SOURCES = \ 
    5         fm_rubber_wrapper.cpp \ 
    6         fm_rubber_wrapper.h \ 
    75        fm_effect_rubber.c \ 
    86        fm_effect_rubber.h 
    97 
    108 
    11 libfm_effect_rubber_la_CPPFLAGS = \ 
     9libfm_effect_rubber_la_CFLAGS = \ 
    1210        $(GLIB_CFLAGS) \ 
    1311        $(RGC_SERVER_CFLAGS) \ 
  • trunk/fm_server/src/fm_effect_rubber/Makefile.in

    r257 r267  
    5252        $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) 
    5353am_libfm_effect_rubber_la_OBJECTS =  \ 
    54         libfm_effect_rubber_la-fm_rubber_wrapper.lo \ 
    5554        libfm_effect_rubber_la-fm_effect_rubber.lo 
    5655libfm_effect_rubber_la_OBJECTS = $(am_libfm_effect_rubber_la_OBJECTS) 
     56libfm_effect_rubber_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ 
     57        $(LIBTOOLFLAGS) --mode=link $(CCLD) \ 
     58        $(libfm_effect_rubber_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ 
     59        $(LDFLAGS) -o $@ 
    5760DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) 
    5861depcomp = $(SHELL) $(top_srcdir)/depcomp 
     
    6669LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ 
    6770        --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ 
    68         $(LDFLAGS) -o $@ 
    69 CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ 
    70         $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) 
    71 LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ 
    72         --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ 
    73         $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) 
    74 CXXLD = $(CXX) 
    75 CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ 
    76         --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ 
    7771        $(LDFLAGS) -o $@ 
    7872SOURCES = $(libfm_effect_rubber_la_SOURCES) 
     
    240234noinst_LTLIBRARIES = libfm_effect_rubber.la 
    241235libfm_effect_rubber_la_SOURCES = \ 
    242         fm_rubber_wrapper.cpp \ 
    243         fm_rubber_wrapper.h \ 
    244236        fm_effect_rubber.c \ 
    245237        fm_effect_rubber.h 
    246238 
    247 libfm_effect_rubber_la_CPPFLAGS = \ 
     239libfm_effect_rubber_la_CFLAGS = \ 
    248240        $(GLIB_CFLAGS) \ 
    249241        $(RGC_SERVER_CFLAGS) \ 
     
    258250 
    259251.SUFFIXES: 
    260 .SUFFIXES: .c .cpp .lo .o .obj 
     252.SUFFIXES: .c .lo .o .obj 
    261253$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps) 
    262254        @for dep in $?; do \ 
     
    298290        done 
    299291libfm_effect_rubber.la: $(libfm_effect_rubber_la_OBJECTS) $(libfm_effect_rubber_la_DEPENDENCIES)  
    300         $(CXXLINK)  $(libfm_effect_rubber_la_OBJECTS) $(libfm_effect_rubber_la_LIBADD) $(LIBS) 
     292        $(libfm_effect_rubber_la_LINK)  $(libfm_effect_rubber_la_OBJECTS) $(libfm_effect_rubber_la_LIBADD) $(LIBS) 
    301293 
    302294mostlyclean-compile: 
     
    307299 
    308300@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfm_effect_rubber_la-fm_effect_rubber.Plo@am__quote@ 
    309 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfm_effect_rubber_la-fm_rubber_wrapper.Plo@am__quote@ 
    310301 
    311302.c.o: 
     
    331322 
    332323libfm_effect_rubber_la-fm_effect_rubber.lo: fm_effect_rubber.c 
    333 @am__fastdepCC_TRUE@    $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfm_effect_rubber_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libfm_effect_rubber_la-fm_effect_rubber.lo -MD -MP -MF $(DEPDIR)/libfm_effect_rubber_la-fm_effect_rubber.Tpo -c -o libfm_effect_rubber_la-fm_effect_rubber.lo `test -f 'fm_effect_rubber.c' || echo '$(srcdir)/'`fm_effect_rubber.c 
     324@am__fastdepCC_TRUE@    $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfm_effect_rubber_la_CFLAGS) $(CFLAGS) -MT libfm_effect_rubber_la-fm_effect_rubber.lo -MD -MP -MF $(DEPDIR)/libfm_effect_rubber_la-fm_effect_rubber.Tpo -c -o libfm_effect_rubber_la-fm_effect_rubber.lo `test -f 'fm_effect_rubber.c' || echo '$(srcdir)/'`fm_effect_rubber.c 
    334325@am__fastdepCC_TRUE@    mv -f $(DEPDIR)/libfm_effect_rubber_la-fm_effect_rubber.Tpo $(DEPDIR)/libfm_effect_rubber_la-fm_effect_rubber.Plo 
    335326@AMDEP_TRUE@@am__fastdepCC_FALSE@       source='fm_effect_rubber.c' object='libfm_effect_rubber_la-fm_effect_rubber.lo' libtool=yes @AMDEPBACKSLASH@ 
    336327@AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 
    337 @am__fastdepCC_FALSE@   $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfm_effect_rubber_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libfm_effect_rubber_la-fm_effect_rubber.lo `test -f 'fm_effect_rubber.c' || echo '$(srcdir)/'`fm_effect_rubber.c 
    338  
    339 .cpp.o: 
    340 @am__fastdepCXX_TRUE@   $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< 
    341 @am__fastdepCXX_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po 
    342 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ 
    343 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 
    344 @am__fastdepCXX_FALSE@  $(CXXCOMPILE) -c -o $@ $< 
    345  
    346 .cpp.obj: 
    347 @am__fastdepCXX_TRUE@   $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` 
    348 @am__fastdepCXX_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po 
    349 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ 
    350 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 
    351 @am__fastdepCXX_FALSE@  $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` 
    352  
    353 .cpp.lo: 
    354 @am__fastdepCXX_TRUE@   $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< 
    355 @am__fastdepCXX_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo 
    356 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ 
    357 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 
    358 @am__fastdepCXX_FALSE@  $(LTCXXCOMPILE) -c -o $@ $< 
    359  
    360 libfm_effect_rubber_la-fm_rubber_wrapper.lo: fm_rubber_wrapper.cpp 
    361 @am__fastdepCXX_TRUE@   $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfm_effect_rubber_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libfm_effect_rubber_la-fm_rubber_wrapper.lo -MD -MP -MF $(DEPDIR)/libfm_effect_rubber_la-fm_rubber_wrapper.Tpo -c -o libfm_effect_rubber_la-fm_rubber_wrapper.lo `test -f 'fm_rubber_wrapper.cpp' || echo '$(srcdir)/'`fm_rubber_wrapper.cpp 
    362 @am__fastdepCXX_TRUE@   mv -f $(DEPDIR)/libfm_effect_rubber_la-fm_rubber_wrapper.Tpo $(DEPDIR)/libfm_effect_rubber_la-fm_rubber_wrapper.Plo 
    363 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      source='fm_rubber_wrapper.cpp' object='libfm_effect_rubber_la-fm_rubber_wrapper.lo' libtool=yes @AMDEPBACKSLASH@ 
    364 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 
    365 @am__fastdepCXX_FALSE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfm_effect_rubber_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libfm_effect_rubber_la-fm_rubber_wrapper.lo `test -f 'fm_rubber_wrapper.cpp' || echo '$(srcdir)/'`fm_rubber_wrapper.cpp 
     328@am__fastdepCC_FALSE@   $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfm_effect_rubber_la_CFLAGS) $(CFLAGS) -c -o libfm_effect_rubber_la-fm_effect_rubber.lo `test -f 'fm_effect_rubber.c' || echo '$(srcdir)/'`fm_effect_rubber.c 
    366329 
    367330mostlyclean-libtool: 
  • trunk/fm_server/src/fm_effect_rubber/fm_effect_rubber.c

    r246 r267  
    2929#include <rgc_server.h> 
    3030 
     31#include <rubberband-c.h> 
     32 
    3133#include "../fm_buffer.h" 
    3234#include "../fm_element.h" 
    3335#include "../fm_input.h" 
    3436#include "../fm_effect.h" 
    35 #include "fm_rubber_wrapper.h" 
    3637#include "fm_effect_rubber.h" 
    3738 
     
    138139fm_effect_rubber_init                   (FmEffectRubber         *rubber) 
    139140{ 
    140         rubber->wrap = NULL; 
     141        rubber->state = NULL; 
    141142        rubber->temp_buffer = NULL; 
    142143        rubber->time_ratio = 1.0; 
     
    166167                return FALSE; 
    167168 
    168         rubber->wrap = fm_rubber_wrapper_new (); 
     169        rubber->state = rubberband_new (44100, 2, RubberBandOptionProcessRealTime, 1.0, 1.0);   /* FIXME: 44100 */ 
    169170        rubber->temp_buffer = fm_buffer_new (16384, FM_CHANNELS_STEREO); 
    170171        rubber->channel_ptr = g_new (gfloat *, FM_CHANNELS_STEREO); 
     
    181182        g_free (rubber->channel_ptr); 
    182183        fm_buffer_destroy (rubber->temp_buffer); 
    183         fm_rubber_wrapper_destroy (rubber->wrap); 
     184        rubberband_delete (rubber->state); 
    184185 
    185186        return TRUE; 
     
    196197 
    197198        if (rubber->change_time_ratio > -1) { 
    198                 fm_rubber_wrapper_set_time_ratio (rubber->wrap, rubber->change_time_ratio); 
     199                rubberband_set_time_ratio (rubber->state, rubber->change_time_ratio); 
    199200                rubber->time_ratio = rubber->change_time_ratio; 
    200201                rubber->change_time_ratio = -1; 
    201                 rubber->latency = fm_rubber_wrapper_get_latency (rubber->wrap); 
     202                rubber->latency = rubberband_get_latency (rubber->state); 
    202203        } 
    203204 
    204205        if (rubber->change_pitch_scale > -1) { 
    205                 fm_rubber_wrapper_set_pitch_scale (rubber->wrap, rubber->change_pitch_scale); 
     206                rubberband_set_pitch_scale (rubber->state, rubber->change_pitch_scale); 
    206207                rubber->pitch_scale = rubber->change_pitch_scale; 
    207208                rubber->change_pitch_scale = -1; 
    208                 rubber->latency = fm_rubber_wrapper_get_latency (rubber->wrap); 
     209                rubber->latency = rubberband_get_latency (rubber->state); 
    209210        } 
    210211 
     
    218219         
    219220        while (samples_needed > 0) { 
    220                 guint samples_avail = fm_rubber_wrapper_available (rubber->wrap); 
     221                guint samples_avail = rubberband_available (rubber->state); 
    221222 
    222223                if (samples_avail) { 
     
    226227                                ask_for = samples_needed; 
    227228 
    228                         guint retrieved = fm_rubber_wrapper_retrieve (rubber->wrap, rubber->channel_ptr, ask_for); 
     229                        guint retrieved = rubberband_retrieve (rubber->state, rubber->channel_ptr, ask_for); 
    229230                        samples_needed -= retrieved; 
    230231 
     
    241242                } else { 
    242243                        /* ask for another buffer from our source */ 
    243                         guint samples_req = fm_rubber_wrapper_get_samples_required (rubber->wrap); 
     244                        guint samples_req = rubberband_get_samples_required (rubber->state); 
    244245 
    245246                        //g_print ("Requested %u samples\n", samples_req); 
     
    250251                        if (rubber->temp_buffer->discont == TRUE) { 
    251252                                g_print ("***************** DISCONT!!!!\n"); 
    252                                 fm_rubber_wrapper_reset (rubber->wrap); 
     253                                rubberband_reset (rubber->state); 
    253254                                start_timestamp = rubber->temp_buffer->timestamp_ns; 
    254255 
     
    261262                        rubber->temp_timestamp_ns = rubber->temp_buffer->timestamp_ns; 
    262263 
    263                         fm_rubber_wrapper_process (rubber->wrap, rubber->temp_buffer->channel_data, samples_req, FALSE); 
     264                        rubberband_process (rubber->state, (const float *const *) rubber->temp_buffer->channel_data, samples_req, FALSE); 
    264265                } 
    265266 
  • trunk/fm_server/src/fm_effect_rubber/fm_effect_rubber.h

    r245 r267  
    3232#define FM_EFFECT_RUBBER_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), FM_TYPE_EFFECT_RUBBER, FmEffectRubberClass)) 
    3333 
     34/* Avoid the need of including "rubberband-c.h" from other plugins */ 
     35#ifndef RubberBandState 
     36#define RubberBandState void* 
     37#endif 
     38 
    3439 
    3540typedef struct _FmEffectRubber FmEffectRubber; 
     
    4045        FmEffect effect; 
    4146 
    42         FmRubberWrapper *wrap; 
     47        RubberBandState state; 
    4348 
    4449        FmBuffer *temp_buffer; 
  • trunk/fm_server/src/fm_input_cdj.c

    r266 r267  
    3131#include "fm_input_gst/fm_input_gst_common.h" 
    3232#include "fm_input_gst/fm_input_gst.h" 
    33 //#include "fm_effect_rate.h" 
    34 #include "fm_effect_rubber/fm_rubber_wrapper.h" 
    3533#include "fm_effect_rubber/fm_effect_rubber.h" 
    3634#include "fm_output.h" 
  • trunk/rubberband/ChangeLog

    r234 r267  
     1 
     2Changes since Rubber Band v1.0.1 
     3 
     4 * Added an initial "formant preservation" option when pitch shifting 
     5 * Real-time pitch shifting now uses a faster method by default, with 
     6   less variation in CPU usage 
     7 * The code is more amenable to compiler auto-vectorization (through 
     8   e.g. gcc --ftree-vectorize). 
     9 
  • trunk/rubberband/README

    r234 r267  
    55An audio time-stretching and pitch-shifting library and utility program. 
    66 
    7 Copyright 2007 Chris Cannam, cannam@all-day-breakfast.com. 
     7Copyright 2008 Chris Cannam, cannam@all-day-breakfast.com. 
    88 
    99Distributed under the GNU General Public License. 
     
    2020 
    2121    Rubber Band is a phase-vocoder-based frequency domain time 
    22     stretcher with partial phase locking to peak frequencies and phase 
    23     resynchronisation at noisy transients.  It is suitable for most 
    24     musical uses with its default settings, and has a range of options 
    25     for fine tuning. 
     22    stretcher with phase resynchronisation at noisy transients and a 
     23    phase lamination technique to reduce phasiness.  It is suitable for 
     24    most musical uses with its default settings, and has a range of 
     25    options for fine tuning. 
    2626 
    2727  * Real-time capable 
     
    143143There is extensive documentation in the class header. 
    144144 
     145A header with C language bindings is also provided in 
     146<rubberband/rubberband-c.h>.  This is a wrapper around the C++ 
     147implementation, and as the implementation is the same, it also 
     148requires linkage against the C++ standard libraries.  It is not yet 
     149documented separately from the C++ header.  You should include only 
     150one of the two headers, not both. 
     151 
    145152The source code for the command-line utility (src/main.cpp) provides a 
    146153good example of how to use Rubber Band in offline mode; the LADSPA 
  • trunk/rubberband/configure

    r257 r267  
    2130021300 
    2130121301if test "x$GCC" = "xyes"; then 
     21302  case " $CFLAGS " in 
     21303    *[\ \       ]-fPIC\ -Wall[\ \       ]*) ;; 
     21304    *) CFLAGS="$CFLAGS -fPIC -Wall" ;; 
     21305  esac 
    2130221306  case " $CXXFLAGS " in 
    2130321307    *[\ \       ]-fPIC\ -Wall[\ \       ]*) ;; 
  • trunk/rubberband/configure.ac

    r236 r267  
    2929changequote(,)dnl 
    3030if test "x$GCC" = "xyes"; then 
     31  case " $CFLAGS " in 
     32    *[\ \       ]-fPIC\ -Wall[\ \       ]*) ;; 
     33    *) CFLAGS="$CFLAGS -fPIC -Wall" ;; 
     34  esac 
    3135  case " $CXXFLAGS " in 
    3236    *[\ \       ]-fPIC\ -Wall[\ \       ]*) ;; 
  • trunk/rubberband/include/Makefile.am

    r235 r267  
    22 
    33librubberband_include_DATA = \ 
    4         TimeStretcher.h \ 
     4        rubberband-c.h \ 
    55        RubberBandStretcher.h 
    66 
  • trunk/rubberband/include/Makefile.in

    r257 r267  
    168168librubberband_includedir = $(pkgincludedir) 
    169169librubberband_include_DATA = \ 
    170         TimeStretcher.h \ 
     170        rubberband-c.h \ 
    171171        RubberBandStretcher.h 
    172172 
  • trunk/rubberband/include/RubberBandStretcher.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1515#ifndef _RUBBERBANDSTRETCHER_H_ 
    1616#define _RUBBERBANDSTRETCHER_H_ 
    17  
    18 #include "TimeStretcher.h" 
     17     
     18#define RUBBERBAND_VERSION "1.2.0-gpl"     
     19#define RUBBERBAND_API_MAJOR_VERSION 2 
     20#define RUBBERBAND_API_MINOR_VERSION 0 
    1921 
    2022#include <vector> 
     23 
     24/** 
     25 * @mainpage RubberBand 
     26 *  
     27 * The Rubber Band API is contained in the single class 
     28 * RubberBand::RubberBandStretcher. 
     29 * 
     30 * Threading notes for real-time applications: 
     31 *  
     32 * Multiple instances of RubberBandStretcher may be created and used 
     33 * in separate threads concurrently.  However, for any single instance 
     34 * of RubberBandStretcher, you may not call process() more than once 
     35 * concurrently, and you may not change the time or pitch ratio while 
     36 * a process() call is being executed (if the stretcher was created in 
     37 * "real-time mode"; in "offline mode" you can't change the ratios 
     38 * during use anyway). 
     39 *  
     40 * So you can run process() in its own thread if you like, but if you 
     41 * want to change ratios dynamically from a different thread, you will 
     42 * need some form of mutex in your code.  Changing the time or pitch 
     43 * ratio is real-time safe except in extreme circumstances, so for 
     44 * most applications that may change these dynamically it probably 
     45 * makes most sense to do so from the same thread as calls process(), 
     46 * even if that is a real-time thread. 
     47 */ 
    2148 
    2249namespace RubberBand 
    2350{ 
    2451 
    25 class RubberBandStretcher : public TimeStretcher 
     52class RubberBandStretcher 
    2653{ 
    2754public: 
    28  
    2955    /** 
    3056     * Processing options for the timestretcher.  The preferred 
     
    103129     * any time. 
    104130     * 
    105      *   \li \c OptionPhaseAdaptive - Lock the adjustments of phase 
    106      *   for frequencies close to peak frequencies to those of the 
    107      *   peak, but reduce the degree of locking as the stretch ratio 
    108      *   gets longer.  This, the default setting, should give a good 
    109      *   balance between clarity and smoothness in most situations. 
    110      * 
    111      *   \li \c OptionPhasePeakLocked - Lock the adjustments of phase 
    112      *   for frequencies close to peak frequencies to those of the 
    113      *   peak.  This should give a clear result in situations with 
    114      *   relatively low stretch ratios, but a relatively metallic 
    115      *   sound at longer stretches. 
    116      * 
    117      *   \li \c OptionPhaseIndependent - Do not lock phase adjustments 
    118      *   to peak frequencies.  This usually results in a softer, 
    119      *   phasier sound. 
     131     *   \li \c OptionPhaseLaminar - Adjust phases when stretching in 
     132     *   such a way as to try to retain the continuity of phase 
     133     *   relationships between adjacent frequency bins whose phases 
     134     *   are behaving in similar ways.  This, the default setting, 
     135     *   should give good results in most situations. 
     136     * 
     137     *   \li \c OptionPhaseIndependent - Adjust the phase in each 
     138     *   frequency bin independently from its neighbours.  This 
     139     *   usually results in a slightly softer, phasier sound. 
    120140     * 
    121141     * 5. Flags prefixed \c OptionThreading control the threading 
     
    152172     *   likely to result in a smoother sound at the expense of 
    153173     *   clarity and timing. 
    154      */ 
     174     * 
     175     * 7. Flags prefixed \c OptionFormant control the handling of 
     176     * formant shape (spectral envelope) when pitch-shifting.  These 
     177     * options may be changed at any time. 
     178     * 
     179     *   \li \c OptionFormantShifted - Apply no special formant 
     180     *   processing.  The spectral envelope will be pitch shifted as 
     181     *   normal. 
     182     * 
     183     *   \li \c OptionFormantPreserved - Preserve the spectral 
     184     *   envelope of the unshifted signal.  This permits shifting the 
     185     *   note frequency without so substantially affecting the 
     186     *   perceived pitch profile of the voice or instrument. 
     187     * 
     188     * 8. Flags prefixed \c OptionPitch control the method used for 
     189     * pitch shifting.  These options may be changed at any time. 
     190     * They are only effective in realtime mode; in offline mode, the 
     191     * pitch-shift method is fixed. 
     192     * 
     193     *   \li \c OptionPitchHighSpeed - Use a method with a CPU cost 
     194     *   that is relatively moderate and predictable.  This may 
     195     *   sound less clear than OptionPitchHighQuality, especially 
     196     *   for large pitch shifts.  
     197 
     198     *   \li \c OptionPitchHighQuality - Use the highest quality 
     199     *   method for pitch shifting.  This method has a CPU cost 
     200     *   approximately proportional to the required frequency shift. 
     201 
     202     *   \li \c OptionPitchHighConsistency - Use the method that gives 
     203     *   greatest consistency when used to create small variations in 
     204     *   pitch around the 1.0-ratio level.  Unlike the previous two 
     205     *   options, this avoids discontinuities when moving across the 
     206     *   1.0 pitch scale in real-time; it also consumes more CPU than 
     207     *   the others in the case where the pitch scale is exactly 1.0. 
     208     */ 
     209     
     210    enum Option { 
     211 
     212        OptionProcessOffline       = 0x00000000, 
     213        OptionProcessRealTime      = 0x00000001, 
     214 
     215        OptionStretchElastic       = 0x00000000, 
     216        OptionStretchPrecise       = 0x00000010, 
     217     
     218        OptionTransientsCrisp      = 0x00000000, 
     219        OptionTransientsMixed      = 0x00000100, 
     220        OptionTransientsSmooth     = 0x00000200, 
     221 
     222        OptionPhaseLaminar         = 0x00000000, 
     223        OptionPhaseIndependent     = 0x00002000, 
     224     
     225        OptionThreadingAuto        = 0x00000000, 
     226        OptionThreadingNever       = 0x00010000, 
     227        OptionThreadingAlways      = 0x00020000, 
     228 
     229        OptionWindowStandard       = 0x00000000, 
     230        OptionWindowShort          = 0x00100000, 
     231        OptionWindowLong           = 0x00200000, 
     232 
     233        OptionFormantShifted       = 0x00000000, 
     234        OptionFormantPreserved     = 0x01000000, 
     235 
     236        OptionPitchHighSpeed       = 0x00000000, 
     237        OptionPitchHighQuality     = 0x02000000, 
     238        OptionPitchHighConsistency = 0x04000000 
     239    }; 
     240 
    155241    typedef int Options; 
    156      
    157     static const int OptionProcessOffline   = 0x00000000; 
    158     static const int OptionProcessRealTime  = 0x00000001; 
    159  
    160     static const int OptionStretchElastic   = 0x00000000; 
    161     static const int OptionStretchPrecise   = 0x00000010; 
    162      
    163     static const int OptionTransientsCrisp  = 0x00000000; 
    164     static const int OptionTransientsMixed  = 0x00000100; 
    165     static const int OptionTransientsSmooth = 0x00000200; 
    166  
    167     static const int OptionPhaseAdaptive    = 0x00000000; 
    168     static const int OptionPhasePeakLocked  = 0x00001000; 
    169     static const int OptionPhaseIndependent = 0x00002000; 
    170      
    171     static const int OptionThreadingAuto    = 0x00000000; 
    172     static const int OptionThreadingNever   = 0x00010000; 
    173     static const int OptionThreadingAlways  = 0x00020000; 
    174  
    175     static const int OptionWindowStandard   = 0x00000000; 
    176     static const int OptionWindowShort      = 0x00100000; 
    177     static const int OptionWindowLong       = 0x00200000; 
    178  
    179     static const int DefaultOptions         = 0x00000000; 
    180     static const int PercussiveOptions      = OptionWindowShort | \ 
    181                                               OptionPhaseIndependent; 
     242 
     243    enum PresetOption { 
     244        DefaultOptions             = 0x00000000, 
     245        PercussiveOptions          = 0x00102000 
     246    }; 
    182247 
    183248    /** 
     
    194259                        double initialTimeRatio = 1.0, 
    195260                        double initialPitchScale = 1.0); 
    196     virtual ~RubberBandStretcher(); 
     261    ~RubberBandStretcher(); 
    197262 
    198263    /** 
     
    201266     * (although retaining the current time and pitch ratio). 
    202267     */ 
    203     virtual void reset(); 
     268    void reset(); 
    204269 
    205270    /** 
     
    224289     * run at once (there is no internal mutex for this purpose). 
    225290     */ 
    226     virtual void setTimeRatio(double ratio); 
     291    void setTimeRatio(double ratio); 
    227292 
    228293    /** 
     
    251316     * run at once (there is no internal mutex for this purpose). 
    252317     */ 
    253     virtual void setPitchScale(double scale); 
     318    void setPitchScale(double scale); 
    254319 
    255320    /** 
     
    257322     * construction or with setTimeRatio()). 
    258323     */ 
    259     virtual double getTimeRatio() const; 
     324    double getTimeRatio() const; 
    260325 
    261326    /** 
     
    263328     * on construction or with setPitchScale()). 
    264329     */ 
    265     virtual double getPitchScale() const; 
     330    double getPitchScale() const; 
    266331 
    267332    /** 
     
    274339     * ratio and other options. 
    275340     */ 
    276     virtual size_t getLatency() const; 
     341    size_t getLatency() const; 
    277342 
    278343    /** 
     
    282347     * construction). 
    283348     */ 
    284     virtual void setTransientsOption(Options options); 
     349    void setTransientsOption(Options options); 
    285350 
    286351    /** 
     
    292357     * way when this function is called. 
    293358     */ 
    294     virtual void setPhaseOption(Options options); 
     359    void setPhaseOption(Options options); 
     360 
     361    /** 
     362     * Change an OptionFormant configuration setting.  This may be 
     363     * called at any time in any mode. 
     364     * 
     365     * Note that if running multi-threaded in Offline mode, the change 
     366     * may not take effect immediately if processing is already under 
     367     * way when this function is called. 
     368     */ 
     369    void setFormantOption(Options options); 
     370 
     371    /** 
     372     * Change an OptionPitch configuration setting.  This may be 
     373     * called at any time in RealTime mode.  It may not be called in 
     374     * Offline mode (for which the transients option is fixed on 
     375     * construction). 
     376     */ 
     377    void setPitchOption(Options options); 
    295378 
    296379    /** 
     
    301384     * possible and this value is ignored. 
    302385     */ 
    303     virtual void setExpectedInputDuration(size_t samples); 
     386    void setExpectedInputDuration(size_t samples); 
    304387 
    305388    /** 
     
    315398     * and from which there is no output). 
    316399     */ 
    317      virtual size_t getSamplesRequired() const; 
     400     size_t getSamplesRequired() const; 
    318401 
    319402    /** 
     
    332415     * and from which there is no output). 
    333416     */ 
    334     virtual void setMaxProcessSize(size_t samples); 
     417    void setMaxProcessSize(size_t samples); 
    335418 
    336419    /** 
     
    351434     * be provided to study() before the first process() call. 
    352435     */ 
    353     virtual void study(const float *const *input, size_t samples, bool final); 
     436    void study(const float *const *input, size_t samples, bool final); 
    354437 
    355438    /** 
     
    359442     * Set "final" to true if this is the last block of input data. 
    360443     */ 
    361     virtual void process(const float *const *input, size_t samples, bool final); 
     444    void process(const float *const *input, size_t samples, bool final); 
    362445 
    363446    /** 
     
    374457     * and all output read, and the stretch process is now finished. 
    375458     */ 
    376     virtual int available() const; 
     459    int available() const; 
    377460 
    378461    /** 
     
    383466     * retrieved. 
    384467     */ 
    385     virtual size_t retrieve(float *const *output, size_t samples) const; 
     468    size_t retrieve(float *const *output, size_t samples) const; 
    386469 
    387470    /** 
     
    390473     * This function is not for general use. 
    391474     */ 
    392     virtual float getFrequencyCutoff(int n) const; 
     475    float getFrequencyCutoff(int n) const; 
    393476 
    394477    /**  
     
    397480     * This function is not for general use. 
    398481     */ 
    399     virtual void setFrequencyCutoff(int n, float f); 
     482    void setFrequencyCutoff(int n, float f); 
    400483     
    401484    /** 
     
    404487     * This function is provided for diagnostic purposes only. 
    405488     */ 
    406     virtual size_t getInputIncrement() const; 
     489    size_t getInputIncrement() const; 
    407490 
    408491    /** 
     
    415498     * This function is provided for diagnostic purposes only. 
    416499     */ 
    417     virtual std::vector<int> getOutputIncrements() const; 
     500    std::vector<int> getOutputIncrements() const; 
    418501 
    419502    /** 
     
    426509     * This function is provided for diagnostic purposes only. 
    427510     */ 
    428     virtual std::vector<float> getPhaseResetCurve() const; 
     511    std::vector<float> getPhaseResetCurve() const; 
    429512 
    430513    /** 
     
    436519     * This function is provided for diagnostic purposes only. 
    437520     */ 
    438     virtual std::vector<int> getExactTimePoints() const; 
     521    std::vector<int> getExactTimePoints() const; 
    439522 
    440523    /** 
     
    442525     * with. 
    443526     */ 
    444     virtual size_t getChannelCount() const; 
     527    size_t getChannelCount() const; 
    445528 
    446529    /** 
     
    451534     * This function is provided for diagnostic purposes only. 
    452535     */ 
    453     virtual void calculateStretch(); 
     536    void calculateStretch(); 
    454537 
    455538    /** 
     
    460543     * called. 
    461544     */ 
    462     virtual void setDebugLevel(int level); 
     545    void setDebugLevel(int level); 
    463546 
    464547    /** 
  • trunk/rubberband/rubberband.pc.in

    r238 r267  
    22exec_prefix=@exec_prefix@ 
    33libdir=@libdir@ 
    4 includedir=@includedir@/rubberband 
     4includedir=@includedir@ 
    55 
    66Name: rubberband 
    7 Version: 1.0 
     7Version: 1.2 
    88Description:  
    9 Requires: fftw3, samplerate 
    10 Libs: -L@libdir@ -lrubberband 
    11 Cflags: -I@includedir@/rubberband 
     9Libs: -L${libdir} -lrubberband 
     10Cflags: -I${includedir}/rubberband  
  • trunk/rubberband/src/AudioCurve.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1414 
    1515#include "AudioCurve.h" 
     16 
     17#include <iostream> 
     18using namespace std; 
    1619 
    1720namespace RubberBand 
     
    2831} 
    2932 
     33float 
     34AudioCurve::process(const double *R__ mag, size_t increment) 
     35{ 
     36    cerr << "WARNING: Using inefficient AudioCurve::process(double)" << endl; 
     37    float *tmp = new float[m_windowSize]; 
     38    for (int i = 0; i < int(m_windowSize); ++i) tmp[i] = float(mag[i]); 
     39    float df = process(tmp, increment); 
     40    delete[] tmp; 
     41    return df; 
     42} 
    3043 
    3144} 
  • trunk/rubberband/src/AudioCurve.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1818#include <sys/types.h> 
    1919 
     20#include "sysutils.h" 
     21 
    2022namespace RubberBand  
    2123{ 
     
    2931    virtual void setWindowSize(size_t newSize) = 0; 
    3032     
    31     virtual float process(float *mag, size_t increment) = 0; 
     33    virtual float process(const float *R__ mag, size_t increment) = 0; 
     34    virtual float process(const double *R__ mag, size_t increment); 
    3235    virtual void reset() = 0; 
    3336 
  • trunk/rubberband/src/ConstantAudioCurve.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    3939 
    4040float 
    41 ConstantAudioCurve::process(float *, size_t) 
     41ConstantAudioCurve::process(const float *R__, size_t) 
    4242{ 
    4343    return 1.f; 
  • trunk/rubberband/src/ConstantAudioCurve.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    2929    virtual void setWindowSize(size_t newSize); 
    3030 
    31     virtual float process(float *mag, size_t increment); 
     31    virtual float process(const float *R__ mag, size_t increment); 
    3232    virtual void reset(); 
    3333}; 
  • trunk/rubberband/src/FFT.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1515#include "FFT.h" 
    1616#include "Thread.h" 
    17  
    18  
     17#include "Profiler.h" 
     18 
     19//#define FFT_MEASUREMENT 1 
     20 
     21 
     22#ifdef HAVE_FFTW3 
    1923#include <fftw3.h> 
     24#endif 
     25 
     26#ifdef USE_KISSFFT 
     27#include "bsd-3rdparty/kissfft/kiss_fftr.h" 
     28#endif 
     29 
     30#ifndef HAVE_FFTW3 
     31#ifndef USE_KISSFFT 
     32#ifndef USE_BUILTIN_FFT 
     33#error No FFT implementation selected! 
     34#endif 
     35#endif 
     36#endif 
    2037 
    2138#include <cmath> 
     
    2340#include <map> 
    2441#include <cstdio> 
     42#include <cstdlib> 
    2543#include <vector> 
    2644 
     
    3553    virtual void initDouble() = 0; 
    3654 
    37     virtual void forward(double *realIn, double *realOut, double *imagOut) = 0; 
    38     virtual void forwardPolar(double *realIn, double *magOut, double *phaseOut) = 0; 
    39     virtual void forwardMagnitude(double *realIn, double *magOut) = 0; 
    40  
    41     virtual void forward(float *realIn, float *realOut, float *imagOut) = 0; 
    42     virtual void forwardPolar(float *realIn, float *magOut, float *phaseOut) = 0; 
    43     virtual void forwardMagnitude(float *realIn, float *magOut) = 0; 
    44  
    45     virtual void inverse(double *realIn, double *imagIn, double *realOut) = 0; 
    46     virtual void inversePolar(double *magIn, double *phaseIn, double *realOut) = 0; 
    47  
    48     virtual void inverse(float *realIn, float *imagIn, float *realOut) = 0; 
    49     virtual void inversePolar(float *magIn, float *phaseIn, float *realOut) = 0; 
     55    virtual void forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) = 0; 
     56    virtual void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) = 0; 
     57    virtual void forwardMagnitude(const double *R__ realIn, double *R__ magOut) = 0; 
     58 
     59    virtual void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) = 0; 
     60    virtual void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) = 0; 
     61    virtual void forwardMagnitude(const float *R__ realIn, float *R__ magOut) = 0; 
     62 
     63    virtual void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) = 0; 
     64    virtual void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) = 0; 
     65    virtual void inverseCepstral(const double *R__ magIn, double *R__ cepOut) = 0; 
     66 
     67    virtual void inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut) = 0; 
     68    virtual void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) = 0; 
     69    virtual void inverseCepstral(const float *R__ magIn, float *R__ cepOut) = 0; 
    5070 
    5171    virtual float *getFloatTimeBuffer() = 0; 
     
    5373};     
    5474 
    55  
    56  
     75namespace FFTs { 
     76 
     77 
     78#ifdef HAVE_FFTW3 
    5779 
    5880// Define FFTW_DOUBLE_ONLY to make all uses of FFTW functions be 
     
    80102 
    81103#ifdef FFTW_DOUBLE_ONLY 
     104#define fft_float_type double 
    82105#define fftwf_complex fftw_complex 
    83106#define fftwf_plan fftw_plan 
     
    92115#define cosf cos 
    93116#define sinf sin 
     117#else 
     118#define fft_float_type float 
    94119#endif /* FFTW_DOUBLE_ONLY */ 
    95120 
    96121#ifdef FFTW_FLOAT_ONLY 
     122#define fft_double_type float 
    97123#define fftw_complex fftwf_complex 
    98124#define fftw_plan fftwf_plan 
     
    106132#define sqrt sqrtf 
    107133#define cos cosf 
    108 #define sif sinf 
     134#define sin sinf 
     135#else 
     136#define fft_double_type double 
    109137#endif /* FFTW_FLOAT_ONLY */ 
    110138 
     
    112140{ 
    113141public: 
    114     D_FFTW(unsigned int size) : m_fplanf(0) 
     142    D_FFTW(int size) : m_fplanf(0) 
    115143#ifdef FFTW_DOUBLE_ONLY 
    116144                              , m_frb(0) 
     
    130158            if (m_extantf > 0 && --m_extantf == 0) save = true; 
    131159            m_extantMutex.unlock(); 
     160#ifndef FFTW_DOUBLE_ONLY 
    132161            if (save) saveWisdom('f'); 
     162#endif 
    133163            fftwf_destroy_plan(m_fplanf); 
    134164            fftwf_destroy_plan(m_fplani); 
     
    144174            if (m_extantd > 0 && --m_extantd == 0) save = true; 
    145175            m_extantMutex.unlock(); 
     176#ifndef FFTW_FLOAT_ONLY 
    146177            if (save) saveWisdom('d'); 
     178#endif 
    147179            fftw_destroy_plan(m_dplanf); 
    148180            fftw_destroy_plan(m_dplani); 
     
    163195#ifdef FFTW_DOUBLE_ONLY 
    164196        if (load) loadWisdom('d'); 
    165         m_fbuf = (double *)fftw_malloc(m_size * sizeof(double)); 
    166197#else 
    167198        if (load) loadWisdom('f'); 
    168         m_fbuf = (float *)fftwf_malloc(m_size * sizeof(float)); 
    169 #endif 
     199#endif 
     200        m_fbuf = (fft_float_type *)fftw_malloc(m_size * sizeof(fft_float_type)); 
    170201        m_fpacked = (fftwf_complex *)fftw_malloc 
    171202            ((m_size/2 + 1) * sizeof(fftwf_complex)); 
     
    184215#ifdef FFTW_FLOAT_ONLY 
    185216        if (load) loadWisdom('f'); 
    186         m_dbuf = (float *)fftwf_malloc(m_size * sizeof(float)); 
    187217#else 
    188218        if (load) loadWisdom('d'); 
    189         m_dbuf = (double *)fftw_malloc(m_size * sizeof(double)); 
    190 #endif 
     219#endif 
     220        m_dbuf = (fft_double_type *)fftw_malloc(m_size * sizeof(fft_double_type)); 
    191221        m_dpacked = (fftw_complex *)fftw_malloc 
    192222            ((m_size/2 + 1) * sizeof(fftw_complex)); 
     
    251281    } 
    252282 
    253     void packFloat(float *re, float *im) { 
    254         for (unsigned int i = 0; i <= m_size/2; ++i) { 
    255             m_fpacked[i][0] = re[i]; 
    256             m_fpacked[i][1] = im[i]; 
    257         } 
    258     } 
    259  
    260     void packDouble(double *re, double *im) { 
    261         for (unsigned int i = 0; i <= m_size/2; ++i) { 
    262             m_dpacked[i][0] = re[i]; 
    263             m_dpacked[i][1] = im[i]; 
    264         } 
    265     } 
    266  
    267     void unpackFloat(float *re, float *im) { 
    268         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     283    void packFloat(const float *R__ re, const float *R__ im) { 
     284        const int hs = m_size/2; 
     285        fftwf_complex *const R__ fpacked = m_fpacked;  
     286        for (int i = 0; i <= hs; ++i) { 
     287            fpacked[i][0] = re[i]; 
     288        } 
     289        if (im) { 
     290            for (int i = 0; i <= hs; ++i) { 
     291                fpacked[i][1] = im[i]; 
     292            } 
     293        } else { 
     294            for (int i = 0; i <= hs; ++i) { 
     295                fpacked[i][1] = 0.f; 
     296            } 
     297        }                 
     298    } 
     299 
     300    void packDouble(const double *R__ re, const double *R__ im) { 
     301        const int hs = m_size/2; 
     302        fftw_complex *const R__ dpacked = m_dpacked;  
     303        for (int i = 0; i <= hs; ++i) { 
     304            dpacked[i][0] = re[i]; 
     305        } 
     306        if (im) { 
     307            for (int i = 0; i <= hs; ++i) { 
     308                dpacked[i][1] = im[i]; 
     309            } 
     310        } else { 
     311            for (int i = 0; i <= hs; ++i) { 
     312                dpacked[i][1] = 0.0; 
     313            } 
     314        } 
     315    } 
     316 
     317    void unpackFloat(float *R__ re, float *R__ im) { 
     318        const int hs = m_size/2; 
     319        for (int i = 0; i <= hs; ++i) { 
    269320            re[i] = m_fpacked[i][0]; 
    270             im[i] = m_fpacked[i][1]; 
     321        } 
     322        if (im) { 
     323            for (int i = 0; i <= hs; ++i) { 
     324                im[i] = m_fpacked[i][1]; 
     325            } 
    271326        } 
    272327    }         
    273328 
    274     void unpackDouble(double *re, double *im) { 
    275         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     329    void unpackDouble(double *R__ re, double *R__ im) { 
     330        const int hs = m_size/2; 
     331        for (int i = 0; i <= hs; ++i) { 
    276332            re[i] = m_dpacked[i][0]; 
    277             im[i] = m_dpacked[i][1]; 
     333        } 
     334        if (im) { 
     335            for (int i = 0; i <= hs; ++i) { 
     336                im[i] = m_dpacked[i][1]; 
     337            } 
    278338        } 
    279339    }         
    280340 
    281     void forward(double *realIn, double *realOut, double *imagOut) { 
     341    void forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) { 
    282342        if (!m_dplanf) initDouble(); 
     343        const int sz = m_size; 
     344        fft_double_type *const R__ dbuf = m_dbuf; 
    283345#ifndef FFTW_FLOAT_ONLY 
    284         if (realIn != m_dbuf)  
    285 #endif 
    286             for (unsigned int i = 0; i < m_size; ++i) { 
    287                 m_dbuf[i] = realIn[i]; 
     346        if (realIn != dbuf)  
     347#endif 
     348            for (int i = 0; i < sz; ++i) { 
     349                dbuf[i] = realIn[i]; 
    288350            } 
    289351        fftw_execute(m_dplanf); 
     
    291353    } 
    292354 
    293     void forwardPolar(double *realIn, double *magOut, double *phaseOut) { 
     355    void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) { 
    294356        if (!m_dplanf) initDouble(); 
     357        fft_double_type *const R__ dbuf = m_dbuf; 
     358        const int sz = m_size; 
     359#ifndef FFTW_FLOAT_ONLY 
     360        if (realIn != dbuf) 
     361#endif 
     362            for (int i = 0; i < sz; ++i) { 
     363                dbuf[i] = realIn[i]; 
     364            } 
     365        fftw_execute(m_dplanf); 
     366        const int hs = m_size/2; 
     367        for (int i = 0; i <= hs; ++i) { 
     368            magOut[i] = sqrt(m_dpacked[i][0] * m_dpacked[i][0] + 
     369                             m_dpacked[i][1] * m_dpacked[i][1]); 
     370        } 
     371        for (int i = 0; i <= hs; ++i) { 
     372            phaseOut[i] = atan2(m_dpacked[i][1], m_dpacked[i][0]); 
     373        } 
     374    } 
     375 
     376    void forwardMagnitude(const double *R__ realIn, double *R__ magOut) { 
     377        if (!m_dplanf) initDouble(); 
     378        fft_double_type *const R__ dbuf = m_dbuf; 
     379        const int sz = m_size; 
    295380#ifndef FFTW_FLOAT_ONLY 
    296381        if (realIn != m_dbuf) 
    297382#endif 
    298             for (unsigned int i = 0; i < m_size; ++i) { 
    299                 m_dbuf[i] = realIn[i]; 
     383            for (int i = 0; i < sz; ++i) { 
     384                dbuf[i] = realIn[i]; 
    300385            } 
    301386        fftw_execute(m_dplanf); 
    302         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     387        const int hs = m_size/2; 
     388        for (int i = 0; i <= hs; ++i) { 
    303389            magOut[i] = sqrt(m_dpacked[i][0] * m_dpacked[i][0] + 
    304390                             m_dpacked[i][1] * m_dpacked[i][1]); 
    305391        } 
    306         for (unsigned int i = 0; i <= m_size/2; ++i) { 
    307             phaseOut[i] = atan2(m_dpacked[i][1], m_dpacked[i][0]); 
    308         } 
    309     } 
    310  
    311     void forwardMagnitude(double *realIn, double *magOut) { 
    312         if (!m_dplanf) initDouble(); 
    313 #ifndef FFTW_FLOAT_ONLY 
    314         if (realIn != m_dbuf) 
    315 #endif 
    316             for (unsigned int i = 0; i < m_size; ++i) { 
    317                 m_dbuf[i] = realIn[i]; 
    318             } 
    319         fftw_execute(m_dplanf); 
    320         for (unsigned int i = 0; i <= m_size/2; ++i) { 
    321             magOut[i] = sqrt(m_dpacked[i][0] * m_dpacked[i][0] + 
    322                              m_dpacked[i][1] * m_dpacked[i][1]); 
    323         } 
    324     } 
    325  
    326     void forward(float *realIn, float *realOut, float *imagOut) { 
     392    } 
     393 
     394    void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) { 
    327395        if (!m_fplanf) initFloat(); 
     396        fft_float_type *const R__ fbuf = m_fbuf; 
     397        const int sz = m_size; 
    328398#ifndef FFTW_DOUBLE_ONLY 
    329         if (realIn != m_fbuf) 
    330 #endif 
    331             for (unsigned int i = 0; i < m_size; ++i) { 
    332                 m_fbuf[i] = realIn[i]; 
     399        if (realIn != fbuf) 
     400#endif 
     401            for (int i = 0; i < sz; ++i) { 
     402                fbuf[i] = realIn[i]; 
    333403            } 
    334404        fftwf_execute(m_fplanf); 
     
    336406    } 
    337407 
    338     void forwardPolar(float *realIn, float *magOut, float *phaseOut) { 
     408    void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) { 
    339409        if (!m_fplanf) initFloat(); 
     410        fft_float_type *const R__ fbuf = m_fbuf; 
     411        const int sz = m_size; 
    340412#ifndef FFTW_DOUBLE_ONLY 
    341         if (realIn != m_fbuf)  
    342 #endif 
    343             for (unsigned int i = 0; i < m_size; ++i) { 
    344                 m_fbuf[i] = realIn[i]; 
     413        if (realIn != fbuf)  
     414#endif 
     415            for (int i = 0; i < sz; ++i) { 
     416                fbuf[i] = realIn[i]; 
    345417            } 
    346418        fftwf_execute(m_fplanf); 
    347         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     419        const int hs = m_size/2; 
     420        for (int i = 0; i <= hs; ++i) { 
    348421            magOut[i] = sqrtf(m_fpacked[i][0] * m_fpacked[i][0] + 
    349422                              m_fpacked[i][1] * m_fpacked[i][1]); 
    350423        } 
    351         for (unsigned int i = 0; i <= m_size/2; ++i) { 
    352           phaseOut[i] = atan2f(m_fpacked[i][1], m_fpacked[i][0]) ; 
    353         } 
    354     } 
    355  
    356     void forwardMagnitude(float *realIn, float *magOut) { 
     424        for (int i = 0; i <= hs; ++i) { 
     425            phaseOut[i] = atan2f(m_fpacked[i][1], m_fpacked[i][0]) ; 
     426        } 
     427    } 
     428 
     429    void forwardMagnitude(const float *R__ realIn, float *R__ magOut) { 
    357430        if (!m_fplanf) initFloat(); 
     431        fft_float_type *const R__ fbuf = m_fbuf; 
     432        const int sz = m_size; 
    358433#ifndef FFTW_DOUBLE_ONLY 
    359         if (realIn != m_fbuf) 
    360 #endif 
    361             for (unsigned int i = 0; i < m_size; ++i) { 
    362                 m_fbuf[i] = realIn[i]; 
     434        if (realIn != fbuf) 
     435#endif 
     436            for (int i = 0; i < sz; ++i) { 
     437                fbuf[i] = realIn[i]; 
    363438            } 
    364439        fftwf_execute(m_fplanf); 
    365         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     440        const int hs = m_size/2; 
     441        for (int i = 0; i <= hs; ++i) { 
    366442            magOut[i] = sqrtf(m_fpacked[i][0] * m_fpacked[i][0] + 
    367443                              m_fpacked[i][1] * m_fpacked[i][1]); 
     
    369445    } 
    370446 
    371     void inverse(double *realIn, double *imagIn, double *realOut) { 
     447    void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) { 
    372448        if (!m_dplanf) initDouble(); 
    373449        packDouble(realIn, imagIn); 
    374450        fftw_execute(m_dplani); 
     451        const int sz = m_size; 
     452        fft_double_type *const R__ dbuf = m_dbuf; 
    375453#ifndef FFTW_FLOAT_ONLY 
    376         if (realOut != m_dbuf)  
    377 #endif 
    378             for (unsigned int i = 0; i < m_size; ++i) { 
    379                 realOut[i] = m_dbuf[i]; 
    380             } 
    381     } 
    382  
    383     void inversePolar(double *magIn, double *phaseIn, double *realOut) { 
     454        if (realOut != dbuf)  
     455#endif 
     456            for (int i = 0; i < sz; ++i) { 
     457                realOut[i] = dbuf[i]; 
     458            } 
     459    } 
     460 
     461    void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) { 
    384462        if (!m_dplanf) initDouble(); 
    385         for (unsigned int i = 0; i <= m_size/2; ++i) { 
    386             m_dpacked[i][0] = magIn[i] * cos(phaseIn[i]); 
    387             m_dpacked[i][1] = magIn[i] * sin(phaseIn[i]); 
     463        const int hs = m_size/2; 
     464        fftw_complex *const R__ dpacked = m_dpacked; 
     465        for (int i = 0; i <= hs; ++i) { 
     466            dpacked[i][0] = magIn[i] * cos(phaseIn[i]); 
     467        } 
     468        for (int i = 0; i <= hs; ++i) { 
     469            dpacked[i][1] = magIn[i] * sin(phaseIn[i]); 
    388470        } 
    389471        fftw_execute(m_dplani); 
     472        const int sz = m_size; 
     473        fft_double_type *const R__ dbuf = m_dbuf; 
    390474#ifndef FFTW_FLOAT_ONLY 
    391         if (realOut != m_dbuf) 
    392 #endif 
    393             for (unsigned int i = 0; i < m_size; ++i) { 
    394                 realOut[i] = m_dbuf[i]; 
    395             } 
    396     } 
    397  
    398     void inverse(float *realIn, float *imagIn, float *realOut) { 
     475        if (realOut != dbuf) 
     476#endif 
     477            for (int i = 0; i < sz; ++i) { 
     478                realOut[i] = dbuf[i]; 
     479            } 
     480    } 
     481 
     482    void inverseCepstral(const double *R__ magIn, double *R__ cepOut) { 
     483        if (!m_dplanf) initDouble(); 
     484        fft_double_type *const R__ dbuf = m_dbuf; 
     485        fftw_complex *const R__ dpacked = m_dpacked; 
     486        const int hs = m_size/2; 
     487        for (int i = 0; i <= hs; ++i) { 
     488            dpacked[i][0] = log(magIn[i] + 0.000001); 
     489        } 
     490        for (int i = 0; i <= hs; ++i) { 
     491            dpacked[i][1] = 0.0; 
     492        } 
     493        fftw_execute(m_dplani); 
     494        const int sz = m_size; 
     495#ifndef FFTW_FLOAT_ONLY 
     496        if (cepOut != dbuf) 
     497#endif 
     498            for (int i = 0; i < sz; ++i) { 
     499                cepOut[i] = dbuf[i]; 
     500            } 
     501    } 
     502 
     503    void inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut) { 
    399504        if (!m_fplanf) initFloat(); 
    400505        packFloat(realIn, imagIn); 
    401506        fftwf_execute(m_fplani); 
     507        const int sz = m_size; 
     508        fft_float_type *const R__ fbuf = m_fbuf; 
    402509#ifndef FFTW_DOUBLE_ONLY 
    403         if (realOut != m_fbuf) 
    404 #endif 
    405             for (unsigned int i = 0; i < m_size; ++i) { 
    406                 realOut[i] = m_fbuf[i]; 
    407             } 
    408     } 
    409  
    410     void inversePolar(float *magIn, float *phaseIn, float *realOut) { 
     510        if (realOut != fbuf) 
     511#endif 
     512            for (int i = 0; i < sz; ++i) { 
     513                realOut[i] = fbuf[i]; 
     514            } 
     515    } 
     516 
     517    void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) { 
    411518        if (!m_fplanf) initFloat(); 
    412         for (unsigned int i = 0; i <= m_size/2; ++i) { 
    413             m_fpacked[i][0] = magIn[i] * cosf(phaseIn[i]); 
    414             m_fpacked[i][1] = magIn[i] * sinf(phaseIn[i]); 
     519        const int hs = m_size/2; 
     520        fftwf_complex *const R__ fpacked = m_fpacked; 
     521        for (int i = 0; i <= hs; ++i) { 
     522            fpacked[i][0] = magIn[i] * cosf(phaseIn[i]); 
     523        } 
     524        for (int i = 0; i <= hs; ++i) { 
     525            fpacked[i][1] = magIn[i] * sinf(phaseIn[i]); 
    415526        } 
    416527        fftwf_execute(m_fplani); 
     528        const int sz = m_size; 
     529        fft_float_type *const R__ fbuf = m_fbuf; 
    417530#ifndef FFTW_DOUBLE_ONLY 
    418         if (realOut != m_fbuf) 
    419 #endif 
    420             for (unsigned int i = 0; i < m_size; ++i) { 
    421                 realOut[i] = m_fbuf[i]; 
     531        if (realOut != fbuf) 
     532#endif 
     533            for (int i = 0; i < sz; ++i) { 
     534                realOut[i] = fbuf[i]; 
     535            } 
     536    } 
     537 
     538    void inverseCepstral(const float *R__ magIn, float *R__ cepOut) { 
     539        if (!m_fplanf) initFloat(); 
     540        const int hs = m_size/2; 
     541        fftwf_complex *const R__ fpacked = m_fpacked; 
     542        for (int i = 0; i <= hs; ++i) { 
     543            fpacked[i][0] = logf(magIn[i] + 0.000001f); 
     544        } 
     545        for (int i = 0; i <= hs; ++i) { 
     546            fpacked[i][1] = 0.f; 
     547        } 
     548        fftwf_execute(m_fplani); 
     549        const int sz = m_size; 
     550        fft_float_type *const R__ fbuf = m_fbuf; 
     551#ifndef FFTW_DOUBLE_ONLY 
     552        if (cepOut != fbuf) 
     553#endif 
     554            for (int i = 0; i < sz; ++i) { 
     555                cepOut[i] = fbuf[i]; 
    422556            } 
    423557    } 
     
    461595    double *m_dbuf; 
    462596#endif 
    463     fftw_complex *m_dpacked; 
    464     unsigned int m_size; 
    465     static unsigned int m_extantf; 
    466     static unsigned int m_extantd; 
     597    fftw_complex * m_dpacked; 
     598    const int m_size; 
     599    static int m_extantf; 
     600    static int m_extantd; 
    467601    static Mutex m_extantMutex; 
    468602}; 
    469603 
    470 unsigned int 
     604int 
    471605D_FFTW::m_extantf = 0; 
    472606 
    473 unsigned int 
     607int 
    474608D_FFTW::m_extantd = 0; 
    475609 
     
    477611D_FFTW::m_extantMutex; 
    478612 
     613#endif /* HAVE_FFTW3 */ 
     614 
     615#ifdef USE_KISSFFT 
     616 
     617class D_KISSFFT : public FFTImpl 
     618{ 
     619public: 
     620    D_KISSFFT(int size) : 
     621        m_size(size), 
     622        m_frb(0), 
     623        m_drb(0), 
     624        m_fplanf(0),   
     625        m_fplani(0) 
     626    { 
     627#ifdef FIXED_POINT 
     628#error KISSFFT is not configured for float values 
     629#endif 
     630        if (sizeof(kiss_fft_scalar) != sizeof(float)) { 
     631            std::cerr << "ERROR: KISSFFT is not configured for float values" 
     632                      << std::endl; 
     633        } 
     634 
     635        m_fbuf = new kiss_fft_scalar[m_size + 2]; 
     636        m_fpacked = new kiss_fft_cpx[m_size + 2]; 
     637        m_fplanf = kiss_fftr_alloc(m_size, 0, NULL, NULL); 
     638        m_fplani = kiss_fftr_alloc(m_size, 1, NULL, NULL); 
     639    } 
     640 
     641    ~D_KISSFFT() { 
     642        kiss_fftr_free(m_fplanf); 
     643        kiss_fftr_free(m_fplani); 
     644        kiss_fft_cleanup(); 
     645 
     646        delete[] m_fbuf; 
     647        delete[] m_fpacked; 
     648 
     649        if (m_frb) delete[] m_frb; 
     650        if (m_drb) delete[] m_drb; 
     651    } 
     652 
     653    void initFloat() { } 
     654    void initDouble() { } 
     655 
     656    void packFloat(const float *R__ re, const float *R__ im) { 
     657        const int hs = m_size/2; 
     658        for (int i = 0; i <= hs; ++i) { 
     659            m_fpacked[i].r = re[i]; 
     660            m_fpacked[i].i = im[i]; 
     661        } 
     662    } 
     663 
     664    void unpackFloat(float *R__ re, float *R__ im) { 
     665        const int hs = m_size/2; 
     666        for (int i = 0; i <= hs; ++i) { 
     667            re[i] = m_fpacked[i].r; 
     668            im[i] = m_fpacked[i].i; 
     669        } 
     670    }         
     671 
     672    void packDouble(const double *R__ re, const double *R__ im) { 
     673        const int hs = m_size/2; 
     674        for (int i = 0; i <= hs; ++i) { 
     675            m_fpacked[i].r = float(re[i]); 
     676            m_fpacked[i].i = float(im[i]); 
     677        } 
     678    } 
     679 
     680    void unpackDouble(double *R__ re, double *R__ im) { 
     681        const int hs = m_size/2; 
     682        for (int i = 0; i <= hs; ++i) { 
     683            re[i] = double(m_fpacked[i].r); 
     684            im[i] = double(m_fpacked[i].i); 
     685        } 
     686    }         
     687 
     688    void forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) { 
     689 
     690        for (int i = 0; i < m_size; ++i) { 
     691            m_fbuf[i] = float(realIn[i]); 
     692        } 
     693 
     694        kiss_fftr(m_fplanf, m_fbuf, m_fpacked); 
     695        unpackDouble(realOut, imagOut); 
     696    } 
     697 
     698    void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) { 
     699 
     700        for (int i = 0; i < m_size; ++i) { 
     701            m_fbuf[i] = float(realIn[i]); 
     702        } 
     703 
     704        kiss_fftr(m_fplanf, m_fbuf, m_fpacked); 
     705 
     706        const int hs = m_size/2; 
     707 
     708        for (int i = 0; i <= hs; ++i) { 
     709            magOut[i] = sqrt(double(m_fpacked[i].r) * double(m_fpacked[i].r) + 
     710                             double(m_fpacked[i].i) * double(m_fpacked[i].i)); 
     711        } 
     712 
     713        for (int i = 0; i <= hs; ++i) { 
     714            phaseOut[i] = atan2(double(m_fpacked[i].i), double(m_fpacked[i].r)); 
     715        } 
     716    } 
     717 
     718    void forwardMagnitude(const double *R__ realIn, double *R__ magOut) { 
     719 
     720        for (int i = 0; i < m_size; ++i) { 
     721            m_fbuf[i] = float(realIn[i]); 
     722        } 
     723 
     724        kiss_fftr(m_fplanf, m_fbuf, m_fpacked); 
     725 
     726        const int hs = m_size/2; 
     727 
     728        for (int i = 0; i <= hs; ++i) { 
     729            magOut[i] = sqrt(double(m_fpacked[i].r) * double(m_fpacked[i].r) + 
     730                             double(m_fpacked[i].i) * double(m_fpacked[i].i)); 
     731        } 
     732    } 
     733 
     734    void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) { 
     735 
     736        kiss_fftr(m_fplanf, realIn, m_fpacked); 
     737        unpackFloat(realOut, imagOut); 
     738    } 
     739 
     740    void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) { 
     741 
     742        kiss_fftr(m_fplanf, realIn, m_fpacked); 
     743 
     744        const int hs = m_size/2; 
     745 
     746        for (int i = 0; i <= hs; ++i) { 
     747            magOut[i] = sqrtf(m_fpacked[i].r * m_fpacked[i].r + 
     748                              m_fpacked[i].i * m_fpacked[i].i); 
     749        } 
     750 
     751        for (int i = 0; i <= hs; ++i) { 
     752            phaseOut[i] = atan2f(m_fpacked[i].i, m_fpacked[i].r); 
     753        } 
     754    } 
     755 
     756    void forwardMagnitude(const float *R__ realIn, float *R__ magOut) { 
     757 
     758        kiss_fftr(m_fplanf, realIn, m_fpacked); 
     759 
     760        const int hs = m_size/2; 
     761 
     762        for (int i = 0; i <= hs; ++i) { 
     763            magOut[i] = sqrtf(m_fpacked[i].r * m_fpacked[i].r + 
     764                              m_fpacked[i].i * m_fpacked[i].i); 
     765        } 
     766    } 
     767 
     768    void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) { 
     769 
     770        packDouble(realIn, imagIn); 
     771 
     772        kiss_fftri(m_fplani, m_fpacked, m_fbuf); 
     773 
     774        for (int i = 0; i < m_size; ++i) { 
     775            realOut[i] = m_fbuf[i]; 
     776        } 
     777    } 
     778 
     779    void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) { 
     780 
     781        const int hs = m_size/2; 
     782 
     783        for (int i = 0; i <= hs; ++i) { 
     784            m_fpacked[i].r = float(magIn[i] * cos(phaseIn[i])); 
     785            m_fpacked[i].i = float(magIn[i] * sin(phaseIn[i])); 
     786        } 
     787 
     788        kiss_fftri(m_fplani, m_fpacked, m_fbuf); 
     789 
     790        for (int i = 0; i < m_size; ++i) { 
     791            realOut[i] = m_fbuf[i]; 
     792        } 
     793    } 
     794 
     795    void inverseCepstral(const double *R__ magIn, double *R__ cepOut) { 
     796 
     797        const int hs = m_size/2; 
     798 
     799        for (int i = 0; i <= hs; ++i) { 
     800            m_fpacked[i].r = float(log(magIn[i] + 0.000001)); 
     801            m_fpacked[i].i = 0.0f; 
     802        } 
     803 
     804        kiss_fftri(m_fplani, m_fpacked, m_fbuf); 
     805 
     806        for (int i = 0; i < m_size; ++i) { 
     807            cepOut[i] = m_fbuf[i]; 
     808        } 
     809    } 
     810     
     811    void inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut) { 
     812 
     813        packFloat(realIn, imagIn); 
     814        kiss_fftri(m_fplani, m_fpacked, realOut); 
     815    } 
     816 
     817    void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) { 
     818 
     819        const int hs = m_size/2; 
     820 
     821        for (int i = 0; i <= hs; ++i) { 
     822            m_fpacked[i].r = magIn[i] * cosf(phaseIn[i]); 
     823            m_fpacked[i].i = magIn[i] * sinf(phaseIn[i]); 
     824        } 
     825 
     826        kiss_fftri(m_fplani, m_fpacked, realOut); 
     827    } 
     828 
     829    void inverseCepstral(const float *R__ magIn, float *R__ cepOut) { 
     830 
     831        const int hs = m_size/2; 
     832 
     833        for (int i = 0; i <= hs; ++i) { 
     834            m_fpacked[i].r = logf(magIn[i] + 0.000001f); 
     835            m_fpacked[i].i = 0.0f; 
     836        } 
     837 
     838        kiss_fftri(m_fplani, m_fpacked, cepOut); 
     839    } 
     840     
     841    float *getFloatTimeBuffer() { 
     842        if (!m_frb) m_frb = new float[m_size]; 
     843        return m_frb; 
     844    } 
     845 
     846    double *getDoubleTimeBuffer() { 
     847        if (!m_drb) m_drb = new double[m_size]; 
     848        return m_drb; 
     849    } 
     850 
     851private: 
     852    const int m_size; 
     853    float* m_frb; 
     854    double* m_drb; 
     855    kiss_fftr_cfg m_fplanf; 
     856    kiss_fftr_cfg m_fplani; 
     857    kiss_fft_scalar *m_fbuf; 
     858    kiss_fft_cpx *m_fpacked; 
     859}; 
     860 
     861#endif /* USE_KISSFFT */ 
     862 
     863#ifdef USE_BUILTIN_FFT 
    479864 
    480865class D_Cross : public FFTImpl 
    481866{ 
    482867public: 
    483     D_Cross(unsigned int size) : m_size(size), m_table(0), m_frb(0), m_drb(0) { 
     868    D_Cross(int size) : m_size(size), m_table(0), m_frb(0), m_drb(0) { 
    484869         
    485870        m_a = new double[size]; 
     
    490875        m_table = new int[m_size]; 
    491876     
    492         unsigned int bits; 
    493         unsigned int i, j, k, m; 
     877        int bits; 
     878        int i, j, k, m; 
    494879 
    495880        for (i = 0; ; ++i) { 
     
    526911    void initDouble() { } 
    527912 
    528     void forward(double *realIn, double *realOut, double *imagOut) { 
     913    void forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) { 
    529914        basefft(false, realIn, 0, m_c, m_d); 
    530         for (size_t i = 0; i <= m_size/2; ++i) realOut[i] = m_c[i]; 
    531         for (size_t i = 0; i <= m_size/2; ++i) imagOut[i] = m_d[i]; 
    532     } 
    533  
    534     void forwardPolar(double *realIn, double *magOut, double *phaseOut) { 
     915        const int hs = m_size/2; 
     916        for (int i = 0; i <= hs; ++i) realOut[i] = m_c[i]; 
     917        if (imagOut) { 
     918            for (int i = 0; i <= hs; ++i) imagOut[i] = m_d[i]; 
     919        } 
     920    } 
     921 
     922    void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) { 
    535923        basefft(false, realIn, 0, m_c, m_d); 
    536         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     924        const int hs = m_size/2; 
     925        for (int i = 0; i <= hs; ++i) { 
    537926            magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]); 
    538927            phaseOut[i] = atan2(m_d[i], m_c[i]) ; 
     
    540929    } 
    541930 
    542     void forwardMagnitude(double *realIn, double *magOut) { 
     931    void forwardMagnitude(const double *R__ realIn, double *R__ magOut) { 
    543932        basefft(false, realIn, 0, m_c, m_d); 
    544         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     933        const int hs = m_size/2; 
     934        for (int i = 0; i <= hs; ++i) { 
    545935            magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]); 
    546936        } 
    547937    } 
    548938 
    549     void forward(float *realIn, float *realOut, float *imagOut) { 
    550         for (size_t i = 0; i < m_size; ++i) m_a[i] = realIn[i]; 
     939    void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) { 
     940        for (int i = 0; i < m_size; ++i) m_a[i] = realIn[i]; 
    551941        basefft(false, m_a, 0, m_c, m_d); 
    552         for (size_t i = 0; i <= m_size/2; ++i) realOut[i] = m_c[i]; 
    553         for (size_t i = 0; i <= m_size/2; ++i) imagOut[i] = m_d[i]; 
    554     } 
    555  
    556     void forwardPolar(float *realIn, float *magOut, float *phaseOut) { 
    557         for (size_t i = 0; i < m_size; ++i) m_a[i] = realIn[i]; 
     942        const int hs = m_size/2; 
     943        for (int i = 0; i <= hs; ++i) realOut[i] = m_c[i]; 
     944        if (imagOut) { 
     945            for (int i = 0; i <= hs; ++i) imagOut[i] = m_d[i]; 
     946        } 
     947    } 
     948 
     949    void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) { 
     950        for (int i = 0; i < m_size; ++i) m_a[i] = realIn[i]; 
    558951        basefft(false, m_a, 0, m_c, m_d); 
    559         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     952        const int hs = m_size/2; 
     953        for (int i = 0; i <= hs; ++i) { 
    560954            magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]); 
    561955            phaseOut[i] = atan2(m_d[i], m_c[i]) ; 
     
    563957    } 
    564958 
    565     void forwardMagnitude(float *realIn, float *magOut) { 
    566         for (size_t i = 0; i < m_size; ++i) m_a[i] = realIn[i]; 
     959    void forwardMagnitude(const float *R__ realIn, float *R__ magOut) { 
     960        for (int i = 0; i < m_size; ++i) m_a[i] = realIn[i]; 
    567961        basefft(false, m_a, 0, m_c, m_d); 
    568         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     962        const int hs = m_size/2; 
     963        for (int i = 0; i <= hs; ++i) { 
    569964            magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]); 
    570965        } 
    571966    } 
    572967 
    573     void inverse(double *realIn, double *imagIn, double *realOut) { 
    574         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     968    void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) { 
     969        const int hs = m_size/2; 
     970        for (int i = 0; i <= hs; ++i) { 
    575971            double real = realIn[i]; 
    576972            double imag = imagIn[i]; 
     
    585981    } 
    586982 
    587     void inversePolar(double *magIn, double *phaseIn, double *realOut) { 
    588         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     983    void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) { 
     984        const int hs = m_size/2; 
     985        for (int i = 0; i <= hs; ++i) { 
    589986            double real = magIn[i] * cos(phaseIn[i]); 
    590987            double imag = magIn[i] * sin(phaseIn[i]); 
     
    599996    } 
    600997 
    601     void inverse(float *realIn, float *imagIn, float *realOut) { 
    602         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     998    void inverseCepstral(const double *R__ magIn, double *R__ cepOut) { 
     999        const int hs = m_size/2; 
     1000        for (int i = 0; i <= hs; ++i) { 
     1001            double real = log(magIn[i] + 0.000001); 
     1002            m_a[i] = real; 
     1003            m_b[i] = 0.0; 
     1004            if (i > 0) { 
     1005                m_a[m_size-i] = real; 
     1006                m_b[m_size-i] = 0.0; 
     1007            } 
     1008        } 
     1009        basefft(true, m_a, m_b, cepOut, m_d); 
     1010    } 
     1011 
     1012    void inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut) { 
     1013        const int hs = m_size/2; 
     1014        for (int i = 0; i <= hs; ++i) { 
    6031015            float real = realIn[i]; 
    6041016            float imag = imagIn[i]; 
     
    6111023        } 
    6121024        basefft(true, m_a, m_b, m_c, m_d); 
    613         for (unsigned int i = 0; i < m_size; ++i) realOut[i] = m_c[i]; 
    614     } 
    615  
    616     void inversePolar(float *magIn, float *phaseIn, float *realOut) { 
    617         for (unsigned int i = 0; i <= m_size/2; ++i) { 
     1025        for (int i = 0; i < m_size; ++i) realOut[i] = m_c[i]; 
     1026    } 
     1027 
     1028    void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) { 
     1029        const int hs = m_size/2; 
     1030        for (int i = 0; i <= hs; ++i) { 
    6181031            float real = magIn[i] * cosf(phaseIn[i]); 
    6191032            float imag = magIn[i] * sinf(phaseIn[i]); 
     
    6261039        } 
    6271040        basefft(true, m_a, m_b, m_c, m_d); 
    628         for (unsigned int i = 0; i < m_size; ++i) realOut[i] = m_c[i]; 
     1041        for (int i = 0; i < m_size; ++i) realOut[i] = m_c[i]; 
     1042    } 
     1043 
     1044    void inverseCepstral(const float *R__ magIn, float *R__ cepOut) { 
     1045        const int hs = m_size/2; 
     1046        for (int i = 0; i <= hs; ++i) { 
     1047            float real = logf(magIn[i] + 0.000001); 
     1048            m_a[i] = real; 
     1049            m_b[i] = 0.0; 
     1050            if (i > 0) { 
     1051                m_a[m_size-i] = real; 
     1052                m_b[m_size-i] = 0.0; 
     1053            } 
     1054        } 
     1055        basefft(true, m_a, m_b, m_c, m_d); 
     1056        for (int i = 0; i < m_size; ++i) cepOut[i] = m_c[i]; 
    6291057    } 
    6301058 
     
    6401068 
    6411069private: 
    642     unsigned int m_size; 
     1070    const int m_size; 
    6431071    int *m_table; 
    6441072    float *m_frb; 
     
    6481076    double *m_c; 
    6491077    double *m_d; 
    650     void basefft(bool inverse, double *ri, double *ii, double *ro, double *io); 
     1078    void basefft(bool inverse, const double *R__ ri, const double *R__ ii, double *R__ ro, double *R__ io); 
    6511079}; 
    6521080 
    6531081void 
    654 D_Cross::basefft(bool inverse, double *ri, double *ii, double *ro, double *io) 
     1082D_Cross::basefft(bool inverse, const double *R__ ri, const double *R__ ii, double *R__ ro, double *R__ io) 
    6551083{ 
    6561084    if (!ri || !ro || !io) return; 
    6571085 
    658     unsigned int i, j, k, m; 
    659     unsigned int blockSize, blockEnd; 
     1086    int i, j, k, m; 
     1087    int blockSize, blockEnd; 
    6601088 
    6611089    double tr, ti; 
     
    6641092    if (inverse) angle = -angle; 
    6651093 
    666     const unsigned int n = m_size; 
     1094    const int n = m_size; 
    6671095 
    6681096    if (ii) { 
    6691097        for (i = 0; i < n; ++i) { 
    6701098            ro[m_table[i]] = ri[i]; 
     1099        } 
     1100        for (i = 0; i < n; ++i) { 
    6711101            io[m_table[i]] = ii[i]; 
    6721102        } 
     
    6741104        for (i = 0; i < n; ++i) { 
    6751105            ro[m_table[i]] = ri[i]; 
     1106        } 
     1107        for (i = 0; i < n; ++i) { 
    6761108            io[m_table[i]] = 0.0; 
    6771109        } 
     
    7371169} 
    7381170 
     1171#endif /* USE_BUILTIN_FFT */ 
     1172 
     1173} /* end namespace FFTs */ 
     1174 
    7391175int 
    7401176FFT::m_method = -1; 
    7411177 
    742 FFT::FFT(unsigned int size) 
    743 { 
    744     if (size < 2) throw InvalidSize; 
    745     if (size & (size-1)) throw InvalidSize; 
     1178FFT::FFT(int size, int debugLevel) 
     1179{ 
     1180    if ((size < 2) || 
     1181        (size & (size-1))) { 
     1182        std::cerr << "FFT::FFT(" << size << "): power-of-two sizes only supported, minimum size 2" << std::endl; 
     1183        throw InvalidSize; 
     1184    } 
    7461185 
    7471186    if (m_method == -1) { 
     1187        m_method = 3; 
     1188#ifdef USE_KISSFFT 
     1189        m_method = 2; 
     1190#endif 
     1191#ifdef HAVE_FFTW3 
    7481192        m_method = 1; 
     1193#endif 
    7491194    } 
    7501195 
     
    7521197 
    7531198    case 0: 
    754         d = new D_Cross(size); 
     1199        std::cerr << "FFT::FFT(" << size << "): WARNING: Selected implemention not available" << std::endl; 
     1200#ifdef USE_BUILTIN_FFT 
     1201        d = new FFTs::D_Cross(size); 
     1202#else 
     1203        std::cerr << "FFT::FFT(" << size << "): ERROR: Fallback implementation not available!" << std::endl; 
     1204        abort(); 
     1205#endif 
    7551206        break; 
    7561207 
    7571208    case 1: 
    758 //        std::cerr << "FFT::FFT(" << size << "): using FFTW3 implementation" 
    759 //                  << std::endl; 
    760         d = new D_FFTW(size); 
     1209#ifdef HAVE_FFTW3 
     1210        if (debugLevel > 0) { 
     1211            std::cerr << "FFT::FFT(" << size << "): using FFTW3 implementation" 
     1212                      << std::endl; 
     1213        } 
     1214        d = new FFTs::D_FFTW(size); 
     1215#else 
     1216        std::cerr << "FFT::FFT(" << size << "): WARNING: Selected implemention not available" << std::endl; 
     1217#ifdef USE_BUILTIN_FFT 
     1218        d = new FFTs::D_Cross(size); 
     1219#else 
     1220        std::cerr << "FFT::FFT(" << size << "): ERROR: Fallback implementation not available!" << std::endl; 
     1221        abort(); 
     1222#endif 
     1223#endif 
    7611224        break; 
    7621225 
     1226    case 2: 
     1227#ifdef USE_KISSFFT 
     1228        if (debugLevel > 0) { 
     1229            std::cerr << "FFT::FFT(" << size << "): using KISSFFT implementation" 
     1230                      << std::endl; 
     1231        } 
     1232        d = new FFTs::D_KISSFFT(size); 
     1233#else 
     1234        std::cerr << "FFT::FFT(" << size << "): WARNING: Selected implemention not available" << std::endl; 
     1235#ifdef USE_BUILTIN_FFT 
     1236        d = new FFTs::D_Cross(size); 
     1237#else 
     1238        std::cerr << "FFT::FFT(" << size << "): ERROR: Fallback implementation not available!" << std::endl; 
     1239        abort(); 
     1240#endif 
     1241#endif 
     1242        break; 
     1243 
    7631244    default: 
    764         std::cerr << "FFT::FFT(" << size << "): WARNING: using slow built-in implementation" 
    765                   << std::endl; 
    766         d = new D_Cross(size); 
     1245#ifdef USE_BUILTIN_FFT 
     1246        std::cerr << "FFT::FFT(" << size << "): WARNING: using slow built-in implementation" << std::endl; 
     1247        d = new FFTs::D_Cross(size); 
     1248#else 
     1249        std::cerr << "FFT::FFT(" << size << "): ERROR: Fallback implementation not available!" << std::endl; 
     1250        abort(); 
     1251#endif 
    7671252        break; 
    7681253    } 
     
    7751260 
    7761261void 
    777 FFT::forward(double *realIn, double *realOut, double *imagOut) 
     1262FFT::forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) 
    7781263{ 
    7791264    d->forward(realIn, realOut, imagOut); 
     
    7811266 
    7821267void 
    783 FFT::forwardPolar(double *realIn, double *magOut, double *phaseOut) 
     1268FFT::forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) 
    7841269{ 
    7851270    d->forwardPolar(realIn, magOut, phaseOut); 
     
    7871272 
    7881273void 
    789 FFT::forwardMagnitude(double *realIn, double *magOut) 
     1274FFT::forwardMagnitude(const double *R__ realIn, double *R__ magOut) 
    7901275{ 
    7911276    d->forwardMagnitude(realIn, magOut); 
     
    7931278 
    7941279void 
    795 FFT::forward(float *realIn, float *realOut, float *imagOut) 
     1280FFT::forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) 
    7961281{ 
    7971282    d->forward(realIn, realOut, imagOut); 
     
    7991284 
    8001285void 
    801 FFT::forwardPolar(float *realIn, float *magOut, float *phaseOut) 
     1286FFT::forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) 
    8021287{ 
    8031288    d->forwardPolar(realIn, magOut, phaseOut); 
     
    8051290 
    8061291void 
    807 FFT::forwardMagnitude(float *realIn, float *magOut) 
     1292FFT::forwardMagnitude(const float *R__ realIn, float *R__ magOut) 
    8081293{ 
    8091294    d->forwardMagnitude(realIn, magOut); 
     
    8111296 
    8121297void 
    813 FFT::inverse(double *realIn, double *imagIn, double *realOut) 
     1298FFT::inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) 
    8141299{ 
    8151300    d->inverse(realIn, imagIn, realOut); 
     
    8171302 
    8181303void 
    819 FFT::inversePolar(double *magIn, double *phaseIn, double *realOut) 
     1304FFT::inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) 
    8201305{ 
    8211306    d->inversePolar(magIn, phaseIn, realOut); 
     
    8231308 
    8241309void 
    825 FFT::inverse(float *realIn, float *imagIn, float *realOut) 
     1310FFT::inverseCepstral(const double *R__ magIn, double *R__ cepOut) 
     1311{ 
     1312    d->inverseCepstral(magIn, cepOut); 
     1313} 
     1314 
     1315void 
     1316FFT::inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut) 
    8261317{ 
    8271318    d->inverse(realIn, imagIn, realOut); 
     
    8291320 
    8301321void 
    831 FFT::inversePolar(float *magIn, float *phaseIn, float *realOut) 
     1322FFT::inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) 
    8321323{ 
    8331324    d->inversePolar(magIn, phaseIn, realOut); 
     1325} 
     1326 
     1327void 
     1328FFT::inverseCepstral(const float *R__ magIn, float *R__ cepOut) 
     1329{ 
     1330    d->inverseCepstral(magIn, cepOut); 
    8341331} 
    8351332 
  • trunk/rubberband/src/FFT.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1515#ifndef _RUBBERBAND_FFT_H_ 
    1616#define _RUBBERBAND_FFT_H_ 
     17 
     18#include "sysutils.h" 
    1719 
    1820namespace RubberBand { 
     
    3739    enum Exception { InvalidSize }; 
    3840 
    39     FFT(unsigned int size); // may throw InvalidSize 
     41    FFT(int size, int debugLevel = 0); // may throw InvalidSize 
    4042    ~FFT(); 
    4143 
    42     void forward(double *realIn, double *realOut, double *imagOut); 
    43     void forwardPolar(double *realIn, double *magOut, double *phaseOut); 
    44     void forwardMagnitude(double *realIn, double *magOut); 
     44    void forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut); 
     45    void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut); 
     46    void forwardMagnitude(const double *R__ realIn, double *R__ magOut); 
    4547 
    46     void forward(float *realIn, float *realOut, float *imagOut); 
    47     void forwardPolar(float *realIn, float *magOut, float *phaseOut); 
    48     void forwardMagnitude(float *realIn, float *magOut); 
     48    void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut); 
     49    void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut); 
     50    void forwardMagnitude(const float *R__ realIn, float *R__ magOut); 
    4951 
    50     void inverse(double *realIn, double *imagIn, double *realOut); 
    51     void inversePolar(double *magIn, double *phaseIn, double *realOut); 
     52    void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut); 
     53    void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut); 
     54    void inverseCepstral(const double *R__ magIn, double *R__ cepOut); 
    5255 
    53     void inverse(float *realIn, float *imagIn, float *realOut); 
    54     void inversePolar(float *magIn, float *phaseIn, float *realOut); 
     56    void inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut); 
     57    void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut); 
     58    void inverseCepstral(const float *R__ magIn, float *R__ cepOut); 
    5559 
    5660    // Calling one or both of these is optional -- if neither is 
  • trunk/rubberband/src/HighFrequencyAudioCurve.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    3939 
    4040float 
    41 HighFrequencyAudioCurve::process(float *mag, size_t increment) 
     41HighFrequencyAudioCurve::process(const float *R__ mag, size_t increment) 
    4242{ 
    4343    float result = 0.0; 
    4444 
    45     for (size_t n = 0; n <= m_windowSize / 2; ++n) { 
    46         result += mag[n] * n; 
     45    const int sz = m_windowSize / 2; 
     46 
     47    for (int n = 0; n <= sz; ++n) { 
     48        result = result + mag[n] * n; 
    4749    } 
    4850 
  • trunk/rubberband/src/HighFrequencyAudioCurve.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    3131    virtual void setWindowSize(size_t newSize); 
    3232 
    33     virtual float process(float *mag, size_t increment); 
     33    virtual float process(const float *R__ mag, size_t increment); 
    3434    virtual void reset(); 
    3535}; 
  • trunk/rubberband/src/Makefile.am

    r234 r267  
    1 AM_CPPFLAGS= -DFFTW_DOUBLE_ONLY $(SRC_CFLAGS) $(FFTW_CFLAGS) $(OPTFLAGS) -I$(srcdir)/../include 
     1AM_CPPFLAGS= -DHAVE_FFTW3 -DFFTW_DOUBLE_ONLY $(SRC_CFLAGS) $(FFTW_CFLAGS) $(OPTFLAGS) -I$(srcdir)/../include 
    22 
    33 
     
    99 
    1010librubberband_la_SOURCES = \ 
     11        AudioCurve.cpp \ 
    1112        AudioCurve.h \ 
     13        ConstantAudioCurve.cpp \ 
    1214        ConstantAudioCurve.h \ 
     15        FFT.cpp \ 
    1316        FFT.h \ 
     17        HighFrequencyAudioCurve.cpp \ 
    1418        HighFrequencyAudioCurve.h \ 
     19        PercussiveAudioCurve.cpp \ 
    1520        PercussiveAudioCurve.h \ 
     21        HighFrequencyAudioCurve.h \ 
     22        Profiler.cpp \ 
     23        Profiler.h \ 
     24        Resampler.cpp \ 
    1625        Resampler.h \ 
    1726        RingBuffer.h \ 
     27        rubberband-c.cpp \ 
     28        RubberBandStretcher.cpp \ 
    1829        Scavenger.h \ 
     30        SilentAudioCurve.cpp \ 
     31        SilentAudioCurve.h \ 
     32        SpectralDifferenceAudioCurve.cpp \ 
    1933        SpectralDifferenceAudioCurve.h \ 
     34        StretchCalculator.cpp \ 
    2035        StretchCalculator.h \ 
     36        StretcherChannelData.h \ 
     37        StretcherImpl.cpp \ 
    2138        StretcherImpl.h \ 
    22         StretcherChannelData.h \ 
    23         Thread.h \ 
    24         Window.h \ 
    25         sysutils.h \ 
    26         RubberBandStretcher.cpp \ 
    27         ConstantAudioCurve.cpp \ 
    28         HighFrequencyAudioCurve.cpp \ 
    29         PercussiveAudioCurve.cpp \ 
    30         AudioCurve.cpp \ 
    31         Resampler.cpp \ 
    32         SpectralDifferenceAudioCurve.cpp \ 
    33         StretchCalculator.cpp \ 
    34         StretcherImpl.cpp \ 
    3539        StretcherProcess.cpp \ 
    3640        StretcherChannelData.cpp \ 
    37         FFT.cpp \ 
    3841        Thread.cpp \ 
    39         sysutils.cpp 
     42        Thread.h \ 
     43        Window.cpp \ 
     44        Window.h \ 
     45        sysutils.cpp \ 
     46        sysutils.h 
     47 
     48 
     49 
     50 
     51 
     52 
     53 
     54 
     55 
     56 
     57 
     58 
     59 
     60 
     61 
     62 
     63 
     64 
     65 
  • trunk/rubberband/src/Makefile.in

    r257 r267  
    5151LTLIBRARIES = $(lib_LTLIBRARIES) 
    5252librubberband_la_LIBADD = 
    53 am_librubberband_la_OBJECTS = RubberBandStretcher.lo \ 
    54         ConstantAudioCurve.lo HighFrequencyAudioCurve.lo \ 
    55         PercussiveAudioCurve.lo AudioCurve.lo Resampler.lo \ 
     53am_librubberband_la_OBJECTS = AudioCurve.lo ConstantAudioCurve.lo \ 
     54        FFT.lo HighFrequencyAudioCurve.lo PercussiveAudioCurve.lo \ 
     55        Profiler.lo Resampler.lo rubberband-c.lo \ 
     56        RubberBandStretcher.lo SilentAudioCurve.lo \ 
    5657        SpectralDifferenceAudioCurve.lo StretchCalculator.lo \ 
    5758        StretcherImpl.lo StretcherProcess.lo StretcherChannelData.lo \ 
    58         FFT.lo Thread.lo sysutils.lo 
     59        Thread.lo Window.lo sysutils.lo 
    5960librubberband_la_OBJECTS = $(am_librubberband_la_OBJECTS) 
    6061librubberband_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ 
     
    200201top_builddir = @top_builddir@ 
    201202top_srcdir = @top_srcdir@ 
    202 AM_CPPFLAGS = -DFFTW_DOUBLE_ONLY $(SRC_CFLAGS) $(FFTW_CFLAGS) $(OPTFLAGS) -I$(srcdir)/../include 
     203AM_CPPFLAGS = -DHAVE_FFTW3 -DFFTW_DOUBLE_ONLY $(SRC_CFLAGS) $(FFTW_CFLAGS) $(OPTFLAGS) -I$(srcdir)/../include 
    203204lib_LTLIBRARIES = librubberband.la 
    204205librubberband_la_LDFLAGS = -lpthread 
    205206librubberband_la_SOURCES = \ 
     207        AudioCurve.cpp \ 
    206208        AudioCurve.h \ 
     209        ConstantAudioCurve.cpp \ 
    207210        ConstantAudioCurve.h \ 
     211        FFT.cpp \ 
    208212        FFT.h \ 
     213        HighFrequencyAudioCurve.cpp \ 
    209214        HighFrequencyAudioCurve.h \ 
     215        PercussiveAudioCurve.cpp \ 
    210216        PercussiveAudioCurve.h \ 
     217        HighFrequencyAudioCurve.h \ 
     218        Profiler.cpp \ 
     219        Profiler.h \ 
     220        Resampler.cpp \ 
    211221        Resampler.h \ 
    212222        RingBuffer.h \ 
     223        rubberband-c.cpp \ 
     224        RubberBandStretcher.cpp \ 
    213225        Scavenger.h \ 
     226        SilentAudioCurve.cpp \ 
     227        SilentAudioCurve.h \ 
     228        SpectralDifferenceAudioCurve.cpp \ 
    214229        SpectralDifferenceAudioCurve.h \ 
     230        StretchCalculator.cpp \ 
    215231        StretchCalculator.h \ 
     232        StretcherChannelData.h \ 
     233        StretcherImpl.cpp \ 
    216234        StretcherImpl.h \ 
    217         StretcherChannelData.h \ 
    218         Thread.h \ 
    219         Window.h \ 
    220         sysutils.h \ 
    221         RubberBandStretcher.cpp \ 
    222         ConstantAudioCurve.cpp \ 
    223         HighFrequencyAudioCurve.cpp \ 
    224         PercussiveAudioCurve.cpp \ 
    225         AudioCurve.cpp \ 
    226         Resampler.cpp \ 
    227         SpectralDifferenceAudioCurve.cpp \ 
    228         StretchCalculator.cpp \ 
    229         StretcherImpl.cpp \ 
    230235        StretcherProcess.cpp \ 
    231236        StretcherChannelData.cpp \ 
    232         FFT.cpp \ 
    233237        Thread.cpp \ 
    234         sysutils.cpp 
     238        Thread.h \ 
     239        Window.cpp \ 
     240        Window.h \ 
     241        sysutils.cpp \ 
     242        sysutils.h 
    235243 
    236244all: all-am 
     
    308316@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HighFrequencyAudioCurve.Plo@am__quote@ 
    309317@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PercussiveAudioCurve.Plo@am__quote@ 
     318@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Profiler.Plo@am__quote@ 
    310319@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Resampler.Plo@am__quote@ 
    311320@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RubberBandStretcher.Plo@am__quote@ 
     321@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SilentAudioCurve.Plo@am__quote@ 
    312322@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SpectralDifferenceAudioCurve.Plo@am__quote@ 
    313323@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StretchCalculator.Plo@am__quote@ 
     
    316326@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StretcherProcess.Plo@am__quote@ 
    317327@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Thread.Plo@am__quote@ 
     328@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Window.Plo@am__quote@ 
     329@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rubberband-c.Plo@am__quote@ 
    318330@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysutils.Plo@am__quote@ 
    319331 
  • trunk/rubberband/src/PercussiveAudioCurve.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1515#include "PercussiveAudioCurve.h" 
    1616 
     17#include "Profiler.h" 
     18 
    1719#include <cmath> 
     20 
    1821 
    1922namespace RubberBand 
     
    2326    AudioCurve(sampleRate, windowSize) 
    2427{ 
    25     m_prevMag = new double[m_windowSize/2 + 1]; 
     28    m_prevMag = new float[m_windowSize/2 + 1]; 
    2629 
    2730    for (size_t i = 0; i <= m_windowSize/2; ++i) { 
     
    4649PercussiveAudioCurve::setWindowSize(size_t newSize) 
    4750{ 
     51    m_windowSize = newSize; 
     52 
    4853    delete[] m_prevMag; 
    49     m_windowSize = newSize; 
    50      
    51     m_prevMag = new double[m_windowSize/2 + 1]; 
     54    m_prevMag = new float[m_windowSize/2 + 1]; 
    5255 
    5356    reset(); 
     
    5558 
    5659float 
    57 PercussiveAudioCurve::process(float *mag, size_t increment) 
     60PercussiveAudioCurve::process(const float *R__ mag, size_t increment) 
    5861{ 
    59     static float threshold = pow(10, 0.3); 
    60     static float zeroThresh = pow(10, -16); 
     62    static float threshold = powf(10.f, 0.15f); // 3dB rise in square of magnitude 
     63    static float zeroThresh = powf(10.f, -8); 
    6164 
    6265    size_t count = 0; 
    6366    size_t nonZeroCount = 0; 
    6467 
    65     for (size_t n = 1; n <= m_windowSize / 2; ++n) { 
    66         float sqrmag = mag[n] * mag[n]; 
    67         bool above = ((sqrmag / m_prevMag[n]) >= threshold); 
     68    const int sz = m_windowSize / 2; 
     69 
     70    for (int n = 1; n <= sz; ++n) { 
     71        bool above = ((mag[n] / m_prevMag[n]) >= threshold); 
    6872        if (above) ++count; 
    69         if (sqrmag > zeroThresh) ++nonZeroCount; 
    70         m_prevMag[n] = sqrmag; 
     73        if (mag[n] > zeroThresh) ++nonZeroCount; 
     74    } 
     75 
     76    for (int n = 1; n <= sz; ++n) { 
     77        m_prevMag[n] = mag[n]; 
     78    } 
     79 
     80    if (nonZeroCount == 0) return 0; 
     81    else return float(count) / float(nonZeroCount); 
     82} 
     83 
     84float 
     85PercussiveAudioCurve::process(const double *R__ mag, size_t increment) 
     86{ 
     87    Profiler profiler("PercussiveAudioCurve::process"); 
     88 
     89    static double threshold = pow(10.0, 0.15); // 3dB rise in square of magnitude 
     90    static double zeroThresh = pow(10.0, -8); 
     91 
     92    size_t count = 0; 
     93    size_t nonZeroCount = 0; 
     94 
     95    const int sz = m_windowSize / 2; 
     96 
     97    for (int n = 1; n <= sz; ++n) { 
     98        bool above = ((mag[n] / m_prevMag[n]) >= threshold); 
     99        if (above) ++count; 
     100        if (mag[n] > zeroThresh) ++nonZeroCount; 
     101    } 
     102 
     103    for (int n = 1; n <= sz; ++n) { 
     104        m_prevMag[n] = mag[n]; 
    71105    } 
    72106 
  • trunk/rubberband/src/PercussiveAudioCurve.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    3030    virtual void setWindowSize(size_t newSize); 
    3131 
    32     virtual float process(float *mag, size_t increment); 
     32    virtual float process(const float *R__ mag, size_t increment); 
     33    virtual float process(const double *R__ mag, size_t increment); 
    3334    virtual void reset(); 
    3435 
    3536protected: 
    36     double *m_prevMag; 
     37    float *R__ m_prevMag; 
    3738}; 
    3839 
  • trunk/rubberband/src/Resampler.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1515#include "Resampler.h" 
    1616 
     17#include "Profiler.h" 
     18 
    1719#include <cstdlib> 
    1820#include <cmath> 
     
    2325#include <samplerate.h> 
    2426 
     27 
     28 
    2529namespace RubberBand { 
    2630 
    27 class Resampler::D 
     31class ResamplerImpl 
    2832{ 
    2933public: 
    30     D(Quality quality, size_t channels, size_t maxBufferSize); 
    31     ~D(); 
    32  
    33     size_t resample(float **in, float **out, 
    34                     size_t incount, float ratio, bool final); 
     34    virtual ~ResamplerImpl() { } 
     35     
     36    virtual int resample(const float *const R__ *const R__ in,  
     37                         float *const R__ *const R__ out, 
     38                         int incount, 
     39                         float ratio, 
     40                         bool final) = 0; 
     41 
     42    virtual void reset() = 0; 
     43}; 
     44 
     45namespace Resamplers { 
     46 
     47 
     48 
     49class D_SRC : public ResamplerImpl 
     50{ 
     51public: 
     52    D_SRC(Resampler::Quality quality, int channels, int maxBufferSize, 
     53          int m_debugLevel); 
     54    ~D_SRC(); 
     55 
     56    int resample(const float *const R__ *const R__ in, 
     57                 float *const R__ *const R__ out, 
     58                 int incount, 
     59                 float ratio, 
     60                 bool final); 
    3561 
    3662    void reset(); 
     
    4066    float *m_iin; 
    4167    float *m_iout; 
    42     size_t m_channels; 
    43     size_t m_iinsize; 
    44     size_t m_ioutsize; 
     68    float m_lastRatio; 
     69    int m_channels; 
     70    int m_iinsize; 
     71    int m_ioutsize; 
     72    int m_debugLevel; 
    4573}; 
    4674 
    47 Resampler::D::D(Quality quality, size_t channels, size_t maxBufferSize) : 
     75D_SRC::D_SRC(Resampler::Quality quality, int channels, int maxBufferSize, 
     76             int debugLevel) : 
    4877    m_src(0), 
    4978    m_iin(0), 
    5079    m_iout(0), 
     80    m_lastRatio(1.f), 
    5181    m_channels(channels), 
    5282    m_iinsize(0), 
    53     m_ioutsize(0) 
    54 { 
    55 //    std::cerr << "Resampler::Resampler: using libsamplerate implementation" 
    56 //              << std::endl; 
     83    m_ioutsize(0), 
     84    m_debugLevel(debugLevel) 
     85{ 
     86    if (m_debugLevel > 0) { 
     87        std::cerr << "Resampler::Resampler: using libsamplerate implementation" 
     88                  << std::endl; 
     89    } 
    5790 
    5891    int err = 0; 
    59     m_src = src_new(quality == Best ? SRC_SINC_BEST_QUALITY : 
    60                     quality == Fastest ? SRC_LINEAR : 
     92    m_src = src_new(quality == Resampler::Best ? SRC_SINC_BEST_QUALITY : 
     93                    quality == Resampler::Fastest ? SRC_LINEAR : 
    6194                    SRC_SINC_FASTEST, 
    6295                    channels, &err); 
    6396 
    64     //!!! check err, throw 
     97    if (err) { 
     98        std::cerr << "Resampler::Resampler: failed to create libsamplerate resampler: "  
     99                  << src_strerror(err) << std::endl; 
     100        throw Resampler::ImplementationError; //!!! of course, need to catch this! 
     101    } 
    65102 
    66103    if (maxBufferSize > 0 && m_channels > 1) { 
    67         //!!! alignment? 
    68104        m_iinsize = maxBufferSize * m_channels; 
    69105        m_ioutsize = maxBufferSize * m_channels * 2; 
    70         m_iin = (float *)malloc(m_iinsize * sizeof(float)); 
    71         m_iout = (float *)malloc(m_ioutsize * sizeof(float)); 
    72     } 
    73 } 
    74  
    75 Resampler::D::~D() 
     106        m_iin = allocFloat(m_iinsize); 
     107        m_iout = allocFloat(m_ioutsize); 
     108    } 
     109 
     110    reset(); 
     111} 
     112 
     113D_SRC::~D_SRC() 
    76114{ 
    77115    src_delete(m_src); 
     
    84122} 
    85123 
    86 size_t 
    87 Resampler::D::resample(float **in, float **out, size_t incount, float ratio, 
    88                        bool final) 
     124int 
     125D_SRC::resample(const float *const R__ *const R__ in, 
     126                float *const R__ *const R__ out, 
     127                int incount, 
     128                float ratio, 
     129                bool final) 
    89130{ 
    90131    SRC_DATA data; 
    91132 
    92     size_t outcount = lrintf(ceilf(incount * ratio)); 
     133    int outcount = lrintf(ceilf(incount * ratio)); 
    93134 
    94135    if (m_channels == 1) { 
    95         data.data_in = *in; 
     136        data.data_in = const_cast<float *>(*in); //!!!??? 
    96137        data.data_out = *out; 
    97138    } else { 
    98139        if (incount * m_channels > m_iinsize) { 
    99             m_iinsize = incount * m_channels; 
    100             m_iin = (float *)realloc(m_iin, m_iinsize * sizeof(float)); 
     140            m_iin = allocFloat(m_iin, m_iinsize); 
    101141        } 
    102142        if (outcount * m_channels > m_ioutsize) { 
    103             m_ioutsize = outcount * m_channels; 
    104             m_iout = (float *)realloc(m_iout, m_ioutsize * sizeof(float)); 
    105         } 
    106         for (size_t i = 0; i < incount; ++i) { 
    107             for (size_t c = 0; c < m_channels; ++c) { 
     143            m_iout = allocFloat(m_iout, m_ioutsize); 
     144        } 
     145        for (int i = 0; i < incount; ++i) { 
     146            for (int c = 0; c < m_channels; ++c) { 
    108147                m_iin[i * m_channels + c] = in[c][i]; 
    109148            } 
     
    118157    data.end_of_input = (final ? 1 : 0); 
    119158 
    120     src_process(m_src, &data); 
    121  
    122     //!!! check err, respond appropriately 
     159    int err = src_process(m_src, &data); 
     160 
     161    if (err) { 
     162        std::cerr << "Resampler::process: libsamplerate error: " 
     163                  << src_strerror(err) << std::endl; 
     164        throw Resampler::ImplementationError; //!!! of course, need to catch this! 
     165    } 
    123166 
    124167    if (m_channels > 1) { 
    125168        for (int i = 0; i < data.output_frames_gen; ++i) { 
    126             for (size_t c = 0; c < m_channels; ++c) { 
     169            for (int c = 0; c < m_channels; ++c) { 
    127170                out[c][i] = m_iout[i * m_channels + c]; 
    128171            } 
     
    130173    } 
    131174 
     175    m_lastRatio = ratio; 
     176 
    132177    return data.output_frames_gen; 
    133178} 
    134179 
    135180void 
    136 Resampler::D::reset() 
     181D_SRC::reset() 
    137182{ 
    138183    src_reset(m_src); 
    139184} 
    140185 
    141 } // end namespace 
    142  
    143  
    144 namespace RubberBand { 
    145  
    146 Resampler::Resampler(Quality quality, size_t channels, size_t maxBufferSize) 
    147 { 
    148     m_d = new D(quality, channels, maxBufferSize); 
     186 
     187 
     188} /* end namespace Resamplers */ 
     189 
     190Resampler::Resampler(Resampler::Quality quality, int channels, 
     191                     int maxBufferSize, int debugLevel) 
     192{ 
     193    m_method = -1; 
     194     
     195    switch (quality) { 
     196 
     197    case Resampler::Best: 
     198        m_method = 1; 
     199        break; 
     200 
     201    case Resampler::FastestTolerable: 
     202        m_method = 1; 
     203        break; 
     204 
     205    case Resampler::Fastest: 
     206        m_method = 1; 
     207        break; 
     208    } 
     209 
     210    if (m_method == -1) { 
     211        std::cerr << "Resampler::Resampler(" << quality << ", " << channels 
     212                  << ", " << maxBufferSize << "): No implementation available!" 
     213                  << std::endl; 
     214        abort(); 
     215    } 
     216 
     217    switch (m_method) { 
     218    case 0: 
     219        std::cerr << "Resampler::Resampler(" << quality << ", " << channels 
     220                  << ", " << maxBufferSize << "): No implementation available!" 
     221                  << std::endl; 
     222        abort(); 
     223        break; 
     224 
     225    case 1: 
     226        d = new Resamplers::D_SRC(quality, channels, maxBufferSize, debugLevel); 
     227        break; 
     228 
     229    case 2: 
     230        std::cerr << "Resampler::Resampler(" << quality << ", " << channels 
     231                  << ", " << maxBufferSize << "): No implementation available!" 
     232                  << std::endl; 
     233        abort(); 
     234        break; 
     235    } 
    149236} 
    150237 
    151238Resampler::~Resampler() 
    152239{ 
    153     delete m_d; 
    154 } 
    155  
    156 size_t  
    157 Resampler::resample(float **in, float **out, 
    158                     size_t incount, float ratio, bool final) 
    159 { 
    160     return m_d->resample(in, out, incount, ratio, final); 
     240    delete d; 
     241} 
     242 
     243int  
     244Resampler::resample(const float *const R__ *const R__ in, 
     245                    float *const R__ *const R__ out, 
     246                    int incount, float ratio, bool final) 
     247{ 
     248    Profiler profiler("Resampler::resample"); 
     249    return d->resample(in, out, incount, ratio, final); 
    161250} 
    162251 
     
    164253Resampler::reset() 
    165254{ 
    166     m_d->reset(); 
    167 } 
    168  
    169 } 
     255    d->reset(); 
     256} 
     257 
     258} 
  • trunk/rubberband/src/Resampler.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1818#include <sys/types.h> 
    1919 
     20#include "sysutils.h" 
     21 
    2022namespace RubberBand { 
     23 
     24class ResamplerImpl; 
    2125 
    2226class Resampler 
     
    2428public: 
    2529    enum Quality { Best, FastestTolerable, Fastest }; 
     30    enum Exception { ImplementationError }; 
    2631 
    2732    /** 
     
    3136     * resampler needs to reallocate its internal buffers. 
    3237     */ 
    33     Resampler(Quality quality, size_t channels, size_t maxBufferSize = 0); 
     38    Resampler(Quality quality, int channels, int maxBufferSize = 0, 
     39              int debugLevel = 0); 
    3440    ~Resampler(); 
    3541 
    36     size_t resample(float **in, float **out, 
    37                     size_t incount, float ratio, bool final = false); 
     42    int resample(const float *const R__ *const R__ in, 
     43                 float *const R__ *const R__ out, 
     44                 int incount, 
     45                 float ratio, 
     46                 bool final = false); 
    3847 
    3948    void reset(); 
    4049 
    4150protected: 
    42     class D; 
    43     D *m_d; 
     51    ResamplerImpl *d; 
     52    int m_method; 
    4453}; 
    4554 
  • trunk/rubberband/src/RingBuffer.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1818#include <sys/types.h> 
    1919 
     20#include <cstring> 
     21 
    2022#ifndef _WIN32 
    2123#include <sys/mman.h> 
     
    2325 
    2426#include "Scavenger.h" 
     27#include "Profiler.h" 
     28 
    2529 
    2630//#define DEBUG_RINGBUFFER 1 
     
    5862     * minus one. 
    5963     */ 
    60     RingBuffer(size_t n); 
     64    RingBuffer(int n); 
    6165 
    6266    virtual ~RingBuffer(); 
     
    6670     * (This is the argument n passed to the constructor.) 
    6771     */ 
    68     size_t getSize() const; 
     72    int getSize() const; 
    6973 
    7074    /** 
     
    7478     * delay.  Should be called from the write thread. 
    7579     */ 
    76     void resize(size_t newSize); 
     80    void resize(int newSize); 
    7781 
    7882    /** 
     
    8488     * size, the contents are undefined. 
    8589     */ 
    86     RingBuffer<T, N> *resized(size_t newSize, int R = 0) const; 
     90    RingBuffer<T, N> *resized(int newSize, int R = 0) const; 
    8791 
    8892    /** 
     
    102106     * samples. 
    103107     */ 
    104     size_t getReadSpace(int R = 0) const; 
     108    int getReadSpace(int R = 0) const; 
    105109 
    106110    /** 
    107111     * Return the amount of space available for writing, in samples. 
    108112     */ 
    109     size_t getWriteSpace() const; 
     113    int getWriteSpace() const; 
    110114 
    111115    /** 
     
    114118     * number of samples actually read. 
    115119     */ 
    116     size_t read(T *destination, size_t n, int R = 0); 
     120    int read(T *R__ destination, int n, int R = 0); 
    117121 
    118122    /** 
     
    122126     * read. 
    123127     */ 
    124     size_t readAdding(T *destination, size_t n, int R = 0); 
     128    int readAdding(T *R__ destination, int n, int R = 0); 
    125129 
    126130    /** 
     
    140144     * number of samples actually read. 
    141145     */ 
    142     size_t peek(T *destination, size_t n, int R = 0) const; 
     146    int peek(T *R__ destination, int n, int R = 0) const; 
    143147 
    144148    /** 
     
    156160     * discarding. 
    157161     */ 
    158     size_t skip(size_t n, int R = 0); 
     162    int skip(int n, int R = 0); 
    159163 
    160164    /** 
     
    163167     * the number of samples actually written. 
    164168     */ 
    165     size_t write(const T *source, size_t n); 
     169    int write(const T *source, int n); 
    166170 
    167171    /** 
     
    170174     * Returns the number of zeroes actually written. 
    171175     */ 
    172     size_t zero(size_t n); 
     176    int zero(int n); 
    173177 
    174178protected: 
    175     T               *m_buffer; 
    176     volatile size_t  m_writer; 
    177     volatile size_t  m_readers[N]; 
    178     size_t           m_size; 
     179    T *R__      m_buffer; 
     180    volatile int     m_writer; 
     181    volatile int     m_readers[N]; 
     182    int              m_size; 
    179183    bool             m_mlocked; 
    180184 
     
    190194 
    191195template <typename T, int N> 
    192 RingBuffer<T, N>::RingBuffer(size_t n) : 
     196RingBuffer<T, N>::RingBuffer(int n) : 
    193197    m_buffer(new T[n + 1]), 
    194198    m_writer(0), 
     
    221225 
    222226template <typename T, int N> 
    223 size_t 
     227int 
    224228RingBuffer<T, N>::getSize() const 
    225229{ 
     
    233237template <typename T, int N> 
    234238void 
    235 RingBuffer<T, N>::resize(size_t newSize) 
     239RingBuffer<T, N>::resize(int newSize) 
    236240{ 
    237241#ifdef DEBUG_RINGBUFFER 
     
    260264template <typename T, int N> 
    261265RingBuffer<T, N> * 
    262 RingBuffer<T, N>::resized(size_t newSize, int R) const 
     266RingBuffer<T, N>::resized(int newSize, int R) const 
    263267{ 
    264268    RingBuffer<T, N> *newBuffer = new RingBuffer<T, N>(newSize); 
    265269 
    266     size_t w = m_writer; 
    267     size_t r = m_readers[R]; 
     270    int w = m_writer; 
     271    int r = m_readers[R]; 
    268272 
    269273    while (r != w) { 
     
    298302 
    299303template <typename T, int N> 
    300 size_t 
     304int 
    301305RingBuffer<T, N>::getReadSpace(int R) const 
    302306{ 
    303     size_t writer = m_writer; 
    304     size_t reader = m_readers[R]; 
    305     size_t space; 
     307    int writer = m_writer; 
     308    int reader = m_readers[R]; 
     309    int space; 
    306310 
    307311#ifdef DEBUG_RINGBUFFER 
     
    321325 
    322326template <typename T, int N> 
    323 size_t 
     327int 
    324328RingBuffer<T, N>::getWriteSpace() const 
    325329{ 
    326     size_t space = 0; 
     330    int space = 0; 
    327331    for (int i = 0; i < N; ++i) { 
    328         size_t writer = m_writer; 
    329         size_t reader = m_readers[i]; 
    330         size_t here = (reader + m_size - writer - 1); 
     332        int writer = m_writer; 
     333        int reader = m_readers[i]; 
     334        int here = (reader + m_size - writer - 1); 
    331335        if (here >= m_size) here -= m_size; 
    332336        if (i == 0 || here < space) space = here; 
     
    334338 
    335339#ifdef DEBUG_RINGBUFFER 
    336     size_t rs(getReadSpace()), rp(m_readers[0]); 
     340    int rs(getReadSpace()), rp(m_readers[0]); 
    337341 
    338342    std::cerr << "RingBuffer: write space " << space << ", read space " 
     
    349353 
    350354template <typename T, int N> 
    351 size_t 
    352 RingBuffer<T, N>::read(T *destination, size_t n, int R) 
    353 { 
     355int 
     356RingBuffer<T, N>::read(T *R__ destination, int n, int R) 
     357{ 
     358    Profiler profiler("RingBuffer::read"); 
     359 
    354360#ifdef DEBUG_RINGBUFFER 
    355361    std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read(dest, " << n << ", " << R << ")" << std::endl; 
    356362#endif 
    357363 
    358     size_t available = getReadSpace(R); 
     364    int available = getReadSpace(R); 
    359365    if (n > available) { 
    360366#ifdef DEBUG_RINGBUFFER 
     
    362368                  << std::endl; 
    363369#endif 
    364         for (size_t i = available; i < n; ++i) { 
     370        for (int i = available; i < n; ++i) { 
    365371            destination[i] = 0; 
    366372        } 
     
    369375    if (n == 0) return n; 
    370376 
    371     size_t reader = m_readers[R]; 
    372     size_t here = m_size - reader; 
     377    int reader = m_readers[R]; 
     378    int here = m_size - reader; 
     379    T *const R__ bufbase = m_buffer + reader; 
    373380 
    374381    if (here >= n) { 
    375         for (size_t i = 0; i < n; ++i) { 
    376             destination[i] = (m_buffer + reader)[i]; 
     382        for (int i = 0; i < n; ++i) { 
     383            destination[i] = bufbase[i]; 
    377384        } 
    378385    } else { 
    379         for (size_t i = 0; i < here; ++i) { 
    380             destination[i] = (m_buffer + reader)[i]; 
    381         } 
    382         for (size_t i = 0; i < (n - here); ++i) { 
    383             destination[i + here] = m_buffer[i]; 
     386        for (int i = 0; i < here; ++i) { 
     387            destination[i] = bufbase[i]; 
     388        } 
     389        T *const R__ destbase = destination + here; 
     390        const int nh = n - here; 
     391        for (int i = 0; i < nh; ++i) { 
     392            destbase[i] = m_buffer[i]; 
    384393        } 
    385394    } 
     
    397406 
    398407template <typename T, int N> 
    399 size_t 
    400 RingBuffer<T, N>::readAdding(T *destination, size_t n, int R) 
    401 { 
     408int 
     409RingBuffer<T, N>::readAdding(T *R__ destination, int n, int R) 
     410{ 
     411    Profiler profiler("RingBuffer::readAdding"); 
     412 
    402413#ifdef DEBUG_RINGBUFFER 
    403414    std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readAdding(dest, " << n << ", " << R << ")" << std::endl; 
    404415#endif 
    405416 
    406     size_t available = getReadSpace(R); 
     417    int available = getReadSpace(R); 
    407418    if (n > available) { 
    408419#ifdef DEBUG_RINGBUFFER 
     
    414425    if (n == 0) return n; 
    415426 
    416     size_t reader = m_readers[R]; 
    417     size_t here = m_size - reader; 
     427    int reader = m_readers[R]; 
     428    int here = m_size - reader; 
     429    const T *const R__ bufbase = m_buffer + reader; 
    418430 
    419431    if (here >= n) { 
    420         for (size_t i = 0; i < n; ++i) { 
    421             destination[i] += (m_buffer + reader)[i]; 
     432        for (int i = 0; i < n; ++i) { 
     433            destination[i] += bufbase[i]; 
    422434        } 
    423435    } else { 
    424         for (size_t i = 0; i < here; ++i) { 
    425             destination[i] += (m_buffer + reader)[i]; 
     436        for (int i = 0; i < here; ++i) { 
     437            destination[i] += bufbase[i]; 
    426438        } 
    427         for (size_t i = 0; i < (n - here); ++i) { 
    428             destination[i + here] += m_buffer[i]; 
     439        T *const R__ destbase = destination + here; 
     440        const int nh = n - here; 
     441        for (int i = 0; i < nh; ++i) { 
     442            destbase[i] += m_buffer[i]; 
    429443        } 
    430444    } 
     
    451465        return 0; 
    452466    } 
    453     size_t reader = m_readers[R]; 
     467    int reader = m_readers[R]; 
    454468    T value = m_buffer[reader]; 
    455469    if (++reader == m_size) reader = 0; 
     
    459473 
    460474template <typename T, int N> 
    461 size_t 
    462 RingBuffer<T, N>::peek(T *destination, size_t n, int R) const 
    463 { 
     475int 
     476RingBuffer<T, N>::peek(T *R__ destination, int n, int R) const 
     477{ 
     478    Profiler profiler("RingBuffer::peek"); 
     479 
    464480#ifdef DEBUG_RINGBUFFER 
    465481    std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(dest, " << n << ", " << R << ")" << std::endl; 
    466482#endif 
    467483 
    468     size_t available = getReadSpace(R); 
     484    int available = getReadSpace(R); 
    469485    if (n > available) { 
    470486#ifdef DEBUG_RINGBUFFER 
     
    477493    if (n == 0) return n; 
    478494 
    479     size_t reader = m_readers[R]; 
    480     size_t here = m_size - reader; 
     495    int reader = m_readers[R]; 
     496    int here = m_size - reader; 
     497    const T *const R__ bufbase = m_buffer + reader; 
    481498 
    482499    if (here >= n) { 
    483         for (size_t i = 0; i < n; ++i) { 
    484             destination[i] = (m_buffer + reader)[i]; 
     500        for (int i = 0; i < n; ++i) { 
     501            destination[i] = bufbase[i]; 
    485502        } 
    486503    } else { 
    487         for (size_t i = 0; i < here; ++i) { 
    488             destination[i] = (m_buffer + reader)[i]; 
    489         } 
    490         for (size_t i = 0; i < (n - here); ++i) { 
    491             destination[i + here] = m_buffer[i]; 
     504        for (int i = 0; i < here; ++i) { 
     505            destination[i] = bufbase[i]; 
     506        } 
     507        T *const R__ destbase = destination + here; 
     508        const int nh = n - here; 
     509        for (int i = 0; i < nh; ++i) { 
     510            destbase[i] = m_buffer[i]; 
    492511        } 
    493512    } 
     
    520539 
    521540template <typename T, int N> 
    522 size_t 
    523 RingBuffer<T, N>::skip(size_t n, int R) 
     541int 
     542RingBuffer<T, N>::skip(int n, int R) 
    524543{ 
    525544#ifdef DEBUG_RINGBUFFER 
     
    527546#endif 
    528547 
    529     size_t available = getReadSpace(R); 
     548    int available = getReadSpace(R); 
    530549    if (n > available) { 
    531550#ifdef DEBUG_RINGBUFFER 
     
    537556    if (n == 0) return n; 
    538557 
    539     size_t reader = m_readers[R]; 
     558    int reader = m_readers[R]; 
    540559    reader += n; 
    541560    while (reader >= m_size) reader -= m_size; 
     
    545564 
    546565template <typename T, int N> 
    547 size_t 
    548 RingBuffer<T, N>::write(const T *source, size_t n) 
    549 { 
     566int 
     567RingBuffer<T, N>::write(const T *source, int n) 
     568{ 
     569    Profiler profiler("RingBuffer::write"); 
     570 
    550571#ifdef DEBUG_RINGBUFFER 
    551572    std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write(" << n << ")" << std::endl; 
    552573#endif 
    553574 
    554     size_t available = getWriteSpace(); 
     575    int available = getWriteSpace(); 
    555576    if (n > available) { 
    556577#ifdef DEBUG_RINGBUFFER 
     
    562583    if (n == 0) return n; 
    563584 
    564     size_t writer = m_writer; 
    565     size_t here = m_size - writer; 
     585    int writer = m_writer; 
     586    int here = m_size - writer; 
     587    T *const R__ bufbase = m_buffer + writer; 
     588 
    566589    if (here >= n) { 
    567         for (size_t i = 0; i < n; ++i) { 
    568             (m_buffer + writer)[i] = source[i]; 
     590        for (int i = 0; i < n; ++i) { 
     591            bufbase[i] = source[i]; 
    569592        } 
    570593    } else { 
    571         for (size_t i = 0; i < here; ++i) { 
    572             (m_buffer + writer)[i] = source[i]; 
    573         } 
    574         for (size_t i = 0; i < (n - here); ++i) { 
    575             m_buffer[i] = (source + here)[i]; 
     594        for (int i = 0; i < here; ++i) { 
     595            bufbase[i] = source[i]; 
     596        } 
     597        const int nh = n - here; 
     598        const T *const R__ srcbase = source + here; 
     599        T *const R__ buf = m_buffer; 
     600        for (int i = 0; i < nh; ++i) { 
     601            buf[i] = srcbase[i]; 
    576602        } 
    577603    } 
     
    589615 
    590616template <typename T, int N> 
    591 size_t 
    592 RingBuffer<T, N>::zero(size_t n) 
    593 { 
     617int 
     618RingBuffer<T, N>::zero(int n) 
     619{ 
     620    Profiler profiler("RingBuffer::zero"); 
     621 
    594622#ifdef DEBUG_RINGBUFFER 
    595623    std::cerr << "RingBuffer<T," << N << ">[" << this << "]::zero(" << n << ")" << std::endl; 
    596624#endif 
    597625 
    598     size_t available = getWriteSpace(); 
     626    int available = getWriteSpace(); 
    599627    if (n > available) { 
    600628#ifdef DEBUG_RINGBUFFER 
     
    606634    if (n == 0) return n; 
    607635 
    608     size_t writer = m_writer; 
    609     size_t here = m_size - writer; 
     636    int writer = m_writer; 
     637    int here = m_size - writer; 
     638    T *const R__ bufbase = m_buffer + writer; 
     639 
    610640    if (here >= n) { 
    611         for (size_t i = 0; i < n; ++i) { 
    612             (m_buffer + writer)[i] = 0; 
     641        for (int i = 0; i < n; ++i) { 
     642            bufbase[i] = 0; 
    613643        } 
    614644    } else { 
    615         for (size_t i = 0; i < here; ++i) { 
    616             (m_buffer + writer)[i] = 0; 
    617         } 
    618         for (size_t i = 0; i < (n - here); ++i) { 
     645        for (int i = 0; i < here; ++i) { 
     646            bufbase[i] = 0; 
     647        } 
     648        const int nh = n - here; 
     649        for (int i = 0; i < nh; ++i) { 
    619650            m_buffer[i] = 0; 
    620651        } 
     
    634665} 
    635666 
     667//#include "RingBuffer.cpp" 
     668 
    636669#endif // _RINGBUFFER_H_ 
  • trunk/rubberband/src/RubberBandStretcher.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    2323                                         double initialTimeRatio, 
    2424                                         double initialPitchScale) : 
    25     TimeStretcher(sampleRate, channels), 
    26     m_d(new Impl(this, sampleRate, channels, options, 
     25    m_d(new Impl(sampleRate, channels, options, 
    2726                 initialTimeRatio, initialPitchScale)) 
    2827{ 
     
    8382 
    8483void 
     84RubberBandStretcher::setFormantOption(Options options) 
     85{ 
     86    m_d->setFormantOption(options); 
     87} 
     88 
     89void 
     90RubberBandStretcher::setPitchOption(Options options) 
     91{ 
     92    m_d->setPitchOption(options); 
     93} 
     94 
     95void 
    8596RubberBandStretcher::setExpectedInputDuration(size_t samples)  
    8697{ 
  • trunk/rubberband/src/Scavenger.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1818#include <vector> 
    1919#include <list> 
     20#include <iostream> 
     21 
     22#ifndef WIN32 
    2023#include <sys/time.h> 
    21 #include <iostream> 
     24#endif 
    2225 
    2326#include "Thread.h" 
  • trunk/rubberband/src/SilentAudioCurve.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1313*/ 
    1414 
    15 #ifndef _HIGHFREQUENCY_AUDIO_CURVE_H_ 
    16 #define _HIGHFREQUENCY_AUDIO_CURVE_H_ 
     15#ifndef _SILENT_AUDIO_CURVE_H_ 
     16#define _SILENT_AUDIO_CURVE_H_ 
    1717 
    1818#include "AudioCurve.h" 
    19 #include "Window.h" 
    2019 
    2120namespace RubberBand 
    2221{ 
    2322 
    24 class HighFrequencyAudioCurve : public AudioCurve 
     23class SilentAudioCurve : public AudioCurve 
    2524{ 
    2625public: 
    27     HighFrequencyAudioCurve(size_t sampleRate, size_t windowSize); 
    28  
    29     virtual ~HighFrequencyAudioCurve(); 
     26    SilentAudioCurve(size_t sampleRate, size_t windowSize); 
     27    virtual ~SilentAudioCurve(); 
    3028 
    3129    virtual void setWindowSize(size_t newSize); 
    3230 
    33     virtual float process(float *mag, size_t increment); 
     31    virtual float process(const float *R__ mag, size_t increment); 
     32    virtual float process(const double *R__ mag, size_t increment); 
    3433    virtual void reset(); 
    3534}; 
  • trunk/rubberband/src/SpectralDifferenceAudioCurve.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    2121    AudioCurve(sampleRate, windowSize) 
    2222{ 
    23     m_prevMag = new double[m_windowSize/2 + 1]; 
     23    m_prevMag = new float[m_windowSize/2 + 1]; 
    2424 
    2525    for (size_t i = 0; i <= m_windowSize/2; ++i) { 
     
    4444SpectralDifferenceAudioCurve::setWindowSize(size_t newSize) 
    4545{ 
     46    delete[] m_prevMag; 
    4647    m_windowSize = newSize; 
     48     
     49    m_prevMag = new float[m_windowSize/2 + 1]; 
     50 
     51    reset(); 
    4752} 
    4853 
    4954float 
    50 SpectralDifferenceAudioCurve::process(float *mag, size_t increment) 
     55SpectralDifferenceAudioCurve::process(const float *R__ mag, size_t increment) 
    5156{ 
    5257    float result = 0.0; 
  • trunk/rubberband/src/SpectralDifferenceAudioCurve.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    3131    virtual void setWindowSize(size_t newSize); 
    3232 
    33     virtual float process(float *mag, size_t increment); 
     33    virtual float process(const float *R__ mag, size_t increment); 
    3434    virtual void reset(); 
    3535 
    3636protected: 
    37     double *m_prevMag; 
     37    float *R__ m_prevMag; 
    3838}; 
    3939 
  • trunk/rubberband/src/StretchCalculator.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    2020#include <set> 
    2121#include <cassert> 
     22#include <algorithm> 
     23 
     24#include "sysutils.h" 
    2225 
    2326namespace RubberBand 
     
    163166int 
    164167StretchCalculator::calculateSingle(double ratio, 
    165                                    size_t inputDurationSoFar, 
    166                                    float df) 
    167 { 
     168                                   float df, 
     169                                   size_t increment) 
     170{ 
     171    if (increment == 0) increment = m_increment; 
     172 
    168173    bool isTransient = false; 
    169174 
     
    177182    // works well in common situations. 
    178183 
    179     float transientThreshold = 0.35; 
    180     if (ratio > 1) transientThreshold = 0.25; 
    181  
    182     if (m_useHardPeaks && df > m_prevDf * 1.1 && df > transientThreshold) { 
     184    float transientThreshold = 0.35f; 
     185    if (ratio > 1) transientThreshold = 0.25f; 
     186 
     187    if (m_useHardPeaks && df > m_prevDf * 1.1f && df > transientThreshold) { 
    183188        isTransient = true; 
    184189    } 
     
    191196    m_prevDf = df; 
    192197 
     198    bool ratioChanged = (ratio != m_prevRatio); 
     199    m_prevRatio = ratio; 
     200 
    193201    if (isTransient && m_transientAmnesty == 0) { 
    194202        if (m_debugLevel > 1) { 
    195             std::cerr << "StretchCalculator::calculateSingle: transient found at " 
    196                       << inputDurationSoFar << std::endl; 
    197         } 
    198         m_divergence += m_increment - (m_increment * ratio); 
     203            std::cerr << "StretchCalculator::calculateSingle: transient" 
     204                      << std::endl; 
     205        } 
     206        m_divergence += increment - (increment * ratio); 
    199207 
    200208        // as in offline mode, 0.05 sec approx min between transients 
    201209        m_transientAmnesty = 
    202             lrint(ceil(double(m_sampleRate) / (20 * double(m_increment)))); 
    203  
    204         m_recovery = m_divergence / ((m_sampleRate / 10.0) / m_increment); 
    205         return -m_increment; 
    206     } 
    207  
    208     if (m_prevRatio != ratio) { 
    209         m_recovery = m_divergence / ((m_sampleRate / 10.0) / m_increment); 
    210         m_prevRatio = ratio; 
     210            lrint(ceil(double(m_sampleRate) / (20 * double(increment)))); 
     211 
     212        m_recovery = m_divergence / ((m_sampleRate / 10.0) / increment); 
     213        return -int(increment); 
     214    } 
     215 
     216    if (ratioChanged) { 
     217        m_recovery = m_divergence / ((m_sampleRate / 10.0) / increment); 
    211218    } 
    212219 
    213220    if (m_transientAmnesty > 0) --m_transientAmnesty; 
    214221 
    215     int incr = lrint(m_increment * ratio - m_recovery); 
     222    int incr = lrint(increment * ratio - m_recovery); 
    216223    if (m_debugLevel > 2 || (m_debugLevel > 1 && m_divergence != 0)) { 
    217224        std::cerr << "divergence = " << m_divergence << ", recovery = " << m_recovery << ", incr = " << incr << ", "; 
    218225    } 
    219     if (incr < lrint((m_increment * ratio) / 2)) { 
    220         incr = lrint((m_increment * ratio) / 2); 
    221     } else if (incr > lrint(m_increment * ratio * 2)) { 
    222         incr = lrint(m_increment * ratio * 2); 
    223     } 
    224  
    225     double divdiff = (m_increment * ratio) - incr; 
     226    if (incr < lrint((increment * ratio) / 2)) { 
     227        incr = lrint((increment * ratio) / 2); 
     228    } else if (incr > lrint(increment * ratio * 2)) { 
     229        incr = lrint(increment * ratio * 2); 
     230    } 
     231 
     232    double divdiff = (increment * ratio) - incr; 
    226233 
    227234    if (m_debugLevel > 2 || (m_debugLevel > 1 && m_divergence != 0)) { 
     
    233240    if ((prevDivergence < 0 && m_divergence > 0) || 
    234241        (prevDivergence > 0 && m_divergence < 0)) { 
    235         m_recovery = m_divergence / ((m_sampleRate / 10.0) / m_increment); 
     242        m_recovery = m_divergence / ((m_sampleRate / 10.0) / increment); 
    236243    } 
    237244 
  • trunk/rubberband/src/StretchCalculator.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    4646     * StretchCalculator object; call reset() to reset it.  This uses 
    4747     * a less sophisticated method than the offline calculate(). 
     48     * 
     49     * If increment is non-zero, use it for the input increment for 
     50     * this block in preference to m_increment. 
    4851     */ 
    49     virtual int calculateSingle(double ratio, size_t inputDurationSoFar, 
    50                                 float curveValue); 
     52    virtual int calculateSingle(double ratio, float curveValue, 
     53                                size_t increment = 0); 
    5154 
    5255    void setUseHardPeaks(bool use) { m_useHardPeaks = use; } 
  • trunk/rubberband/src/StretcherChannelData.cpp

    r234 r267  
    11/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ 
    22 
     3/* 
     4    Rubber Band 
     5    An audio time-stretching and pitch-shifting library. 
     6    Copyright 2007-2008 Chris Cannam. 
     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 as 
     10    published by the Free Software Foundation; either version 2 of the 
     11    License, or (at your option) any later version.  See the file 
     12    COPYING included with this distribution for more information. 
     13*/ 
     14 
    315#include "StretcherChannelData.h" 
    416 
    517#include "Resampler.h" 
    618 
     19 
    720namespace RubberBand  
    821{ 
    9  
     22       
    1023RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize, 
    11                                                     size_t outbufSize) 
     24                                                    int overSample, 
     25                                                    size_t outbufSize) : 
     26    oversample(overSample) 
    1227{ 
    1328    std::set<size_t> s; 
     
    1631 
    1732RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set<size_t> &windowSizes, 
     33                                                    int overSample, 
    1834                                                    size_t initialWindowSize, 
    19                                                     size_t outbufSize) 
     35                                                    size_t outbufSize) : 
     36    oversample(overSample) 
    2037{ 
    2138    construct(windowSizes, initialWindowSize, outbufSize); 
     
    3855    } 
    3956 
    40     size_t realSize = maxSize/2 + 1; // size of the real "half" of freq data 
     57    // max size of the real "half" of freq data 
     58    size_t realSize = (maxSize * oversample)/2 + 1; 
    4159 
    4260//    std::cerr << "ChannelData::construct([" << windowSizes.size() << "], " << maxSize << ", " << outbufSize << ")" << std::endl; 
     
    4765    outbuf = new RingBuffer<float>(outbufSize); 
    4866 
    49     mag = new double[realSize]; 
    50     phase = new double[realSize]; 
    51     prevPhase = new double[realSize]; 
    52     unwrappedPhase = new double[realSize]; 
     67    mag = allocDouble(realSize); 
     68    phase = allocDouble(realSize); 
     69    prevPhase = allocDouble(realSize); 
     70    prevError = allocDouble(realSize); 
     71    unwrappedPhase = allocDouble(realSize); 
     72    envelope = allocDouble(realSize); 
     73 
    5374    freqPeak = new size_t[realSize]; 
    5475 
    55     accumulator = new float[maxSize]; 
    56     windowAccumulator = new float[maxSize]; 
    57  
    58     fltbuf = new float[maxSize]; 
     76    fltbuf = allocFloat(maxSize); 
     77 
     78    accumulator = allocFloat(maxSize); 
     79    windowAccumulator = allocFloat(maxSize); 
    5980 
    6081    for (std::set<size_t>::const_iterator i = windowSizes.begin(); 
    6182         i != windowSizes.end(); ++i) { 
    62         ffts[*i] = new FFT(*i); 
     83        ffts[*i] = new FFT(*i * oversample); 
    6384        ffts[*i]->initDouble(); 
    6485    } 
    6586    if (windowSizes.find(initialWindowSize) == windowSizes.end()) { 
    66         ffts[initialWindowSize] = new FFT(initialWindowSize); 
     87        ffts[initialWindowSize] = new FFT(initialWindowSize * oversample); 
    6788        ffts[initialWindowSize]->initDouble(); 
    6889    } 
     
    7899 
    79100    for (size_t i = 0; i < realSize; ++i) { 
    80         mag[i] = 0.0; 
    81         phase[i] = 0.0; 
    82         prevPhase[i] = 0.0; 
    83         unwrappedPhase[i] = 0.0; 
    84101        freqPeak[i] = 0; 
    85102    } 
    86103 
    87     for (size_t i = 0; i < initialWindowSize; ++i) { 
     104    for (size_t i = 0; i < initialWindowSize * oversample; ++i) { 
    88105        dblbuf[i] = 0.0; 
    89106    } 
    90  
    91     for (size_t i = 0; i < maxSize; ++i) { 
    92         accumulator[i] = 0.f; 
    93         windowAccumulator[i] = 0.f; 
    94         fltbuf[i] = 0.0; 
    95     } 
    96107} 
    97108 
     
    100111{ 
    101112    size_t oldSize = inbuf->getSize(); 
    102     size_t realSize = windowSize/2 + 1; 
     113    size_t realSize = (windowSize * oversample) / 2 + 1; 
    103114 
    104115//    std::cerr << "ChannelData::setWindowSize(" << windowSize << ") [from " << oldSize << "]" << std::endl; 
     
    115126            //!!! this also requires a lock, but it shouldn't occur in 
    116127            //RT mode with proper initialisation 
    117             ffts[windowSize] = new FFT(windowSize); 
     128            ffts[windowSize] = new FFT(windowSize * oversample); 
    118129            ffts[windowSize]->initDouble(); 
    119130        } 
     
    123134        dblbuf = fft->getDoubleTimeBuffer(); 
    124135 
    125         for (size_t i = 0; i < windowSize; ++i) { 
     136        for (size_t i = 0; i < windowSize * oversample; ++i) { 
    126137            dblbuf[i] = 0.0; 
    127138        } 
     
    131142            phase[i] = 0.0; 
    132143            prevPhase[i] = 0.0; 
     144            prevError[i] = 0.0; 
    133145            unwrappedPhase[i] = 0.0; 
    134146            freqPeak[i] = 0; 
     
    151163    // We don't want to preserve data in these arrays 
    152164 
    153     delete[] mag; 
    154     delete[] phase; 
    155     delete[] prevPhase; 
    156     delete[] unwrappedPhase; 
     165    mag = allocDouble(mag, realSize); 
     166    phase = allocDouble(phase, realSize); 
     167    prevPhase = allocDouble(prevPhase, realSize); 
     168    prevError = allocDouble(prevError, realSize); 
     169    unwrappedPhase = allocDouble(unwrappedPhase, realSize); 
     170    envelope = allocDouble(envelope, realSize); 
     171 
    157172    delete[] freqPeak; 
    158  
    159     mag = new double[realSize]; 
    160     phase = new double[realSize]; 
    161     prevPhase = new double[realSize]; 
    162     unwrappedPhase = new double[realSize]; 
    163173    freqPeak = new size_t[realSize]; 
    164174 
    165     delete[] fltbuf; 
    166     fltbuf = new float[windowSize]; 
     175    fltbuf = allocFloat(fltbuf, windowSize); 
    167176 
    168177    // But we do want to preserve data in these 
    169178 
    170     float *newAcc = new float[windowSize]; 
     179    float *newAcc = allocFloat(windowSize); 
     180 
    171181    for (size_t i = 0; i < oldSize; ++i) newAcc[i] = accumulator[i]; 
    172     delete[] accumulator; 
     182 
     183    freeFloat(accumulator); 
    173184    accumulator = newAcc; 
    174185 
    175     newAcc = new float[windowSize]; 
     186    newAcc = allocFloat(windowSize); 
     187 
    176188    for (size_t i = 0; i < oldSize; ++i) newAcc[i] = windowAccumulator[i]; 
    177     delete[] windowAccumulator; 
     189 
     190    freeFloat(windowAccumulator); 
    178191    windowAccumulator = newAcc; 
    179192     
     
    181194 
    182195    for (size_t i = 0; i < realSize; ++i) { 
    183         mag[i] = 0.0; 
    184         phase[i] = 0.0; 
    185         prevPhase[i] = 0.0; 
    186         unwrappedPhase[i] = 0.0; 
    187196        freqPeak[i] = 0; 
    188197    } 
    189198 
    190199    for (size_t i = 0; i < windowSize; ++i) { 
    191         fltbuf[i] = 0.0; 
    192     } 
    193  
    194     for (size_t i = oldSize; i < windowSize; ++i) { 
    195         accumulator[i] = 0.f; 
    196         windowAccumulator[i] = 0.f; 
     200        fltbuf[i] = 0.f; 
    197201    } 
    198202 
    199203    if (ffts.find(windowSize) == ffts.end()) { 
    200         ffts[windowSize] = new FFT(windowSize); 
     204        ffts[windowSize] = new FFT(windowSize * oversample); 
    201205        ffts[windowSize]->initDouble(); 
    202206    } 
     
    206210    dblbuf = fft->getDoubleTimeBuffer(); 
    207211 
    208     for (size_t i = 0; i < windowSize; ++i) { 
     212    for (size_t i = 0; i < windowSize * oversample; ++i) { 
    209213        dblbuf[i] = 0.0; 
    210214    } 
     
    229233} 
    230234 
     235void 
     236RubberBandStretcher::Impl::ChannelData::setResampleBufSize(size_t sz) 
     237{ 
     238    resamplebuf = allocFloat(resamplebuf, sz); 
     239    resamplebufSize = sz; 
     240} 
     241 
    231242RubberBandStretcher::Impl::ChannelData::~ChannelData() 
    232243{ 
    233244    delete resampler; 
    234     delete[] resamplebuf; 
     245 
     246    freeFloat(resamplebuf); 
    235247 
    236248    delete inbuf; 
    237249    delete outbuf; 
    238     delete[] mag; 
    239     delete[] phase; 
    240     delete[] prevPhase; 
    241     delete[] unwrappedPhase; 
     250 
     251    freeDouble(mag); 
     252    freeDouble(phase); 
     253    freeDouble(prevPhase); 
     254    freeDouble(prevError); 
     255    freeDouble(unwrappedPhase); 
     256    freeDouble(envelope); 
    242257    delete[] freqPeak; 
    243     delete[] accumulator; 
    244     delete[] windowAccumulator; 
    245     delete[] fltbuf; 
     258    freeFloat(accumulator); 
     259    freeFloat(windowAccumulator); 
     260    freeFloat(fltbuf); 
    246261 
    247262    for (std::map<size_t, FFT *>::iterator i = ffts.begin(); 
     
    265280    inputSize = -1; 
    266281    outCount = 0; 
     282    unchanged = true; 
    267283    draining = false; 
    268284    outputComplete = false; 
  • trunk/rubberband/src/StretcherChannelData.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1919 
    2020#include <set> 
     21 
     22//#define EXPERIMENT 1 
    2123 
    2224namespace RubberBand 
     
    4042     * size specified by the user of the code. 
    4143     */ 
    42     ChannelData(size_t windowSize, size_t outbufSize); 
     44    ChannelData(size_t windowSize, int overSample, size_t outbufSize); 
    4345 
    4446    /** 
     
    5557     */ 
    5658    ChannelData(const std::set<size_t> &windowSizes, 
    57                 size_t initialWindowSize, size_t outbufSize); 
     59                int overSample, size_t initialWindowSize, size_t outbufSize); 
    5860    ~ChannelData(); 
    5961 
     
    7779    void setOutbufSize(size_t outbufSize); 
    7880 
     81    /** 
     82     * Set the resampler buffer size.  Default if not called is no 
     83     * buffer allocated at all. 
     84     */ 
     85    void setResampleBufSize(size_t resamplebufSize); 
     86     
    7987    RingBuffer<float> *inbuf; 
    8088    RingBuffer<float> *outbuf; 
     
    8492 
    8593    double *prevPhase; 
     94    double *prevError; 
    8695    double *unwrappedPhase; 
     96 
    8797 
    8898    size_t *freqPeak; 
     
    94104    float *fltbuf; 
    95105    double *dblbuf; // owned by FFT object, only used for time domain FFT i/o 
     106    double *envelope; // for cepstral formant shift 
     107    bool unchanged; 
    96108 
    97109    size_t prevIncrement; // only used in RT mode 
     
    112124    size_t resamplebufSize; 
    113125 
     126    int oversample; 
     127 
    114128private: 
    115129    void construct(const std::set<size_t> &windowSizes, 
  • trunk/rubberband/src/StretcherImpl.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1717#include "HighFrequencyAudioCurve.h" 
    1818#include "SpectralDifferenceAudioCurve.h" 
     19#include "SilentAudioCurve.h" 
    1920#include "ConstantAudioCurve.h" 
    2021#include "StretchCalculator.h" 
    2122#include "StretcherChannelData.h" 
    2223#include "Resampler.h" 
     24#include "Profiler.h" 
    2325 
    2426#include <cassert> 
     
    3537using std::min; 
    3638 
     39 
    3740namespace RubberBand { 
    3841 
     
    4750 
    4851 
    49 RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher, 
    50                                 size_t sampleRate, 
     52 
     53RubberBandStretcher::Impl::Impl(size_t sampleRate, 
    5154                                size_t channels, 
    5255                                Options options, 
    5356                                double initialTimeRatio, 
    5457                                double initialPitchScale) : 
    55     m_stretcher(stretcher), 
     58    m_sampleRate(sampleRate), 
    5659    m_channels(channels), 
    5760    m_timeRatio(initialTimeRatio), 
     
    7174    m_spaceAvailable("space"), 
    7275    m_inputDuration(0), 
     76    m_silentHistory(0), 
    7377    m_lastProcessOutputIncrements(16), 
    7478    m_lastProcessPhaseResetDf(16), 
    7579    m_phaseResetAudioCurve(0), 
    7680    m_stretchAudioCurve(0), 
     81    m_silentAudioCurve(0), 
    7782    m_stretchCalculator(0), 
    7883    m_freq0(600), 
     
    8186    m_baseWindowSize(m_defaultWindowSize) 
    8287{ 
     88 
    8389    if (m_debugLevel > 0) { 
    84         cerr << "RubberBandStretcher::Impl::Impl: rate = " << m_stretcher->m_sampleRate << ", options = " << options << endl; 
     90        cerr << "RubberBandStretcher::Impl::Impl: rate = " << m_sampleRate << ", options = " << options << endl; 
    8591    } 
    8692 
    8793    // Window size will vary according to the audio sample rate, but 
    8894    // we don't let it drop below the 48k default 
    89     m_rateMultiple = float(m_stretcher->m_sampleRate) / 48000.f; 
     95    m_rateMultiple = float(m_sampleRate) / 48000.f; 
    9096    if (m_rateMultiple < 1.f) m_rateMultiple = 1.f; 
    9197    m_baseWindowSize = roundUp(int(m_defaultWindowSize * m_rateMultiple)); 
     
    161167    delete m_phaseResetAudioCurve; 
    162168    delete m_stretchAudioCurve; 
     169    delete m_silentAudioCurve; 
    163170    delete m_stretchCalculator; 
    164171    delete m_studyFFT; 
     
    194201    if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset(); 
    195202    if (m_stretchAudioCurve) m_stretchAudioCurve->reset(); 
     203    if (m_silentAudioCurve) m_silentAudioCurve->reset(); 
    196204    m_inputDuration = 0; 
     205    m_silentHistory = 0; 
    197206 
    198207    if (m_threaded) m_threadSetMutex.unlock(); 
     
    228237 
    229238    if (fs == m_pitchScale) return; 
     239     
     240    bool was1 = (m_pitchScale == 1.f); 
     241    bool rbs = resampleBeforeStretching(); 
     242 
    230243    m_pitchScale = fs; 
    231244 
    232245    reconfigure(); 
     246 
     247    if (!(m_options & OptionPitchHighConsistency) && 
     248        (was1 || resampleBeforeStretching() != rbs) && 
     249        m_pitchScale != 1.f) { 
     250         
     251        // resampling mode has changed 
     252        for (int c = 0; c < int(m_channels); ++c) { 
     253            if (m_channelData[c]->resampler) { 
     254                m_channelData[c]->resampler->reset(); 
     255            } 
     256        } 
     257    } 
    233258} 
    234259 
     
    322347    if (m_realtime) { 
    323348 
    324         // use a fixed input increment 
    325  
    326         inputIncrement = roundUp(int(m_defaultIncrement * m_rateMultiple)); 
    327  
    328349        if (r < 1) { 
     350             
     351            bool rsb = (m_pitchScale < 1.0 && !resampleBeforeStretching()); 
     352            float windowIncrRatio = 4.5; 
     353            if (r == 1.0) windowIncrRatio = 4; 
     354            else if (rsb) windowIncrRatio = 4.5; 
     355            else windowIncrRatio = 6; 
     356 
     357            inputIncrement = int(windowSize / windowIncrRatio); 
    329358            outputIncrement = int(floor(inputIncrement * r)); 
    330             if (outputIncrement < 1) { 
    331                 outputIncrement = 1; 
    332                 inputIncrement = roundUp(lrint(ceil(outputIncrement / r))); 
    333                 windowSize = inputIncrement * 4; 
    334             } 
     359 
     360            // Very long stretch or very low pitch shift 
     361            if (outputIncrement < m_defaultIncrement / 4) { 
     362                if (outputIncrement < 1) outputIncrement = 1; 
     363                while (outputIncrement < m_defaultIncrement / 4 && 
     364                       windowSize < m_baseWindowSize * 4) { 
     365                    outputIncrement *= 2; 
     366                    inputIncrement = lrint(ceil(outputIncrement / r)); 
     367                    windowSize = roundUp(lrint(ceil(inputIncrement * windowIncrRatio))); 
     368                } 
     369            } 
     370 
    335371        } else { 
    336             outputIncrement = int(ceil(inputIncrement * r)); 
    337             while (outputIncrement > 1024 && inputIncrement > 1) { 
    338                 inputIncrement /= 2; 
    339                 outputIncrement = lrint(ceil(inputIncrement * r)); 
    340             } 
    341             windowSize = std::max(windowSize, roundUp(outputIncrement * 6)); 
    342             if (r > 5) while (windowSize < 8192) windowSize *= 2; 
     372 
     373            bool rsb = (m_pitchScale > 1.0 && resampleBeforeStretching()); 
     374            float windowIncrRatio = 4.5; 
     375            if (r == 1.0) windowIncrRatio = 4; 
     376            else if (rsb) windowIncrRatio = 4.5; 
     377            else windowIncrRatio = 6; 
     378 
     379            outputIncrement = int(windowSize / windowIncrRatio); 
     380            inputIncrement = int(outputIncrement / r); 
     381            while (outputIncrement > 1024 * m_rateMultiple && 
     382                   inputIncrement > 1) { 
     383                outputIncrement /= 2; 
     384                inputIncrement = int(outputIncrement / r); 
     385            } 
     386            size_t minwin = roundUp(lrint(outputIncrement * windowIncrRatio)); 
     387            if (windowSize < minwin) windowSize = minwin; 
     388 
     389            if (rsb) { 
     390//                cerr << "adjusting window size from " << windowSize; 
     391                size_t newWindowSize = roundUp(lrint(windowSize / m_pitchScale)); 
     392                if (newWindowSize < 512) newWindowSize = 512; 
     393                size_t div = windowSize / newWindowSize; 
     394                if (inputIncrement > div && outputIncrement > div) { 
     395                    inputIncrement /= div; 
     396                    outputIncrement /= div; 
     397                    windowSize /= div; 
     398                } 
     399//                cerr << " to " << windowSize << " (inputIncrement = " << inputIncrement << ", outputIncrement = " << outputIncrement << ")" << endl; 
     400            } 
    343401        } 
    344402 
    345403    } else { 
    346  
    347         // use a variable increment 
    348404 
    349405        if (r < 1) { 
     
    366422            if (r > 5) while (windowSize < 8192) windowSize *= 2; 
    367423        } 
    368     }         
     424    } 
    369425 
    370426    if (m_expectedInputDuration > 0) { 
     
    451507    if (m_realtime) { 
    452508        windowSizes.insert(m_baseWindowSize); 
     509        windowSizes.insert(m_baseWindowSize / 2); 
    453510        windowSizes.insert(m_baseWindowSize * 2); 
    454         windowSizes.insert(m_baseWindowSize * 4); 
     511//        windowSizes.insert(m_baseWindowSize * 4); 
    455512    } 
    456513    windowSizes.insert(m_windowSize); 
     
    480537        for (size_t c = 0; c < m_channels; ++c) { 
    481538            m_channelData.push_back 
    482                 (new ChannelData(windowSizes, m_windowSize, m_outbufSize)); 
     539                (new ChannelData(windowSizes, 1, m_windowSize, m_outbufSize)); 
    483540        } 
    484541    } 
     
    486543    if (!m_realtime && windowSizeChanged) { 
    487544        delete m_studyFFT; 
    488         m_studyFFT = new FFT(m_windowSize); 
     545        m_studyFFT = new FFT(m_windowSize, m_debugLevel); 
    489546        m_studyFFT->initFloat(); 
    490547    } 
    491548 
    492     if (m_pitchScale != 1.0 || m_realtime) { 
     549    if (m_pitchScale != 1.0 || 
     550        (m_options & OptionPitchHighConsistency) || 
     551        m_realtime) { 
    493552 
    494553        for (size_t c = 0; c < m_channels; ++c) { 
     
    497556 
    498557            m_channelData[c]->resampler = 
    499                 new Resampler(Resampler::FastestTolerable, 1, 4096 * 16); 
     558                new Resampler(Resampler::FastestTolerable, 1, 4096 * 16, 
     559                              m_debugLevel); 
    500560 
    501561            // rbs is the amount of buffer space we think we'll need 
     
    505565                lrintf(ceil((m_increment * m_timeRatio * 2) / m_pitchScale)); 
    506566            if (rbs < m_increment * 16) rbs = m_increment * 16; 
    507             m_channelData[c]->resamplebufSize = rbs; 
    508             m_channelData[c]->resamplebuf = new float[rbs]; 
     567            m_channelData[c]->setResampleBufSize(rbs); 
    509568        } 
    510569    } 
    511570     
     571    // stretchAudioCurve is unused in RT mode; phaseResetAudioCurve, 
     572    // silentAudioCurve and stretchCalculator however are used in all 
     573    // modes 
     574 
    512575    delete m_phaseResetAudioCurve; 
    513     m_phaseResetAudioCurve = new PercussiveAudioCurve(m_stretcher->m_sampleRate, 
    514                                                       m_windowSize); 
    515  
    516     // stretchAudioCurve unused in RT mode; phaseResetAudioCurve and 
    517     // stretchCalculator however are used in all modes 
     576    m_phaseResetAudioCurve = new PercussiveAudioCurve 
     577        (m_sampleRate, m_windowSize); 
     578 
     579    delete m_silentAudioCurve; 
     580    m_silentAudioCurve = new SilentAudioCurve 
     581        (m_sampleRate, m_windowSize); 
    518582 
    519583    if (!m_realtime) { 
     
    521585        if (!(m_options & OptionStretchPrecise)) { 
    522586            m_stretchAudioCurve = new SpectralDifferenceAudioCurve 
    523                 (m_stretcher->m_sampleRate, m_windowSize); 
     587                (m_sampleRate, m_windowSize); 
    524588        } else { 
    525589            m_stretchAudioCurve = new ConstantAudioCurve 
    526                 (m_stretcher->m_sampleRate, m_windowSize); 
     590                (m_sampleRate, m_windowSize); 
    527591        } 
    528592    } 
     
    530594    delete m_stretchCalculator; 
    531595    m_stretchCalculator = new StretchCalculator 
    532         (m_stretcher->m_sampleRate, m_increment, 
     596        (m_sampleRate, m_increment, 
    533597         !(m_options & OptionTransientsSmooth)); 
    534598 
     
    566630            m_phaseResetDf.clear(); 
    567631            m_stretchDf.clear(); 
     632            m_silence.clear(); 
    568633            m_inputDuration = 0; 
    569634        } 
     
    610675 
    611676            m_channelData[c]->resampler = 
    612                 new Resampler(Resampler::FastestTolerable, 1, m_windowSize); 
    613  
    614             m_channelData[c]->resamplebufSize = 
    615                 lrintf(ceil((m_increment * m_timeRatio * 2) / m_pitchScale)); 
    616             m_channelData[c]->resamplebuf = 
    617                 new float[m_channelData[c]->resamplebufSize]; 
     677                new Resampler(Resampler::FastestTolerable, 1, m_windowSize, 
     678                              m_debugLevel); 
     679 
     680            m_channelData[c]->setResampleBufSize 
     681                (lrintf(ceil((m_increment * m_timeRatio * 2) / m_pitchScale))); 
    618682        } 
    619683    } 
     
    638702        return; 
    639703    } 
    640     m_options &= ~(OptionTransientsMixed | 
    641                    OptionTransientsSmooth | 
    642                    OptionTransientsCrisp); 
     704    int mask = (OptionTransientsMixed | OptionTransientsSmooth | OptionTransientsCrisp); 
     705    m_options &= ~mask; 
     706    options &= mask; 
    643707    m_options |= options; 
    644708 
     
    650714RubberBandStretcher::Impl::setPhaseOption(Options options) 
    651715{ 
    652     m_options &= ~(OptionPhaseAdaptive | 
    653                    OptionPhasePeakLocked | 
    654                    OptionPhaseIndependent); 
     716    int mask = (OptionPhaseLaminar | OptionPhaseIndependent); 
     717    m_options &= ~mask; 
     718    options &= mask; 
    655719    m_options |= options; 
    656720} 
    657721 
    658722void 
     723RubberBandStretcher::Impl::setFormantOption(Options options) 
     724{ 
     725    int mask = (OptionFormantShifted | OptionFormantPreserved); 
     726    m_options &= ~mask; 
     727    options &= mask; 
     728    m_options |= options; 
     729} 
     730 
     731void 
     732RubberBandStretcher::Impl::setPitchOption(Options options) 
     733{ 
     734    if (!m_realtime) { 
     735        cerr << "RubberBandStretcher::Impl::setPitchOption: Pitch option is not used in non-RT mode" << endl; 
     736        return; 
     737    } 
     738 
     739    Options prior = m_options; 
     740 
     741    int mask = (OptionPitchHighQuality | 
     742                OptionPitchHighSpeed | 
     743                OptionPitchHighConsistency); 
     744    m_options &= ~mask; 
     745    options &= mask; 
     746    m_options |= options; 
     747 
     748    if (prior != m_options) reconfigure(); 
     749} 
     750 
     751void 
    659752RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool final) 
    660753{ 
     754    Profiler profiler("RubberBandStretcher::Impl::study"); 
     755 
    661756    if (m_realtime) { 
    662757        if (m_debugLevel > 1) { 
     
    716811        } 
    717812 
    718         while ((inbuf.getReadSpace() >= m_windowSize) || 
    719                (final && (inbuf.getReadSpace() >= m_windowSize/2))) { 
     813        while ((inbuf.getReadSpace() >= int(m_windowSize)) || 
     814               (final && (inbuf.getReadSpace() >= int(m_windowSize/2)))) { 
    720815 
    721816            // We know we have at least m_windowSize samples available 
     
    744839            df = m_stretchAudioCurve->process(cd.fltbuf, m_increment); 
    745840            m_stretchDf.push_back(df); 
     841 
     842            df = m_silentAudioCurve->process(cd.fltbuf, m_increment); 
     843            bool silent = (df > 0.f); 
     844            if (silent && m_debugLevel > 1) { 
     845                cerr << "silence found at " << m_inputDuration << endl; 
     846            } 
     847            m_silence.push_back(silent); 
    746848 
    747849//            cout << df << endl; 
     
    818920RubberBandStretcher::Impl::calculateStretch() 
    819921{ 
     922    Profiler profiler("RubberBandStretcher::Impl::calculateStretch"); 
     923 
    820924    std::vector<int> increments = m_stretchCalculator->calculate 
    821925        (getEffectiveRatio(), 
     
    824928         m_stretchDf); 
    825929 
     930    int history = 0; 
     931    for (size_t i = 0; i < increments.size(); ++i) { 
     932        if (i >= m_silence.size()) break; 
     933        if (m_silence[i]) ++history; 
     934        else history = 0; 
     935        if (history >= int(m_windowSize / m_increment) && increments[i] >= 0) { 
     936            increments[i] = -increments[i]; 
     937            if (m_debugLevel > 1) { 
     938                std::cerr << "phase reset on silence (silent history == " 
     939                          << history << ")" << std::endl; 
     940            } 
     941        } 
     942    } 
     943 
    826944    if (m_outputIncrements.empty()) m_outputIncrements = increments; 
    827945    else { 
     
    844962RubberBandStretcher::Impl::getSamplesRequired() const 
    845963{ 
     964    Profiler profiler("RubberBandStretcher::Impl::getSamplesRequired"); 
     965 
    846966    size_t reqd = 0; 
    847967 
     
    879999RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bool final) 
    8801000{ 
     1001    Profiler profiler("RubberBandStretcher::Impl::process"); 
     1002 
    8811003    if (m_mode == Finished) { 
    8821004        cerr << "RubberBandStretcher::Impl::process: Cannot process again after final chunk" << endl; 
     
    9141036    bool allConsumed = false; 
    9151037 
    916     map<size_t, size_t> consumed; 
     1038    size_t *consumed = (size_t *)alloca(m_channels * sizeof(size_t)); 
    9171039    for (size_t c = 0; c < m_channels; ++c) { 
    9181040        consumed[c] = 0; 
     
    9201042 
    9211043    while (!allConsumed) { 
    922  
    923 //        cerr << "process looping" << endl; 
    9241044 
    9251045//#ifndef NO_THREADING 
     
    9361056 
    9371057        allConsumed = true; 
     1058 
    9381059        for (size_t c = 0; c < m_channels; ++c) { 
    9391060            consumed[c] += consumeChannel(c, 
    9401061                                          input[c] + consumed[c], 
    941                                           samples - consumed[c]); 
     1062                                          samples - consumed[c], 
     1063                                          final); 
    9421064            if (consumed[c] < samples) { 
    9431065                allConsumed = false; 
     
    9821104*/ 
    9831105        } 
     1106 
     1107//        if (!allConsumed) cerr << "process looping" << endl; 
     1108 
    9841109    } 
    9851110     
     
    9891114} 
    9901115 
    991 size_t 
    992 RubberBandStretcher::Impl::consumeChannel(size_t c, const float *input, size_t samples) 
    993 { 
    994     size_t consumed = 0; 
    995      
    996     ChannelData &cd = *m_channelData[c]; 
    997     RingBuffer<float> &inbuf = *cd.inbuf; 
    998      
    999     while (consumed < samples) { 
    1000  
    1001         size_t writable = inbuf.getWriteSpace(); 
    1002  
    1003 //        cerr << "channel " << c << ": samples remaining = " << samples - consumed << ", writable space = " << writable << endl; 
    1004  
    1005         writable = min(writable, samples - consumed); 
    1006  
    1007         if (writable == 0) { 
    1008             // warn 
    1009 //            cerr << "WARNING: writable == 0 for ch " << c << " (consumed = " << consumed << ", samples = " << samples << ")" << endl; 
    1010             return consumed; 
    1011         } else { 
    1012             inbuf.write(input + consumed, writable); 
    1013             consumed += writable; 
    1014             cd.inCount += writable; 
    1015         } 
    1016     } 
    1017  
    1018     return samples; 
    1019 } 
    1020  
    1021  
    1022 } 
    1023  
     1116 
     1117} 
     1118 
  • trunk/rubberband/src/StretcherImpl.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    3535{ 
    3636public: 
    37     Impl(RubberBandStretcher *stretcher, 
    38          size_t sampleRate, size_t channels, Options options, 
     37    Impl(size_t sampleRate, size_t channels, Options options, 
    3938         double initialTimeRatio, double initialPitchScale); 
    4039    ~Impl(); 
     
    5150    void setTransientsOption(Options); 
    5251    void setPhaseOption(Options); 
     52    void setFormantOption(Options); 
     53    void setPitchOption(Options); 
    5354 
    5455    void setExpectedInputDuration(size_t samples); 
     
    8485 
    8586protected: 
    86     RubberBandStretcher *m_stretcher; 
     87    size_t m_sampleRate; 
    8788    size_t m_channels; 
    8889 
    89     size_t consumeChannel(size_t channel, const float *input, size_t samples); 
     90    size_t consumeChannel(size_t channel, const float *input, 
     91                          size_t samples, bool final); 
    9092    void processChunks(size_t channel, bool &any, bool &last); 
    9193    bool processOneChunk(); // across all channels, for real time use 
     
    99101    void analyseChunk(size_t channel); 
    100102    void modifyChunk(size_t channel, size_t outputIncrement, bool phaseReset); 
     103    void formantShiftChunk(size_t channel); 
    101104    void synthesiseChunk(size_t channel); 
    102105    void writeChunk(size_t channel, size_t shiftIncrement, bool last); 
     
    110113    size_t roundUp(size_t value); // to next power of two 
    111114 
     115    bool resampleBeforeStretching() const; 
     116     
    112117    double m_timeRatio; 
    113118    double m_pitchScale; 
     
    162167    std::vector<float> m_phaseResetDf; 
    163168    std::vector<float> m_stretchDf; 
     169    std::vector<bool> m_silence; 
     170    int m_silentHistory; 
    164171 
    165172    class ChannelData;  
     
    173180    AudioCurve *m_phaseResetAudioCurve; 
    174181    AudioCurve *m_stretchAudioCurve; 
     182    AudioCurve *m_silentAudioCurve; 
    175183    StretchCalculator *m_stretchCalculator; 
    176184 
  • trunk/rubberband/src/StretcherProcess.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    2020#include "StretcherChannelData.h" 
    2121#include "Resampler.h" 
     22#include "Profiler.h" 
    2223 
    2324#include <cassert> 
     
    2526#include <set> 
    2627#include <map> 
     28#include <deque> 
     29 
    2730 
    2831using std::cerr; 
     
    98101} 
    99102 
     103bool 
     104RubberBandStretcher::Impl::resampleBeforeStretching() const 
     105{ 
     106    // We can't resample before stretching in offline mode, because 
     107    // the stretch calculation is based on doing it the other way 
     108    // around.  It would take more work (and testing) to enable this. 
     109    if (!m_realtime) return false; 
     110 
     111    if (m_options & OptionPitchHighQuality) { 
     112        return (m_pitchScale < 1.0); // better sound 
     113    } else if (m_options & OptionPitchHighConsistency) { 
     114        return false; 
     115    } else { 
     116        return (m_pitchScale > 1.0); // better performance 
     117    } 
     118} 
     119     
     120size_t 
     121RubberBandStretcher::Impl::consumeChannel(size_t c, const float *input, 
     122                                          size_t samples, bool final) 
     123{ 
     124    Profiler profiler("RubberBandStretcher::Impl::consumeChannel"); 
     125 
     126    ChannelData &cd = *m_channelData[c]; 
     127    RingBuffer<float> &inbuf = *cd.inbuf; 
     128 
     129    size_t toWrite = samples; 
     130    size_t writable = inbuf.getWriteSpace(); 
     131 
     132    bool resampling = resampleBeforeStretching(); 
     133 
     134    if (resampling) { 
     135 
     136        toWrite = int(ceil(samples / m_pitchScale)); 
     137        if (writable < toWrite) { 
     138            samples = int(floor(writable * m_pitchScale)); 
     139            if (samples == 0) return 0; 
     140        } 
     141 
     142        size_t reqSize = int(ceil(samples / m_pitchScale)); 
     143        if (reqSize > cd.resamplebufSize) { 
     144            cerr << "WARNING: RubberBandStretcher::Impl::consumeChannel: resizing resampler buffer from " 
     145                 << cd.resamplebufSize << " to " << reqSize << endl; 
     146            cd.setResampleBufSize(reqSize); 
     147        } 
     148 
     149 
     150        toWrite = cd.resampler->resample(&input, 
     151                                         &cd.resamplebuf, 
     152                                         samples, 
     153                                         1.0 / m_pitchScale, 
     154                                         final); 
     155 
     156    } 
     157 
     158    if (writable < toWrite) { 
     159        if (resampling) { 
     160            return 0; 
     161        } 
     162        toWrite = writable; 
     163    } 
     164 
     165    if (resampling) { 
     166        inbuf.write(cd.resamplebuf, toWrite); 
     167        cd.inCount += samples; 
     168        return samples; 
     169    } else { 
     170        inbuf.write(input, toWrite); 
     171        cd.inCount += toWrite; 
     172        return toWrite; 
     173    } 
     174} 
     175 
    100176void 
    101177RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last) 
    102178{ 
     179    Profiler profiler("RubberBandStretcher::Impl::processChunks"); 
     180 
    103181    // Process as many chunks as there are available on the input 
    104182    // buffer for channel c.  This requires that the increments have 
     
    141219RubberBandStretcher::Impl::processOneChunk() 
    142220{ 
     221    Profiler profiler("RubberBandStretcher::Impl::processOneChunk"); 
     222 
    143223    // Process a single chunk for all channels, provided there is 
    144224    // enough data on each channel for at least one chunk.  This is 
     
    174254RubberBandStretcher::Impl::testInbufReadSpace(size_t c) 
    175255{ 
     256    Profiler profiler("RubberBandStretcher::Impl::testInbufReadSpace"); 
     257 
    176258    ChannelData &cd = *m_channelData[c]; 
    177259    RingBuffer<float> &inbuf = *cd.inbuf; 
     
    224306                                                  bool phaseReset) 
    225307{ 
     308    Profiler profiler("RubberBandStretcher::Impl::processChunkForChannel"); 
     309 
    226310    // Process a single chunk on a single channel.  This assumes 
    227311    // enough input data is available; caller must have tested this 
     
    250334        // We need to peek m_windowSize samples for processing, and 
    251335        // then skip m_increment to advance the read pointer. 
    252          
     336 
    253337        modifyChunk(c, phaseIncrement, phaseReset); 
    254338        synthesiseChunk(c); // reads from cd.mag, cd.phase 
     
    285369         
    286370    if (m_threaded) { 
    287         size_t required = shiftIncrement; 
     371 
     372        int required = shiftIncrement; 
     373 
    288374        if (m_pitchScale != 1.0) { 
    289375            required = int(required / m_pitchScale) + 1; 
     
    314400                                               bool &phaseReset) 
    315401{ 
     402    Profiler profiler("RubberBandStretcher::Impl::calculateIncrements"); 
     403 
    316404//    cerr << "calculateIncrements" << endl; 
    317405     
     
    342430        } 
    343431    } 
     432 
     433    const int hs = m_windowSize/2 + 1; 
    344434 
    345435    // Normally we would mix down the time-domain signal and apply a 
     
    353443    // be apparent. 
    354444 
    355     for (size_t i = 0; i <= m_windowSize/2; ++i) { 
    356         cd.fltbuf[i] = 0.0; 
    357     } 
    358  
    359     for (size_t c = 0; c < m_channels; ++c) { 
    360         for (size_t i = 0; i <= m_windowSize/2; ++i) { 
    361             cd.fltbuf[i] += m_channelData[c]->mag[i]; 
    362         } 
    363     } 
    364      
    365     float df = m_phaseResetAudioCurve->process(cd.fltbuf, m_increment); 
     445    float df = 0.f; 
     446    bool silent = false; 
     447 
     448    if (m_channels == 1) { 
     449 
     450        df = m_phaseResetAudioCurve->process(cd.mag, m_increment); 
     451        silent = (m_silentAudioCurve->process(cd.mag, m_increment) > 0.f); 
     452 
     453    } else { 
     454 
     455        double *tmp = (double *)alloca(hs * sizeof(double)); 
     456 
     457        for (int i = 0; i < hs; ++i) { 
     458            tmp[i] = 0.0; 
     459        } 
     460        for (size_t c = 0; c < m_channels; ++c) { 
     461            for (int i = 0; i < hs; ++i) { 
     462                tmp[i] += m_channelData[c]->mag[i]; 
     463            } 
     464        } 
     465     
     466        df = m_phaseResetAudioCurve->process(tmp, m_increment); 
     467        silent = (m_silentAudioCurve->process(tmp, m_increment) > 0.f); 
     468    } 
    366469 
    367470    int incr = m_stretchCalculator->calculateSingle 
    368         (getEffectiveRatio(), 
    369          m_inputDuration, //!!! no, totally wrong... fortunately it doesn't matter atm 
    370          df); 
     471            (getEffectiveRatio(), df, m_increment); 
    371472 
    372473    m_lastProcessPhaseResetDf.write(&df, 1); 
     
    400501 
    401502    cd.prevIncrement = shiftIncrementRtn; 
     503 
     504    if (silent) ++m_silentHistory; 
     505    else m_silentHistory = 0; 
     506 
     507    if (m_silentHistory >= int(m_windowSize / m_increment) && !phaseReset) { 
     508        phaseReset = true; 
     509        if (m_debugLevel > 1) { 
     510            cerr << "calculateIncrements: phase reset on silence (silent history == " 
     511                 << m_silentHistory << ")" << endl; 
     512        } 
     513    } 
    402514} 
    403515 
     
    408520                                         bool &phaseReset) 
    409521{ 
     522    Profiler profiler("RubberBandStretcher::Impl::getIncrements"); 
     523 
    410524    if (channel >= m_channels) { 
    411525        phaseIncrementRtn = m_increment; 
     
    479593RubberBandStretcher::Impl::analyseChunk(size_t channel) 
    480594{ 
    481     size_t i; 
     595    Profiler profiler("RubberBandStretcher::Impl::analyseChunk"); 
     596 
     597    int i; 
    482598 
    483599    ChannelData &cd = *m_channelData[channel]; 
    484600 
     601    double *const R__ dblbuf = cd.dblbuf; 
     602    float *const R__ fltbuf = cd.fltbuf; 
     603 
     604    int sz = m_windowSize; 
     605    int hs = m_windowSize/2; 
     606 
    485607    // cd.fltbuf is known to contain m_windowSize samples 
    486608 
    487     m_window->cut(cd.fltbuf); 
    488  
    489     for (i = 0; i < m_windowSize/2; ++i) { 
    490         cd.dblbuf[i] = cd.fltbuf[i + m_windowSize/2]; 
    491         cd.dblbuf[i + m_windowSize/2] = cd.fltbuf[i]; 
    492     } 
    493  
    494     cd.fft->forwardPolar(cd.dblbuf, cd.mag, cd.phase); 
    495 } 
    496  
    497 double mod(double x, double y) { return x - (y * floor(x / y)); } 
    498 double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; } 
     609    m_window->cut(fltbuf); 
     610 
     611    if (cd.oversample > 1) { 
     612 
     613        int bufsiz = sz * cd.oversample; 
     614        int offset = (bufsiz - sz) / 2; 
     615 
     616        // eek 
     617 
     618        for (i = 0; i < offset; ++i) { 
     619            dblbuf[i] = 0.0; 
     620        } 
     621        for (i = 0; i < offset; ++i) { 
     622            dblbuf[bufsiz - i - 1] = 0.0; 
     623        } 
     624        for (i = 0; i < sz; ++i) { 
     625            dblbuf[offset + i] = fltbuf[i]; 
     626        } 
     627        for (i = 0; i < bufsiz / 2; ++i) { 
     628            double tmp = dblbuf[i]; 
     629            dblbuf[i] = dblbuf[i + bufsiz/2]; 
     630            dblbuf[i + bufsiz/2] = tmp; 
     631        } 
     632    } else { 
     633        for (i = 0; i < hs; ++i) { 
     634            dblbuf[i] = fltbuf[i + hs]; 
     635            dblbuf[i + hs] = fltbuf[i]; 
     636        } 
     637    } 
     638 
     639    cd.fft->forwardPolar(dblbuf, cd.mag, cd.phase); 
     640} 
     641 
     642static inline double mod(double x, double y) { return x - (y * floor(x / y)); } 
     643static inline double princarg(double a) { return mod(a + M_PI, -2.0 * M_PI) + M_PI; } 
    499644 
    500645void 
    501 RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, 
     646RubberBandStretcher::Impl::modifyChunk(size_t channel, 
     647                                       size_t outputIncrement, 
    502648                                       bool phaseReset) 
    503649{ 
     650    Profiler profiler("RubberBandStretcher::Impl::modifyChunk"); 
     651 
    504652    ChannelData &cd = *m_channelData[channel]; 
    505653 
     
    508656    } 
    509657 
    510     size_t count = m_windowSize/2; 
    511     size_t pfp = 0; 
    512     double rate = m_stretcher->m_sampleRate; 
    513  
    514     if (!(m_options & OptionPhaseIndependent)) { 
    515  
    516         cd.freqPeak[0] = 0; 
    517  
    518         float freq0 = m_freq0; 
    519         float freq1 = m_freq1; 
    520         float freq2 = m_freq2; 
    521  
    522         // As the stretch ratio increases, so the frequency thresholds 
    523         // for phase lamination should increase.  Beyond a ratio of 
    524         // about 1.5, the threshold should be about 1200Hz; beyond a 
    525         // ratio of 2, we probably want no lamination to happen at all 
    526         // by default.  This calculation aims for more or less that. 
    527         // We only do this if the phase option is OptionPhaseAdaptive 
    528         // (the default), i.e. not Independent or PeakLocked. 
    529  
    530         if (!(m_options & OptionPhasePeakLocked)) { 
    531             float r = getEffectiveRatio(); 
    532             if (r > 1) { 
    533                 float rf0 = 600 + (600 * ((r-1)*(r-1)*(r-1)*2)); 
    534                 float f1ratio = freq1 / freq0; 
    535                 float f2ratio = freq2 / freq0; 
    536                 freq0 = std::max(freq0, rf0); 
    537                 freq1 = freq0 * f1ratio; 
    538                 freq2 = freq0 * f2ratio; 
    539             } 
    540         } 
    541  
    542         size_t limit0 = lrint((freq0 * m_windowSize) / rate); 
    543         size_t limit1 = lrint((freq1 * m_windowSize) / rate); 
    544         size_t limit2 = lrint((freq2 * m_windowSize) / rate); 
    545  
    546         size_t range = 0; 
    547  
    548         if (limit1 < limit0) limit1 = limit0; 
    549         if (limit2 < limit1) limit2 = limit1; 
    550      
    551 //        cerr << "limit0 = " << limit0 << " limit1 = " << limit1 << " limit2 = " << limit2 << endl; 
    552  
    553         int peakCount = 0; 
    554  
    555         for (size_t i = 0; i <= count; ++i) { 
    556  
    557             double mag = cd.mag[i]; 
    558             bool isPeak = true; 
    559  
    560             for (size_t j = 1; j <= range; ++j) { 
    561  
    562                 if (mag < cd.mag[i-j]) { 
    563                     isPeak = false; 
    564                     break; 
    565                 } 
    566  
    567                 if (mag < cd.mag[i+j]) { 
    568                     isPeak = false; 
    569                     break; 
    570                 } 
    571             }         
    572  
    573             if (isPeak) { 
    574  
    575                 // i is a peak bin. 
    576  
    577                 // The previous peak bin was at pfp; make freqPeak entries 
    578                 // from pfp to half-way between pfp and i point at pfp, and 
    579                 // those from the half-way mark to i point at i. 
    580              
    581                 size_t halfway = (pfp + i) / 2; 
    582                 if (halfway == pfp) halfway = pfp + 1; 
    583  
    584                 for (size_t j = pfp + 1; j < halfway; ++j) { 
    585                     cd.freqPeak[j] = pfp; 
    586                 } 
    587                 for (size_t j = halfway; j <= i; ++j) { 
    588                     cd.freqPeak[j] = i; 
    589                 } 
    590  
    591                 pfp = i; 
    592  
    593                 ++peakCount; 
    594             } 
    595  
    596             if (i == limit0) range = 1; 
    597             if (i == limit1) range = 2; 
    598             if (i >= limit2) { 
    599                 range = 3; 
    600                 if (i + range + 1 > count) range = count - i; 
    601             } 
    602         } 
    603  
    604 //        cerr << "peakCount = " << peakCount << endl; 
    605          
    606         cd.freqPeak[count-1] = count-1; 
    607         cd.freqPeak[count] = count; 
    608     } 
    609  
    610     double peakInPhase = 0.0; 
    611     double peakOutPhase = 0.0; 
    612     size_t p, pp; 
    613  
    614     for (size_t i = 0; i <= count; ++i) { 
    615          
    616         if (m_options & OptionPhaseIndependent) { 
    617             p = i; 
    618             pp = i-1; 
    619         } else { 
    620             p = cd.freqPeak[i]; 
    621             pp = cd.freqPeak[i-1]; 
    622         } 
     658    const double rate = m_sampleRate; 
     659    const int sz = m_windowSize; 
     660    const int count = (sz * cd.oversample) / 2; 
     661 
     662    bool unchanged = cd.unchanged && (outputIncrement == m_increment); 
     663    bool fullReset = phaseReset; 
     664    bool laminar = !(m_options & OptionPhaseIndependent); 
     665    bool bandlimited = (m_options & OptionTransientsMixed); 
     666    int bandlow = lrint((150 * sz * cd.oversample) / rate); 
     667    int bandhigh = lrint((1000 * sz * cd.oversample) / rate); 
     668 
     669    float freq0 = m_freq0; 
     670    float freq1 = m_freq1; 
     671    float freq2 = m_freq2; 
     672 
     673    if (laminar) { 
     674        float r = getEffectiveRatio(); 
     675        if (r > 1) { 
     676            float rf0 = 600 + (600 * ((r-1)*(r-1)*(r-1)*2)); 
     677            float f1ratio = freq1 / freq0; 
     678            float f2ratio = freq2 / freq0; 
     679            freq0 = std::max(freq0, rf0); 
     680            freq1 = freq0 * f1ratio; 
     681            freq2 = freq0 * f2ratio; 
     682        } 
     683    } 
     684 
     685    int limit0 = lrint((freq0 * sz * cd.oversample) / rate); 
     686    int limit1 = lrint((freq1 * sz * cd.oversample) / rate); 
     687    int limit2 = lrint((freq2 * sz * cd.oversample) / rate); 
     688 
     689    if (limit1 < limit0) limit1 = limit0; 
     690    if (limit2 < limit1) limit2 = limit1; 
     691     
     692    double prevInstability = 0.0; 
     693    bool prevDirection = false; 
     694 
     695    double distance = 0.0; 
     696    const double maxdist = 8.0; 
     697 
     698    const int lookback = 1; 
     699 
     700    double distacc = 0.0; 
     701 
     702    for (int i = count; i >= 0; i -= lookback) { 
    623703 
    624704        bool resetThis = phaseReset; 
    625705         
    626         if (m_options & OptionTransientsMixed) { 
    627             size_t low = lrint((150 * m_windowSize) / rate); 
    628             size_t high = lrint((1000 * m_windowSize) / rate); 
     706        if (bandlimited) { 
    629707            if (resetThis) { 
    630                 if (i > low && i < high) resetThis = false; 
    631             } 
    632         } 
     708                if (i > bandlow && i < bandhigh) { 
     709                    resetThis = false; 
     710                    fullReset = false; 
     711                } 
     712            } 
     713        } 
     714 
     715        double p = cd.phase[i]; 
     716        double perr = 0.0; 
     717        double outphase = p; 
     718 
     719        double mi = maxdist; 
     720        if (i <= limit0) mi = 0.0; 
     721        else if (i <= limit1) mi = 1.0; 
     722        else if (i <= limit2) mi = 3.0; 
    633723 
    634724        if (!resetThis) { 
    635725 
    636             if (i == 0 || p != pp) { 
    637          
    638                 double omega = (2 * M_PI * m_increment * p) / m_windowSize; 
    639                 double expectedPhase = cd.prevPhase[p] + omega; 
    640                 double phaseError = princarg(cd.phase[p] - expectedPhase); 
    641                 double phaseIncrement = (omega + phaseError) / m_increment; 
    642              
    643                 double unwrappedPhase = cd.unwrappedPhase[p] + 
    644                     outputIncrement * phaseIncrement; 
    645  
    646                 cd.prevPhase[p] = cd.phase[p]; 
    647                 cd.phase[p] = unwrappedPhase; 
    648                 cd.unwrappedPhase[p] = unwrappedPhase; 
    649  
    650                 peakInPhase = cd.prevPhase[p]; 
    651                 peakOutPhase = unwrappedPhase; 
    652             } 
    653  
    654             if (i != p) { 
    655  
    656                 double diffToPeak = peakInPhase - cd.phase[i]; 
    657                 double unwrappedPhase = peakOutPhase - diffToPeak; 
    658                  
    659                 cd.prevPhase[i] = cd.phase[i]; 
    660                 cd.phase[i] = unwrappedPhase; 
    661                 cd.unwrappedPhase[i] = unwrappedPhase; 
    662             } 
     726            double omega = (2 * M_PI * m_increment * i) / (sz * cd.oversample); 
     727 
     728            double pp = cd.prevPhase[i]; 
     729            double ep = pp + omega; 
     730            perr = princarg(p - ep); 
     731 
     732            double instability = fabs(perr - cd.prevError[i]); 
     733            bool direction = (perr > cd.prevError[i]); 
     734 
     735            bool inherit = false; 
     736 
     737            if (laminar) { 
     738                if (distance >= mi) { 
     739                    inherit = false; 
     740                } else if (bandlimited && (i == bandhigh || i == bandlow)) { 
     741                    inherit = false; 
     742                } else if (instability > prevInstability && 
     743                           direction == prevDirection) { 
     744                    inherit = true; 
     745                } 
     746            } 
     747 
     748            double advance = outputIncrement * ((omega + perr) / m_increment); 
     749 
     750            if (inherit) { 
     751                double inherited = 
     752                    cd.unwrappedPhase[i + lookback] - cd.prevPhase[i + lookback]; 
     753                advance = ((advance * distance) + 
     754                           (inherited * (maxdist - distance))) 
     755                    / maxdist; 
     756                outphase = p + advance; 
     757                distacc += distance; 
     758                distance += 1.0; 
     759            } else { 
     760                outphase = cd.unwrappedPhase[i] + advance; 
     761                distance = 0.0; 
     762            } 
     763 
     764            prevInstability = instability; 
     765            prevDirection = direction; 
    663766 
    664767        } else { 
    665             cd.prevPhase[i] = cd.phase[i]; 
    666             cd.unwrappedPhase[i] = cd.phase[i]; 
    667         } 
    668     } 
     768            distance = 0.0; 
     769        } 
     770 
     771        cd.prevError[i] = perr; 
     772        cd.prevPhase[i] = p; 
     773        cd.phase[i] = outphase; 
     774        cd.unwrappedPhase[i] = outphase; 
     775    } 
     776 
     777    if (m_debugLevel > 1) { 
     778        cerr << "mean inheritance distance = " << distacc / count << endl; 
     779    } 
     780 
     781    if (fullReset) unchanged = true; 
     782    cd.unchanged = unchanged; 
     783 
     784    if (unchanged && m_debugLevel > 1) { 
     785        cerr << "frame unchanged on channel " << channel << endl; 
     786    } 
     787}     
     788 
     789 
     790void 
     791RubberBandStretcher::Impl::formantShiftChunk(size_t channel) 
     792{ 
     793    Profiler profiler("RubberBandStretcher::Impl::formantShiftChunk"); 
     794 
     795    ChannelData &cd = *m_channelData[channel]; 
     796 
     797    double *const R__ mag = cd.mag; 
     798    double *const R__ envelope = cd.envelope; 
     799    double *const R__ dblbuf = cd.dblbuf; 
     800 
     801    const int sz = m_windowSize; 
     802    const int hs = m_windowSize/2; 
     803    const double denom = sz; 
     804 
     805     
     806    cd.fft->inverseCepstral(mag, dblbuf); 
     807 
     808    for (int i = 0; i < sz; ++i) { 
     809        dblbuf[i] /= denom; 
     810    } 
     811 
     812    const int cutoff = m_sampleRate / 700; 
     813 
     814//    cerr <<"cutoff = "<< cutoff << ", m_sampleRate/cutoff = " << m_sampleRate/cutoff << endl; 
     815 
     816    dblbuf[0] /= 2; 
     817    dblbuf[cutoff-1] /= 2; 
     818 
     819    for (int i = cutoff; i < sz; ++i) { 
     820        dblbuf[i] = 0.0; 
     821    } 
     822 
     823    cd.fft->forward(dblbuf, envelope, 0); 
     824 
     825 
     826    for (int i = 0; i <= hs; ++i) { 
     827        envelope[i] = exp(envelope[i]); 
     828    } 
     829    for (int i = 0; i <= hs; ++i) { 
     830        mag[i] /= envelope[i]; 
     831    } 
     832 
     833    if (m_pitchScale > 1.0) { 
     834        // scaling up, we want a new envelope that is lower by the pitch factor 
     835        for (int target = 0; target <= hs; ++target) { 
     836            int source = lrint(target * m_pitchScale); 
     837            if (source > int(m_windowSize)) { 
     838                envelope[target] = 0.0; 
     839            } else { 
     840                envelope[target] = envelope[source]; 
     841            } 
     842        } 
     843    } else { 
     844        // scaling down, we want a new envelope that is higher by the pitch factor 
     845        for (int target = hs; target > 0; ) { 
     846            --target; 
     847            int source = lrint(target * m_pitchScale); 
     848            envelope[target] = envelope[source]; 
     849        } 
     850    } 
     851 
     852    for (int i = 0; i <= hs; ++i) { 
     853        mag[i] *= envelope[i]; 
     854    } 
     855 
     856    cd.unchanged = false; 
    669857} 
    670858 
     
    672860RubberBandStretcher::Impl::synthesiseChunk(size_t channel) 
    673861{ 
     862    Profiler profiler("RubberBandStretcher::Impl::synthesiseChunk"); 
     863 
     864 
     865    if ((m_options & OptionFormantPreserved) && 
     866        (m_pitchScale != 1.0)) { 
     867        formantShiftChunk(channel); 
     868    } 
     869 
    674870    ChannelData &cd = *m_channelData[channel]; 
    675871 
    676     cd.fft->inversePolar(cd.mag, cd.phase, cd.dblbuf); 
    677  
    678     for (size_t i = 0; i < m_windowSize/2; ++i) { 
    679         cd.fltbuf[i] = cd.dblbuf[i + m_windowSize/2]; 
    680         cd.fltbuf[i + m_windowSize/2] = cd.dblbuf[i]; 
    681     } 
    682  
    683     // our ffts produced unscaled results 
    684     for (size_t i = 0; i < m_windowSize; ++i) { 
    685         cd.fltbuf[i] = cd.fltbuf[i] / m_windowSize; 
    686     } 
    687  
    688     m_window->cut(cd.fltbuf); 
    689  
    690     for (size_t i = 0; i < m_windowSize; ++i) { 
    691         cd.accumulator[i] += cd.fltbuf[i]; 
     872    double *const R__ dblbuf = cd.dblbuf; 
     873    float *const R__ fltbuf = cd.fltbuf; 
     874    float *const R__ accumulator = cd.accumulator; 
     875    float *const R__ windowAccumulator = cd.windowAccumulator; 
     876     
     877    int sz = m_windowSize; 
     878    int hs = m_windowSize/2; 
     879    int i; 
     880 
     881 
     882    if (!cd.unchanged) { 
     883 
     884        cd.fft->inversePolar(cd.mag, cd.phase, cd.dblbuf); 
     885 
     886        if (cd.oversample > 1) { 
     887 
     888            int bufsiz = sz * cd.oversample; 
     889            int hbs = hs * cd.oversample; 
     890            int offset = (bufsiz - sz) / 2; 
     891 
     892            for (i = 0; i < hbs; ++i) { 
     893                double tmp = dblbuf[i]; 
     894                dblbuf[i] = dblbuf[i + hbs]; 
     895                dblbuf[i + hbs] = tmp; 
     896            } 
     897            for (i = 0; i < sz; ++i) { 
     898                fltbuf[i] = float(dblbuf[i + offset]); 
     899            } 
     900        } else { 
     901            for (i = 0; i < hs; ++i) { 
     902                fltbuf[i] = float(dblbuf[i + hs]); 
     903            } 
     904            for (i = 0; i < hs; ++i) { 
     905                fltbuf[i + hs] = float(dblbuf[i]); 
     906            } 
     907        } 
     908 
     909        float denom = float(sz * cd.oversample); 
     910 
     911        // our ffts produced unscaled results 
     912        for (i = 0; i < sz; ++i) { 
     913            fltbuf[i] = fltbuf[i] / denom; 
     914        } 
     915    } 
     916 
     917    m_window->cut(fltbuf); 
     918 
     919    for (i = 0; i < sz; ++i) { 
     920        accumulator[i] += fltbuf[i]; 
    692921    } 
    693922 
    694923    cd.accumulatorFill = m_windowSize; 
    695924 
    696     float fixed = m_window->getArea() * 1.5; 
    697  
    698     for (size_t i = 0; i < m_windowSize; ++i) { 
     925    float fixed = m_window->getArea() * 1.5f; 
     926 
     927    for (i = 0; i < sz; ++i) { 
    699928        float val = m_window->getValue(i); 
    700         cd.windowAccumulator[i] += val * fixed; 
     929        windowAccumulator[i] += val * fixed; 
    701930    } 
    702931} 
     
    705934RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, bool last) 
    706935{ 
     936    Profiler profiler("RubberBandStretcher::Impl::writeChunk"); 
     937 
    707938    ChannelData &cd = *m_channelData[channel]; 
    708  
     939     
     940    float *const R__ accumulator = cd.accumulator; 
     941    float *const R__ windowAccumulator = cd.windowAccumulator; 
     942 
     943    const int sz = m_windowSize; 
     944    const int si = shiftIncrement; 
     945 
     946    int i; 
     947     
    709948    if (m_debugLevel > 2) { 
    710949        cerr << "writeChunk(" << channel << ", " << shiftIncrement << ", " << last << ")" << endl; 
    711950    } 
    712951 
    713     for (size_t i = 0; i < shiftIncrement; ++i) { 
    714         if (cd.windowAccumulator[i] > 0.f) { 
    715             cd.accumulator[i] /= cd.windowAccumulator[i]; 
     952    for (i = 0; i < si; ++i) { 
     953        if (windowAccumulator[i] > 0.f) { 
     954            accumulator[i] /= windowAccumulator[i]; 
    716955        } 
    717956    } 
     
    724963    } 
    725964 
    726     if (m_pitchScale != 1.0 && cd.resampler) { 
    727  
    728         size_t reqSize = int(ceil(shiftIncrement / m_pitchScale)); 
     965    bool resampledAlready = resampleBeforeStretching(); 
     966 
     967    if (!resampledAlready && 
     968        (m_pitchScale != 1.0 || m_options & OptionPitchHighConsistency) && 
     969        cd.resampler) { 
     970 
     971        size_t reqSize = int(ceil(si / m_pitchScale)); 
    729972        if (reqSize > cd.resamplebufSize) { 
    730973            // This shouldn't normally happen -- the buffer is 
     
    735978            cerr << "WARNING: RubberBandStretcher::Impl::writeChunk: resizing resampler buffer from " 
    736979                      << cd.resamplebufSize << " to " << reqSize << endl; 
    737             cd.resamplebufSize = reqSize; 
    738             if (cd.resamplebuf) delete[] cd.resamplebuf; 
    739             cd.resamplebuf = new float[cd.resamplebufSize]; 
     980            cd.setResampleBufSize(reqSize); 
    740981        } 
    741982 
     
    743984        size_t outframes = cd.resampler->resample(&cd.accumulator, 
    744985                                                  &cd.resamplebuf, 
    745                                                   shiftIncrement, 
     986                                                  si, 
    746987                                                  1.0 / m_pitchScale, 
    747988                                                  last); 
     
    752993 
    753994    } else { 
    754         writeOutput(*cd.outbuf, cd.accumulator, 
    755                     shiftIncrement, cd.outCount, theoreticalOut); 
    756     } 
    757      
    758     for (size_t i = 0; i < m_windowSize - shiftIncrement; ++i) { 
    759         cd.accumulator[i] = cd.accumulator[i + shiftIncrement]; 
    760     } 
    761      
    762     for (size_t i = m_windowSize - shiftIncrement; i < m_windowSize; ++i) { 
    763         cd.accumulator[i] = 0.0f; 
    764     } 
    765      
    766     for (size_t i = 0; i < m_windowSize - shiftIncrement; ++i) { 
    767         cd.windowAccumulator[i] = cd.windowAccumulator[i + shiftIncrement]; 
    768     } 
    769      
    770     for (size_t i = m_windowSize - shiftIncrement; i < m_windowSize; ++i) { 
    771         cd.windowAccumulator[i] = 0.0f; 
    772     } 
    773      
    774     if (cd.accumulatorFill > shiftIncrement) { 
    775         cd.accumulatorFill -= shiftIncrement; 
     995        writeOutput(*cd.outbuf, accumulator, 
     996                    si, cd.outCount, theoreticalOut); 
     997    } 
     998     
     999    for (i = 0; i < sz - si; ++i) { 
     1000        accumulator[i] = accumulator[i + si]; 
     1001    } 
     1002     
     1003    for (i = sz - si; i < sz; ++i) { 
     1004        accumulator[i] = 0.0f; 
     1005    } 
     1006     
     1007    for (i = 0; i < sz - si; ++i) { 
     1008        windowAccumulator[i] = windowAccumulator[i + si]; 
     1009    } 
     1010     
     1011    for (i = sz - si; i < sz; ++i) { 
     1012        windowAccumulator[i] = 0.0f; 
     1013    } 
     1014     
     1015    if (int(cd.accumulatorFill) > si) { 
     1016        cd.accumulatorFill -= si; 
    7761017    } else { 
    7771018        cd.accumulatorFill = 0; 
     
    7881029RubberBandStretcher::Impl::writeOutput(RingBuffer<float> &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut) 
    7891030{ 
     1031    Profiler profiler("RubberBandStretcher::Impl::writeOutput"); 
     1032 
    7901033    // In non-RT mode, we don't want to write the first startSkip 
    7911034    // samples, because the first chunk is centred on the start of the 
     
    8601103RubberBandStretcher::Impl::available() const 
    8611104{ 
     1105    Profiler profiler("RubberBandStretcher::Impl::available"); 
     1106 
    8621107    if (m_threaded) { 
    8631108        MutexLocker locker(&m_threadSetMutex); 
     
    9071152RubberBandStretcher::Impl::retrieve(float *const *output, size_t samples) const 
    9081153{ 
     1154    Profiler profiler("RubberBandStretcher::Impl::retrieve"); 
     1155 
    9091156    size_t got = samples; 
    9101157 
  • trunk/rubberband/src/Thread.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1616 
    1717#include <iostream> 
     18#include <cstdlib> 
    1819 
    1920#include <sys/time.h> 
    2021#include <time.h> 
    21  
    22 //#define DEBUG_THREAD 1 
    23 //#define DEBUG_MUTEX 1 
    24 //#define DEBUG_CONDITION 1 
    2522 
    2623using std::cerr; 
     
    108105} 
    109106 
    110 Mutex::Mutex() : 
    111     m_locked(false) 
     107Mutex::Mutex() 
     108#ifndef NO_THREAD_CHECKS 
     109    : 
     110    m_lockedBy(-1) 
     111#endif 
    112112{ 
    113113    m_mutex = CreateMutex(NULL, FALSE, NULL); 
     
    128128Mutex::lock() 
    129129{ 
    130     if (m_locked) { 
     130#ifndef NO_THREAD_CHECKS 
     131    DWORD tid = GetCurrentThreadId(); 
     132    if (m_lockedBy == tid) { 
    131133        cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl; 
    132134    } 
    133 #ifdef DEBUG_MUTEX 
    134     cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Want to lock mutex " << &m_mutex << endl; 
     135#endif 
     136#ifdef DEBUG_MUTEX 
     137    cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl; 
    135138#endif 
    136139    WaitForSingleObject(m_mutex, INFINITE); 
    137     m_locked = true; 
    138 #ifdef DEBUG_MUTEX 
    139     cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Locked mutex " << &m_mutex << endl; 
     140#ifndef NO_THREAD_CHECKS 
     141    m_lockedBy = tid; 
     142#endif 
     143#ifdef DEBUG_MUTEX 
     144    cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl; 
    140145#endif 
    141146} 
     
    144149Mutex::unlock() 
    145150{ 
    146 #ifdef DEBUG_MUTEX 
    147     cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Unlocking mutex " << &m_mutex << endl; 
    148 #endif 
    149     m_locked = false; 
     151#ifndef NO_THREAD_CHECKS 
     152    DWORD tid = GetCurrentThreadId(); 
     153    if (m_lockedBy != tid) { 
     154        cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl; 
     155        return; 
     156    } 
     157#endif 
     158#ifdef DEBUG_MUTEX 
     159    cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl; 
     160#endif 
     161#ifndef NO_THREAD_CHECKS 
     162    m_lockedBy = -1; 
     163#endif 
    150164    ReleaseMutex(m_mutex); 
    151165} 
     
    154168Mutex::trylock() 
    155169{ 
     170#ifndef NO_THREAD_CHECKS 
     171    DWORD tid = GetCurrentThreadId(); 
     172#endif 
    156173    DWORD result = WaitForSingleObject(m_mutex, 0); 
    157174    if (result == WAIT_TIMEOUT || result == WAIT_FAILED) { 
    158175#ifdef DEBUG_MUTEX 
    159         cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Mutex " << &m_mutex << " unavailable" << endl; 
     176        cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl; 
    160177#endif 
    161178        return false; 
    162179    } else { 
    163         m_locked = true; 
    164 #ifdef DEBUG_MUTEX 
    165         cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; 
     180#ifndef NO_THREAD_CHECKS 
     181        m_lockedBy = tid; 
     182#endif 
     183#ifdef DEBUG_MUTEX 
     184        cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; 
    166185#endif 
    167186        return true; 
     
    170189 
    171190Condition::Condition(string name) : 
    172     m_name(name), 
    173191    m_locked(false) 
     192#ifdef DEBUG_CONDITION 
     193    , m_name(name) 
     194#endif 
    174195{ 
    175196    m_mutex = CreateMutex(NULL, FALSE, NULL); 
     
    344365} 
    345366 
    346 Mutex::Mutex() : 
     367Mutex::Mutex() 
     368#ifndef NO_THREAD_CHECKS 
     369    : 
     370    m_lockedBy(0), 
    347371    m_locked(false) 
     372#endif 
    348373{ 
    349374    pthread_mutex_init(&m_mutex, 0); 
     
    364389Mutex::lock() 
    365390{ 
    366     if (m_locked) { 
     391#ifndef NO_THREAD_CHECKS 
     392    pthread_t tid = pthread_self(); 
     393    if (m_locked && m_lockedBy == tid) { 
    367394        cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl; 
    368395    } 
    369 #ifdef DEBUG_MUTEX 
    370     cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Want to lock mutex " << &m_mutex << endl; 
     396#endif 
     397#ifdef DEBUG_MUTEX 
     398    cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl; 
    371399#endif 
    372400    pthread_mutex_lock(&m_mutex); 
     401#ifndef NO_THREAD_CHECKS 
     402    m_lockedBy = tid; 
    373403    m_locked = true; 
    374 #ifdef DEBUG_MUTEX 
    375     cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Locked mutex " << &m_mutex << endl; 
     404#endif 
     405#ifdef DEBUG_MUTEX 
     406    cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl; 
    376407#endif 
    377408} 
     
    380411Mutex::unlock() 
    381412{ 
    382 #ifdef DEBUG_MUTEX 
    383     cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Unlocking mutex " << &m_mutex << endl; 
    384 #endif 
     413#ifndef NO_THREAD_CHECKS 
     414    pthread_t tid = pthread_self(); 
     415    if (!m_locked) { 
     416        cerr << "ERROR: Mutex " << &m_mutex << " not locked in unlock" << endl; 
     417        return; 
     418    } else if (m_lockedBy != tid) { 
     419        cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl; 
     420        return; 
     421    } 
     422#endif 
     423#ifdef DEBUG_MUTEX 
     424    cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl; 
     425#endif 
     426#ifndef NO_THREAD_CHECKS 
    385427    m_locked = false; 
     428#endif 
    386429    pthread_mutex_unlock(&m_mutex); 
    387430} 
     
    390433Mutex::trylock() 
    391434{ 
     435#ifndef NO_THREAD_CHECKS 
     436    pthread_t tid = pthread_self(); 
     437#endif 
    392438    if (pthread_mutex_trylock(&m_mutex)) { 
    393439#ifdef DEBUG_MUTEX 
    394         cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Mutex " << &m_mutex << " unavailable" << endl; 
     440        cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl; 
    395441#endif 
    396442        return false; 
    397443    } else { 
     444#ifndef NO_THREAD_CHECKS 
     445        m_lockedBy = tid; 
    398446        m_locked = true; 
    399 #ifdef DEBUG_MUTEX 
    400         cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; 
     447#endif 
     448#ifdef DEBUG_MUTEX 
     449        cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; 
    401450#endif 
    402451        return true; 
     
    405454 
    406455Condition::Condition(string name) : 
    407     m_locked(false), 
    408     m_name(name) 
     456    m_locked(false) 
     457#ifdef DEBUG_CONDITION 
     458    , m_name(name) 
     459#endif 
    409460{ 
    410461    pthread_mutex_init(&m_mutex, 0); 
  • trunk/rubberband/src/Thread.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    2323 
    2424#include <string> 
     25 
     26//#define DEBUG_THREAD 1 
     27//#define DEBUG_MUTEX 1 
     28//#define DEBUG_CONDITION 1 
    2529 
    2630namespace RubberBand 
     
    7478#ifdef _WIN32 
    7579    HANDLE m_mutex; 
    76     bool m_locked; 
     80#ifndef NO_THREAD_CHECKS 
     81    DWORD m_lockedBy; 
     82#endif 
    7783#else 
    7884    pthread_mutex_t m_mutex; 
     85#ifndef NO_THREAD_CHECKS 
     86    pthread_t m_lockedBy; 
    7987    bool m_locked; 
     88#endif 
    8089#endif 
    8190}; 
     
    114123     
    115124private: 
     125 
    116126#ifdef _WIN32 
    117127    HANDLE m_mutex; 
     128    HANDLE m_condition; 
    118129    bool m_locked; 
    119     HANDLE m_condition; 
    120     std::string m_name; 
    121130#else 
    122131    pthread_mutex_t m_mutex; 
     132    pthread_cond_t m_condition; 
    123133    bool m_locked; 
    124     pthread_cond_t m_condition; 
     134#endif 
     135#ifdef DEBUG_CONDITION 
    125136    std::string m_name; 
    126137#endif 
  • trunk/rubberband/src/Window.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1313*/ 
    1414 
    15 #include "AudioCurve.h" 
    16  
    17 namespace RubberBand 
    18 { 
    19  
    20 AudioCurve::AudioCurve(size_t sampleRate, size_t windowSize) : 
    21     m_sampleRate(sampleRate), 
    22     m_windowSize(windowSize) 
    23 { 
    24 } 
    25  
    26 AudioCurve::~AudioCurve() 
    27 { 
    28 } 
     15#include "Window.h" 
    2916 
    3017 
    31 } 
  • trunk/rubberband/src/Window.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1818#include <cmath> 
    1919#include <iostream> 
     20#include <cstdlib> 
    2021#include <map> 
     22 
     23#include "sysutils.h" 
    2124 
    2225namespace RubberBand { 
     
    4144     * Construct a windower of the given type. 
    4245     */ 
    43     Window(WindowType type, size_t size) : m_type(type), m_size(size) { encache(); } 
     46    Window(WindowType type, int size) : m_type(type), m_size(size) { encache(); } 
    4447    Window(const Window &w) : m_type(w.m_type), m_size(w.m_size) { encache(); } 
    4548    Window &operator=(const Window &w) { 
     
    5255    virtual ~Window() { delete[] m_cache; } 
    5356     
    54     void cut(T *src) const { cut(src, src); } 
    55     void cut(T *src, T *dst) const { 
    56         for (size_t i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i]; 
     57    void cut(T *R__ src) const 
     58    { 
     59        const int sz = m_size; 
     60        for (int i = 0; i < sz; ++i) { 
     61            src[i] *= m_cache[i]; 
     62        } 
     63    } 
     64 
     65    void cut(T *R__ src, T *dst) const { 
     66        const int sz = m_size; 
     67        for (int i = 0; i < sz; ++i) { 
     68            dst[i] = src[i]; 
     69        } 
     70        for (int i = 0; i < sz; ++i) { 
     71            dst[i] *= m_cache[i]; 
     72        } 
    5773    } 
    5874 
    5975    T getArea() { return m_area; } 
    60     T getValue(size_t i) { return m_cache[i]; } 
     76    T getValue(int i) { return m_cache[i]; } 
    6177 
    6278    WindowType getType() const { return m_type; } 
    63     size_t getSize() const { return m_size; } 
     79    int getSize() const { return m_size; } 
    6480 
    6581protected: 
    6682    WindowType m_type; 
    67     size_t m_size; 
    68     T *m_cache; 
     83    int m_size; 
     84    T *R__ m_cache; 
    6985    T m_area; 
    7086     
  • trunk/rubberband/src/sysutils.cpp

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    2727 
    2828#include <iostream> 
     29 
    2930 
    3031namespace RubberBand { 
     
    8283#ifdef _WIN32 
    8384 
    84 void gettimeofday(struct timeval *tv, void *tz) 
     85int gettimeofday(struct timeval *tv, void *tz) 
    8586{ 
    8687    union {  
     
    9293    tv->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL);  
    9394    tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL);  
     95    return 0; 
    9496} 
    9597 
     
    101103#endif 
    102104 
     105 
     106float *allocFloat(float *ptr, int count) 
     107{ 
     108    if (ptr) free((void *)ptr); 
     109    void *allocated; 
     110#ifndef _WIN32 
     111    if (!posix_memalign(&allocated, 16, count * sizeof(float))) 
     112#endif 
     113        allocated = malloc(count * sizeof(float)); 
     114    for (int i = 0; i < count; ++i) ((float *)allocated)[i] = 0.f; 
     115    return (float *)allocated; 
     116} 
     117 
     118float *allocFloat(int count) 
     119{ 
     120    return allocFloat(0, count); 
     121} 
     122 
     123void freeFloat(float *ptr) 
     124{ 
     125    if (ptr) free(ptr); 
     126} 
     127       
     128double *allocDouble(double *ptr, int count) 
     129{ 
     130    if (ptr) free((void *)ptr); 
     131    void *allocated; 
     132#ifndef _WIN32 
     133    if (!posix_memalign(&allocated, 16, count * sizeof(double))) 
     134#endif 
     135        allocated = malloc(count * sizeof(double)); 
     136    for (int i = 0; i < count; ++i) ((double *)allocated)[i] = 0.f; 
     137    return (double *)allocated; 
     138} 
     139 
     140double *allocDouble(int count) 
     141{ 
     142    return allocDouble(0, count); 
     143} 
     144 
     145void freeDouble(double *ptr) 
     146{ 
     147    if (ptr) free(ptr); 
     148} 
     149  
     150 
    103151} 
    104152 
  • trunk/rubberband/src/sysutils.h

    r234 r267  
    44    Rubber Band 
    55    An audio time-stretching and pitch-shifting library. 
    6     Copyright 2007 Chris Cannam. 
     6    Copyright 2007-2008 Chris Cannam. 
    77     
    88    This program is free software; you can redistribute it and/or 
     
    1616#define _RUBBERBAND_SYSINFO_H_ 
    1717 
     18#ifdef __MSVC__ 
     19#include "bsd-3rdparty/float_cast/float_cast.h" 
     20#define R__ __restrict 
     21#endif 
     22 
     23#ifdef __GNUC__ 
     24#define R__ __restrict__ 
     25#endif 
     26 
     27#ifndef R__ 
     28#define R__ 
     29#endif 
     30 
     31#ifdef __MINGW32__ 
     32#include <malloc.h> 
     33#endif 
     34 
     35#ifdef __MSVC__ 
     36#define alloca _alloca 
     37#endif 
     38 
    1839namespace RubberBand { 
    1940 
     
    2142 
    2243#ifdef _WIN32 
     44 
    2345struct timeval { long tv_sec; long tv_usec; }; 
    24 void gettimeofday(struct timeval *p, void *tz); 
     46int gettimeofday(struct timeval *p, void *tz); 
     47 
    2548void usleep(unsigned long); 
     49 
    2650#endif 
     51 
     52extern float *allocFloat(int);     
     53extern float *allocFloat(float *, int); 
     54extern void freeFloat(float *); 
     55 
     56extern double *allocDouble(int);     
     57extern double *allocDouble(double *, int); 
     58extern void freeDouble(double *); 
    2759 
    2860}