mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-20 13:46:30 +01:00
integrate the not-yet-released RubberBand library into ardour for timefx
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2704 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
e9e328b469
commit
678de81b96
11 changed files with 398 additions and 34 deletions
69
SConstruct
69
SConstruct
|
|
@ -64,6 +64,7 @@ class LibraryInfo(Environment):
|
||||||
self.Append (LIBPATH = other.get ('LIBPATH', []))
|
self.Append (LIBPATH = other.get ('LIBPATH', []))
|
||||||
self.Append (CPPPATH = other.get('CPPPATH', []))
|
self.Append (CPPPATH = other.get('CPPPATH', []))
|
||||||
self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
|
self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
|
||||||
|
self.Append (CCFLAGS = other.get('CCFLAGS', []))
|
||||||
self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
|
self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
|
||||||
self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
|
self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
|
||||||
#doing LINKFLAGS breaks -framework
|
#doing LINKFLAGS breaks -framework
|
||||||
|
|
@ -434,6 +435,12 @@ def CheckPKGVersion(context, name, version):
|
||||||
context.Result( ret )
|
context.Result( ret )
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def CheckPKGExists(context, name):
|
||||||
|
context.Message ('Checking for %s...' % name)
|
||||||
|
ret = context.TryAction('pkg-config --exists %s' % name)[0]
|
||||||
|
context.Result (ret)
|
||||||
|
return ret
|
||||||
|
|
||||||
conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
|
conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
|
||||||
'CheckPKGVersion' : CheckPKGVersion })
|
'CheckPKGVersion' : CheckPKGVersion })
|
||||||
|
|
||||||
|
|
@ -472,26 +479,20 @@ libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
|
||||||
libraries['samplerate'] = LibraryInfo()
|
libraries['samplerate'] = LibraryInfo()
|
||||||
libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
|
libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
|
||||||
|
|
||||||
libraries['rubberband'] = LibraryInfo()
|
|
||||||
#
|
|
||||||
# chris cannam's rubberband has not yet been released
|
|
||||||
#
|
|
||||||
if os.path.exists ('libs/rubberband'):
|
|
||||||
libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
|
|
||||||
LIBPATH='#libs/rubberband/lib',
|
|
||||||
CPPPATH='#libs/rubberband/src',
|
|
||||||
CXXFLAGS='-DUSE_RUBBERBAND')
|
|
||||||
|
|
||||||
if env['FFT_ANALYSIS']:
|
|
||||||
libraries['fftw3f'] = LibraryInfo()
|
libraries['fftw3f'] = LibraryInfo()
|
||||||
libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
|
libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
|
||||||
|
|
||||||
|
libraries['fftw3'] = LibraryInfo()
|
||||||
|
libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
|
||||||
|
|
||||||
|
if env['FFT_ANALYSIS']:
|
||||||
#
|
#
|
||||||
# Check for fftw3 header as well as the library
|
# Check for fftw3 header as well as the library
|
||||||
conf = Configure (libraries['fftw3f'])
|
#
|
||||||
|
conf = env.Configure()
|
||||||
if conf.CheckHeader ('fftw3.h') == False:
|
if conf.CheckHeader ('fftw3.h') == False:
|
||||||
print "FFT Analysis cannot be compiled without the FFTW3 headers, which don't seem to be installed"
|
print ('FFT Analysis cannot be compiled without the FFTW3 headers, which do not seem to be installed')
|
||||||
sys.exit (1)
|
sys.exit (1)
|
||||||
libraries['fftw3f'] = conf.Finish();
|
|
||||||
|
|
||||||
libraries['jack'] = LibraryInfo()
|
libraries['jack'] = LibraryInfo()
|
||||||
libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
|
libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
|
||||||
|
|
@ -732,6 +733,35 @@ def prep_libcheck(topenv, libinfo):
|
||||||
|
|
||||||
prep_libcheck(env, env)
|
prep_libcheck(env, env)
|
||||||
|
|
||||||
|
#
|
||||||
|
# check for VAMP and rubberband (currently optional)
|
||||||
|
#
|
||||||
|
|
||||||
|
libraries['vamp'] = LibraryInfo()
|
||||||
|
|
||||||
|
env['RUBBERBAND'] = False
|
||||||
|
|
||||||
|
conf = Configure (libraries['vamp'], custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
|
||||||
|
|
||||||
|
if conf.CheckPKGExists('vamp-sdk'):
|
||||||
|
have_vamp = True
|
||||||
|
libraries['vamp'].ParseConfig('pkg-config --cflags --libs vamp-sdk')
|
||||||
|
else:
|
||||||
|
have_vamp = False
|
||||||
|
|
||||||
|
libraries['vamp'] = conf.Finish ()
|
||||||
|
|
||||||
|
if have_vamp:
|
||||||
|
if os.path.exists ('libs/rubberband/src'):
|
||||||
|
conf = Configure (libraries['vamp'])
|
||||||
|
if conf.CheckHeader ('fftw3.h'):
|
||||||
|
env['RUBBERBAND'] = True
|
||||||
|
libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
|
||||||
|
LIBPATH='#libs/rubberband',
|
||||||
|
CPPPATH='#libs/rubberband/rubberband',
|
||||||
|
CCFLAGS='-DUSE_RUBBERBAND')
|
||||||
|
libraries['vamp'] = conf.Finish ()
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check for libusb
|
# Check for libusb
|
||||||
|
|
||||||
|
|
@ -972,7 +1002,6 @@ else:
|
||||||
CPPPATH='#libs/appleutility')
|
CPPPATH='#libs/appleutility')
|
||||||
|
|
||||||
coredirs = [
|
coredirs = [
|
||||||
'libs/soundtouch',
|
|
||||||
'templates'
|
'templates'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1039,6 +1068,14 @@ else:
|
||||||
env['POWERMATE'] = 0
|
env['POWERMATE'] = 0
|
||||||
env['TRANZPORT'] = 0
|
env['TRANZPORT'] = 0
|
||||||
|
|
||||||
|
#
|
||||||
|
# timestretch libraries
|
||||||
|
#
|
||||||
|
|
||||||
|
timefx_subdirs = ['libs/soundtouch']
|
||||||
|
if env['RUBBERBAND']:
|
||||||
|
timefx_subdirs += ['libs/rubberband']
|
||||||
|
|
||||||
opts.Save('scache.conf', env)
|
opts.Save('scache.conf', env)
|
||||||
Help(opts.GenerateHelpText(env))
|
Help(opts.GenerateHelpText(env))
|
||||||
|
|
||||||
|
|
@ -1212,7 +1249,7 @@ env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
|
||||||
for subdir in coredirs:
|
for subdir in coredirs:
|
||||||
SConscript (subdir + '/SConscript')
|
SConscript (subdir + '/SConscript')
|
||||||
|
|
||||||
for sublistdir in [ subdirs, gtk_subdirs, surface_subdirs ]:
|
for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
|
||||||
for subdir in sublistdir:
|
for subdir in sublistdir:
|
||||||
SConscript (subdir + '/SConscript')
|
SConscript (subdir + '/SConscript')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,6 @@ gtkardour.Merge ([
|
||||||
libraries['gtk2'],
|
libraries['gtk2'],
|
||||||
libraries['xml'],
|
libraries['xml'],
|
||||||
libraries['xslt'],
|
libraries['xslt'],
|
||||||
libraries['soundtouch'],
|
|
||||||
libraries['rubberband'],
|
|
||||||
libraries['samplerate'],
|
libraries['samplerate'],
|
||||||
libraries['jack']
|
libraries['jack']
|
||||||
])
|
])
|
||||||
|
|
@ -76,6 +74,11 @@ if gtkardour['FFT_ANALYSIS']:
|
||||||
gtkardour.Merge ([libraries['fftw3f']])
|
gtkardour.Merge ([libraries['fftw3f']])
|
||||||
gtkardour.Append(CCFLAGS='-DFFT_ANALYSIS')
|
gtkardour.Append(CCFLAGS='-DFFT_ANALYSIS')
|
||||||
|
|
||||||
|
if gtkardour['RUBBERBAND']:
|
||||||
|
gtkardour.Merge ([ libraries['rubberband'], libraries['vamp'], libraries['fftw3f'], libraries['fftw3'] ])
|
||||||
|
else:
|
||||||
|
gtkardour.Merge ([ libraries['soundtouch'] ])
|
||||||
|
|
||||||
skipped_files=Split("""
|
skipped_files=Split("""
|
||||||
connection_editor.cc
|
connection_editor.cc
|
||||||
""")
|
""")
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ export ARDOUR_PATH=gtk2_ardour/icons:gtk2_ardour/pixmaps:gtk2_ardour
|
||||||
export GTK_PATH=libs/clearlooks
|
export GTK_PATH=libs/clearlooks
|
||||||
|
|
||||||
|
|
||||||
export LD_LIBRARY_PATH=libs/surfaces/control_protocol:libs/ardour:libs/midi++2:libs/pbd:libs/soundtouch:libs/gtkmm2ext:libs/sigc++2:libs/glibmm2:libs/gtkmm2/atk:libs/gtkmm2/pango:libs/gtkmm2/gdk:libs/gtkmm2/gtk:libs/libgnomecanvasmm:libs/libsndfile:libs/appleutility:$LD_LIBRARY_PATH
|
export LD_LIBRARY_PATH=libs/surfaces/control_protocol:libs/ardour:libs/midi++2:libs/pbd:libs/rubberband:libs/soundtouch:libs/gtkmm2ext:libs/sigc++2:libs/glibmm2:libs/gtkmm2/atk:libs/gtkmm2/pango:libs/gtkmm2/gdk:libs/gtkmm2/gtk:libs/libgnomecanvasmm:libs/libsndfile:libs/appleutility:$LD_LIBRARY_PATH
|
||||||
|
|
||||||
# DYLD_LIBRARY_PATH is for darwin.
|
# DYLD_LIBRARY_PATH is for darwin.
|
||||||
export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
|
export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,8 @@
|
||||||
<menuitem action='finish-add-range'/>
|
<menuitem action='finish-add-range'/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<menuitem action='select-all'/>
|
<menuitem action='select-all'/>
|
||||||
|
<menuitem action='deselect-all'/>
|
||||||
|
<menuitem action='invert-selection'/>
|
||||||
<menuitem action='select-all-after-edit-cursor'/>
|
<menuitem action='select-all-after-edit-cursor'/>
|
||||||
<menuitem action='select-all-before-edit-cursor'/>
|
<menuitem action='select-all-before-edit-cursor'/>
|
||||||
<menuitem action='select-all-after-playhead'/>
|
<menuitem action='select-all-after-playhead'/>
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@
|
||||||
|
|
||||||
#include <pbd/stateful.h>
|
#include <pbd/stateful.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
#include <ardour/stretch.h>
|
|
||||||
#include <ardour/tempo.h>
|
#include <ardour/tempo.h>
|
||||||
|
#include <ardour/stretch.h>
|
||||||
#include <ardour/location.h>
|
#include <ardour/location.h>
|
||||||
#include <ardour/audioregion.h>
|
#include <ardour/audioregion.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5048,7 +5048,11 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position();
|
nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position();
|
||||||
|
#ifdef USE_RUBBERBAND
|
||||||
|
float percentage = (float) ((double) newlen / (double) clicked_regionview->region()->length());
|
||||||
|
#else
|
||||||
float percentage = (float) ((double) newlen - (double) clicked_regionview->region()->length()) / ((double) newlen) * 100.0f;
|
float percentage = (float) ((double) newlen - (double) clicked_regionview->region()->length()) / ((double) newlen) * 100.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
begin_reversible_command (_("timestretch"));
|
begin_reversible_command (_("timestretch"));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,6 @@ sndfile_helpers.cc
|
||||||
sndfilesource.cc
|
sndfilesource.cc
|
||||||
source.cc
|
source.cc
|
||||||
source_factory.cc
|
source_factory.cc
|
||||||
stretch.cc
|
|
||||||
tempo.cc
|
tempo.cc
|
||||||
utils.cc
|
utils.cc
|
||||||
version.cc
|
version.cc
|
||||||
|
|
@ -106,6 +105,7 @@ vst_files = [ 'vst_plugin.cc', 'session_vst.cc' ]
|
||||||
audiounit_files = [ 'audio_unit.cc' ]
|
audiounit_files = [ 'audio_unit.cc' ]
|
||||||
coreaudio_files = [ 'coreaudiosource.cc' ]
|
coreaudio_files = [ 'coreaudiosource.cc' ]
|
||||||
extra_sources = [ ]
|
extra_sources = [ ]
|
||||||
|
timefx_sources = [ ]
|
||||||
|
|
||||||
if ardour['VST']:
|
if ardour['VST']:
|
||||||
extra_sources += vst_files
|
extra_sources += vst_files
|
||||||
|
|
@ -260,12 +260,18 @@ ardour.Merge ([
|
||||||
libraries['samplerate'],
|
libraries['samplerate'],
|
||||||
libraries['sigc2'],
|
libraries['sigc2'],
|
||||||
libraries['pbd'],
|
libraries['pbd'],
|
||||||
libraries['soundtouch'],
|
|
||||||
libraries['midi++2'],
|
libraries['midi++2'],
|
||||||
libraries['glib2'],
|
libraries['glib2'],
|
||||||
libraries['glibmm2']
|
libraries['glibmm2']
|
||||||
])
|
])
|
||||||
|
|
||||||
|
if ardour['RUBBERBAND']:
|
||||||
|
ardour.Merge ([ libraries['rubberband'], libraries['vamp'], libraries['fftw3f'] ])
|
||||||
|
timefx_sources += [ 'rb_stretch.cc' ]
|
||||||
|
else:
|
||||||
|
ardour.Merge ([ libraries['soundtouch'] ])
|
||||||
|
timefx_sources += [ 'st_stretch.cc' ]
|
||||||
|
|
||||||
if ardour['LIBLO']:
|
if ardour['LIBLO']:
|
||||||
ardour.Merge ([ libraries['lo'] ])
|
ardour.Merge ([ libraries['lo'] ])
|
||||||
|
|
||||||
|
|
@ -305,12 +311,12 @@ if env['FPU_OPTIMIZATION']:
|
||||||
arch_specific_objects = env.SharedAsmObject('sse_functions_64bit.os', 'sse_functions_64bit.s')
|
arch_specific_objects = env.SharedAsmObject('sse_functions_64bit.os', 'sse_functions_64bit.s')
|
||||||
always_sse_objects += [ sse_env.SharedObject (source = 'sse_functions_xmm.cc') ]
|
always_sse_objects += [ sse_env.SharedObject (source = 'sse_functions_xmm.cc') ]
|
||||||
|
|
||||||
libardour = ardour.SharedLibrary('ardour', ardour_files + always_sse_objects + extra_sources + arch_specific_objects)
|
libardour = ardour.SharedLibrary('ardour', ardour_files + always_sse_objects + timefx_sources + extra_sources + arch_specific_objects)
|
||||||
|
|
||||||
Default(libardour)
|
Default(libardour)
|
||||||
|
|
||||||
if env['NLS']:
|
if env['NLS']:
|
||||||
i18n (ardour, ardour_files + vst_files + coreaudio_files + audiounit_files, env)
|
i18n (ardour, ardour_files + vst_files + coreaudio_files + timefx_sources + audiounit_files, env)
|
||||||
|
|
||||||
|
|
||||||
env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2'), libardour))
|
env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2'), libardour))
|
||||||
|
|
@ -318,6 +324,8 @@ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ar
|
||||||
env.Alias('version', ardour.VersionBuild(['version.cc', 'ardour/version.h'], []))
|
env.Alias('version', ardour.VersionBuild(['version.cc', 'ardour/version.h'], []))
|
||||||
|
|
||||||
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||||
[ 'SConscript', 'i18n.h', 'gettext.h', 'sse_functions_xmm.cc', 'sse_functions.s', 'sse_functions_64bit.s' ] +
|
[ 'SConscript', 'i18n.h', 'gettext.h' ] +
|
||||||
|
[ 'sse_functions_xmm.cc', 'sse_functions.s', 'sse_functions_64bit.s' ] +
|
||||||
|
[ 'rb_stretch.cc', 'st_stretch.cc' ] +
|
||||||
ardour_files + osc_files + vst_files + coreaudio_files + audiounit_files +
|
ardour_files + osc_files + vst_files + coreaudio_files + audiounit_files +
|
||||||
glob.glob('po/*.po') + glob.glob('ardour/*.h')))
|
glob.glob('po/*.po') + glob.glob('ardour/*.h')))
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,10 @@
|
||||||
#define __ardour_stretch_h__
|
#define __ardour_stretch_h__
|
||||||
|
|
||||||
#include <ardour/audiofilter.h>
|
#include <ardour/audiofilter.h>
|
||||||
|
|
||||||
|
#ifndef USE_RUBBERBAND
|
||||||
#include <soundtouch/SoundTouch.h>
|
#include <soundtouch/SoundTouch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
|
@ -42,7 +45,10 @@ class Stretch : public AudioFilter {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TimeStretchRequest& tsr;
|
TimeStretchRequest& tsr;
|
||||||
|
|
||||||
|
#ifndef USE_RUBBERBAND
|
||||||
soundtouch::SoundTouch st;
|
soundtouch::SoundTouch st;
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
276
libs/ardour/rb_stretch.cc
Normal file
276
libs/ardour/rb_stretch.cc
Normal file
|
|
@ -0,0 +1,276 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2004-2007 Paul Davis
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <pbd/error.h>
|
||||||
|
#include "/usr/local/music/src/rubberband/rubberband/RubberBandStretcher.h" //!!!
|
||||||
|
|
||||||
|
#include <ardour/types.h>
|
||||||
|
#include <ardour/stretch.h>
|
||||||
|
#include <ardour/audiofilesource.h>
|
||||||
|
#include <ardour/session.h>
|
||||||
|
#include <ardour/audioregion.h>
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
using namespace PBD;
|
||||||
|
using namespace RubberBand;
|
||||||
|
|
||||||
|
Stretch::Stretch (Session& s, TimeStretchRequest& req)
|
||||||
|
: AudioFilter (s)
|
||||||
|
, tsr (req)
|
||||||
|
|
||||||
|
{
|
||||||
|
tsr.progress = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stretch::~Stretch ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Stretch::run (boost::shared_ptr<AudioRegion> region)
|
||||||
|
{
|
||||||
|
SourceList nsrcs;
|
||||||
|
nframes_t done;
|
||||||
|
int ret = -1;
|
||||||
|
const nframes_t bufsize = 256;
|
||||||
|
gain_t* gain_buffer = 0;
|
||||||
|
Sample** buffers = 0;
|
||||||
|
char suffix[32];
|
||||||
|
string new_name;
|
||||||
|
string::size_type at;
|
||||||
|
nframes_t pos = 0;
|
||||||
|
int avail = 0;
|
||||||
|
|
||||||
|
RubberBandStretcher stretcher (session.frame_rate(), region->n_channels(),
|
||||||
|
RubberBandStretcher::DefaultOptions,
|
||||||
|
tsr.fraction, 1.0);
|
||||||
|
|
||||||
|
stretcher.setExpectedInputDuration(region->length());
|
||||||
|
stretcher.setDebugLevel(1);
|
||||||
|
|
||||||
|
tsr.progress = 0.0f;
|
||||||
|
tsr.done = false;
|
||||||
|
|
||||||
|
uint32_t channels = region->n_channels();
|
||||||
|
nframes_t duration = region->length();
|
||||||
|
|
||||||
|
/* the name doesn't need to be super-precise, but allow for 2 fractional
|
||||||
|
digits just to disambiguate close but not identical stretches.
|
||||||
|
*/
|
||||||
|
|
||||||
|
snprintf (suffix, sizeof (suffix), "@%d", (int) floor (tsr.fraction * 100.0f));
|
||||||
|
|
||||||
|
/* create new sources */
|
||||||
|
|
||||||
|
if (make_new_sources (region, nsrcs, suffix)) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
gain_buffer = new gain_t[bufsize];
|
||||||
|
buffers = new float *[channels];
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < channels; ++i) {
|
||||||
|
buffers[i] = new float[bufsize];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we read from the master (original) sources for the region,
|
||||||
|
not the ones currently in use, in case it's already been
|
||||||
|
subject to timefx. */
|
||||||
|
|
||||||
|
/* study first, process afterwards. */
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
avail = 0;
|
||||||
|
done = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (pos < duration && !tsr.cancel) {
|
||||||
|
|
||||||
|
nframes_t this_read = 0;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < channels; ++i) {
|
||||||
|
|
||||||
|
this_read = 0;
|
||||||
|
nframes_t this_time;
|
||||||
|
|
||||||
|
this_time = min(bufsize, duration - pos);
|
||||||
|
|
||||||
|
this_read = region->master_read_at
|
||||||
|
(buffers[i],
|
||||||
|
buffers[i],
|
||||||
|
gain_buffer,
|
||||||
|
pos + region->position(),
|
||||||
|
this_time,
|
||||||
|
i);
|
||||||
|
|
||||||
|
if (this_read != this_time) {
|
||||||
|
error << string_compose
|
||||||
|
(_("tempoize: error reading data from %1"),
|
||||||
|
nsrcs[i]->name()) << endmsg;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += this_read;
|
||||||
|
done += this_read;
|
||||||
|
|
||||||
|
tsr.progress = ((float) done / duration) * 0.25;
|
||||||
|
|
||||||
|
stretcher.study(buffers, this_read, pos == duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
tsr.done = 0;
|
||||||
|
|
||||||
|
while (pos < duration && !tsr.cancel) {
|
||||||
|
|
||||||
|
nframes_t this_read = 0;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < channels; ++i) {
|
||||||
|
|
||||||
|
this_read = 0;
|
||||||
|
nframes_t this_time;
|
||||||
|
|
||||||
|
this_time = min(bufsize, duration - pos);
|
||||||
|
|
||||||
|
this_read = region->master_read_at
|
||||||
|
(buffers[i],
|
||||||
|
buffers[i],
|
||||||
|
gain_buffer,
|
||||||
|
pos + region->position(),
|
||||||
|
this_time,
|
||||||
|
i);
|
||||||
|
|
||||||
|
if (this_read != this_time) {
|
||||||
|
error << string_compose
|
||||||
|
(_("tempoize: error reading data from %1"),
|
||||||
|
nsrcs[i]->name()) << endmsg;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += this_read;
|
||||||
|
done += this_read;
|
||||||
|
|
||||||
|
tsr.progress = 0.25 + ((float) done / duration) * 0.75;
|
||||||
|
|
||||||
|
stretcher.process(buffers, this_read, pos == duration);
|
||||||
|
|
||||||
|
int avail = 0;
|
||||||
|
|
||||||
|
while ((avail = stretcher.available()) > 0) {
|
||||||
|
|
||||||
|
this_read = min(bufsize, uint32_t(avail));
|
||||||
|
|
||||||
|
stretcher.retrieve(buffers, this_read);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < nsrcs.size(); ++i) {
|
||||||
|
|
||||||
|
if (nsrcs[i]->write(buffers[i], this_read) !=
|
||||||
|
this_read) {
|
||||||
|
error << string_compose (_("error writing tempo-adjusted data to %1"), nsrcs[i]->name()) << endmsg;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((avail = stretcher.available()) >= 0) {
|
||||||
|
|
||||||
|
uint32_t this_read = min(bufsize, uint32_t(avail));
|
||||||
|
|
||||||
|
stretcher.retrieve(buffers, this_read);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < nsrcs.size(); ++i) {
|
||||||
|
|
||||||
|
if (nsrcs[i]->write(buffers[i], this_read) !=
|
||||||
|
this_read) {
|
||||||
|
error << string_compose (_("error writing tempo-adjusted data to %1"), nsrcs[i]->name()) << endmsg;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (runtime_error& err) {
|
||||||
|
error << _("timefx code failure. please notify ardour-developers.") << endmsg;
|
||||||
|
error << err.what() << endmsg;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_name = region->name();
|
||||||
|
at = new_name.find ('@');
|
||||||
|
|
||||||
|
// remove any existing stretch indicator
|
||||||
|
|
||||||
|
if (at != string::npos && at > 2) {
|
||||||
|
new_name = new_name.substr (0, at - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_name += suffix;
|
||||||
|
|
||||||
|
ret = finish (region, nsrcs, new_name);
|
||||||
|
|
||||||
|
/* now reset ancestral data for each new region */
|
||||||
|
|
||||||
|
for (vector<boost::shared_ptr<AudioRegion> >::iterator x = results.begin(); x != results.end(); ++x) {
|
||||||
|
nframes64_t astart = (*x)->ancestral_start();
|
||||||
|
nframes64_t alength = (*x)->ancestral_length();
|
||||||
|
nframes_t start;
|
||||||
|
nframes_t length;
|
||||||
|
|
||||||
|
// note: tsr.fraction is a percentage of original length. 100 = no change,
|
||||||
|
// 50 is half as long, 200 is twice as long, etc.
|
||||||
|
|
||||||
|
float stretch = (*x)->stretch() * (tsr.fraction/100.0);
|
||||||
|
|
||||||
|
start = (nframes_t) floor (astart + ((astart - (*x)->start()) / stretch));
|
||||||
|
length = (nframes_t) floor (alength / stretch);
|
||||||
|
|
||||||
|
(*x)->set_ancestral_data (start, length, stretch);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
|
if (gain_buffer) {
|
||||||
|
delete [] gain_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffers) {
|
||||||
|
for (uint32_t i = 0; i < channels; ++i) {
|
||||||
|
delete buffers[i];
|
||||||
|
}
|
||||||
|
delete [] buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret || tsr.cancel) {
|
||||||
|
for (SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
|
||||||
|
(*si)->mark_for_remove ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tsr.done = true;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
28
libs/rubberband/SConscript
Normal file
28
libs/rubberband/SConscript
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import glob
|
||||||
|
|
||||||
|
rubberband_files = glob.glob ('src/*.cpp')
|
||||||
|
|
||||||
|
Import('env install_prefix libraries')
|
||||||
|
rb = env.Copy()
|
||||||
|
|
||||||
|
rb.Merge ([libraries['fftw3f'],
|
||||||
|
libraries['vamp'],
|
||||||
|
libraries['sndfile-ardour']
|
||||||
|
])
|
||||||
|
|
||||||
|
rb.Append (CPPATH='#libs/rubberband/rubberband', CXXFLAGS="-Ilibs/rubberband/rubberband")
|
||||||
|
|
||||||
|
librb = rb.SharedLibrary('rubberband', rubberband_files)
|
||||||
|
|
||||||
|
Default(librb)
|
||||||
|
|
||||||
|
env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2'), librb))
|
||||||
|
|
||||||
|
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||||
|
[ 'SConscript'] + rubberband_files + glob.glob('src/*.h')))
|
||||||
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue