Major update to TimeScale effect, incorporating libsbsms-2.0.0, fixes to bug 172, changes to ui
This commit is contained in:
parent
9869ea4afd
commit
a17e741abc
|
@ -1,196 +0,0 @@
|
|||
Version 2.0.2 (15 Aug 2005)
|
||||
|
||||
* packaging changes:
|
||||
- require automake (>= 1.5) for 'make -f Makefile.cvs'
|
||||
(mandatory for 'dist-bzip2' automake option)
|
||||
|
||||
* src/gig.cpp, src/gig.h:
|
||||
- support for gig v3 multi-file format (.gig, .gx01, .gx02, ...),
|
||||
the extension files are read automatically when the samples are
|
||||
loaded
|
||||
- fixed the 24 bit decompression, the result should now be exact
|
||||
instead of an approximation
|
||||
- added VCFCutoffControllerInvert parameter and GetVelocityCutoff
|
||||
function to DimensionRegion
|
||||
|
||||
* src/DLS.cpp, src/DLS.h:
|
||||
- the upper bits of the pool table indices are read (used as
|
||||
extension file numbers for gig v3)
|
||||
|
||||
* src/RIFF.cpp, src/RIFF.h:
|
||||
- the file name is remembered in the RIFF::File object
|
||||
|
||||
Version 2.0.1 (12 Jun 2005)
|
||||
|
||||
* packaging changes:
|
||||
- include debian/ directory on 'make dist'
|
||||
- create a bzip2 tarball on 'make dist'
|
||||
|
||||
* src/gigextract.cpp:
|
||||
- show also version of libsndfile or build version of libaudiofile when
|
||||
using the -v switch
|
||||
- fixed mutual link dependency to libsndfile / libaudiofile
|
||||
|
||||
* src/gig.cpp, src/gig.h:
|
||||
- added DimensionRegion::GetVelocityRelease function
|
||||
|
||||
Version 2.0.0 (9 May 2005)
|
||||
|
||||
* packaging changes:
|
||||
- fixed conditional linkage of either libsndfile or libaudiofile
|
||||
(if none of the two exist, configure script will abort)
|
||||
- man pages are now auto generated with the correct libgig version
|
||||
|
||||
* src/gig.cpp, src/gig.h:
|
||||
- experimental support for Gigasampler v3 format;
|
||||
64 bit file offsets are truncated to 32 bit, 24 bit samples are
|
||||
truncated to 16 bit, up to 8 dimensions are read, additional
|
||||
articulation informations are ignored at the moment
|
||||
(patch by Andreas Persson)
|
||||
- added some file format compatibility checks
|
||||
- fixed vcf_type_lowpassturbo value (vcf_type_lowpassturbo was actually
|
||||
never used, because the necessary check was made before
|
||||
initialization)
|
||||
- fixed crossfade points order (structure for big endian and little
|
||||
endian systems was interchanged)
|
||||
- fixed some memory leaks (patch by 'Gene', a.k.a Anders Alm)
|
||||
- fixed crash which occured when patches did not have a sample assigned
|
||||
to their region or dimension region (patch by Andreas Persson)
|
||||
- support for compressed mono samples
|
||||
- experimental support for compressed 24 bit samples
|
||||
- fixed decompression on big-endian CPUs
|
||||
- fixed decompression bug that truncated the last block of samples
|
||||
- external decompression buffers can now be used for streaming samples
|
||||
to avoid race conditions in case of multiple streaming threads
|
||||
- added pre-calculated sample attenuation parameter
|
||||
- added v3 "random" and "round robin" dimensions
|
||||
- implemented progress indicator callback mechanism for loading
|
||||
instruments and samples
|
||||
- added functions libraryName() and libraryVersion()
|
||||
|
||||
* src/DLS.cpp, src/DLS.h:
|
||||
- fixed File constructor which caused variable File::Instruments always
|
||||
to be zero
|
||||
- added functions libraryName() and libraryVersion()
|
||||
|
||||
* src/RIFF.cpp, src/RIFF.h:
|
||||
- fixed method List::LoadSubChunks() which did not restore the original
|
||||
position within the body of the given list chunk
|
||||
- added functions libraryName() and libraryVersion()
|
||||
|
||||
* src/rifftree.cpp:
|
||||
- added command line switch -v to show rifftree's revision and the used
|
||||
libgig version
|
||||
|
||||
* src/dlsdump.cpp:
|
||||
- added command line switch -v to show dlsdump's revision and the used
|
||||
libgig version
|
||||
|
||||
* src/gigdump.cpp:
|
||||
- added output of UnityNote, FineTune, Gain, SampleStartOffset an
|
||||
LoopPlayCount
|
||||
- added command line switch -v to show gigdump's revision and the used
|
||||
libgig version
|
||||
|
||||
* src/gigextract.cpp:
|
||||
- support for compressed mono samples and compressed 24 bit samples
|
||||
- added command line switch -v to show gigextract's revision and the
|
||||
used libgig version
|
||||
|
||||
Version 1.0.0 (26 Nov 2004)
|
||||
|
||||
* packaging changes:
|
||||
- renamed 'libgig.pc.in' -> 'gig.pc.in' and renamed pkg-config lib name
|
||||
'libgig' -> 'gig' as it's common practice to omit the 'lib' prefix
|
||||
- fixed man pages automake install rule (which didn't work on Mandrake,
|
||||
SuSE and Fedora)
|
||||
- fixed generation of Doxygen API documentation (now also included in
|
||||
RPM and Debian packages)
|
||||
|
||||
* src/gig.cpp, src/gig.h:
|
||||
- fixed / improved accuracy of all three velocity to volume
|
||||
transformation functions a.k.a. 'nonlinear','linear','special'
|
||||
(patch by Andreas Persson)
|
||||
- denormals are filtered from the velocity to volume tables
|
||||
- bugfix for dimension region switching (wrong handling of the release
|
||||
trigger dimension, no bit range check for dimensions of split type
|
||||
'split_type_bit')
|
||||
- fixed panorama value in DimensionRegion (invalid conversion from
|
||||
signed 7 bit to signed 8 bit)
|
||||
- added class attribute 'Layers' to class 'gig::Region'
|
||||
- symbol prototyping of gig::Region (fixes build failure with qsampler)
|
||||
|
||||
* src/gigextract.cpp:
|
||||
- added support for libsndfile (if libaudiofile and libsndfile are
|
||||
available then libsndfile is preferred)
|
||||
|
||||
* src/gigdump.cpp:
|
||||
- added printout for dimension informations (amount, type, bits, zones)
|
||||
- added printout for velocity response curve parameters
|
||||
- added printout for crossfade definitions
|
||||
- added printout for panorama value for each DimensionRegion
|
||||
- replaced printout of DLS Region layer by printout of amount of
|
||||
Gigasampler layers
|
||||
|
||||
Version 0.7.1 (2 Jul 2004)
|
||||
|
||||
* packaging changes:
|
||||
- added libgig.spec and libgig.pc package configurations for generating
|
||||
Redhat packages
|
||||
- header files included on installation.
|
||||
- autotools-generated files removed from CVS repository.
|
||||
- added support for generating Debian packages
|
||||
- version of shared library can be set in configure.in
|
||||
|
||||
Version 0.7.0 (3 May 2004)
|
||||
|
||||
* general changes:
|
||||
- various big endian specific corrections
|
||||
(successfully tested now on PPC)
|
||||
- minor adjustments to avoid compile errors on some systems
|
||||
(using now pow() instead of powl() and --pedantic g++ compiler switch)
|
||||
- libtoolized the library
|
||||
- added man pages for the command line tools
|
||||
(gigextract, gigdump, dlsdump, rifftree)
|
||||
|
||||
* src/gig.cpp, src/gig.h:
|
||||
- fixed bug in decompression algorithm which caused it not to detect
|
||||
the end of a stream
|
||||
- added method GetVelocityAttenuation() to class 'DimensionRegion' which
|
||||
takes the MIDI key velocity value as an argument and returns the
|
||||
appropriate volume factor (0.0 ... 1.0) for the sample to be played
|
||||
back, the velocity curve transformation functions used for this are
|
||||
only an approximation so far
|
||||
- fixed class attributes 'Sample::LoopStart', 'Sample::LoopEnd' and
|
||||
'Sample::LoopSize' which reflected wrong values
|
||||
- class attributes 'Sample::LoopStart' and 'Sample::LoopEnd' are now
|
||||
measured in sample points instead of byte offset
|
||||
- renamed misleading attribute name 'Sample::MIDIPitchFraction' to
|
||||
'Sample::FineTune'
|
||||
- added class attribute 'Sample::LoopSize'
|
||||
- added method GetInstrument(uint index) to class 'File'
|
||||
- added ReadAndLoop() method to class 'Sample' which is an extension to
|
||||
the normal Read() method to honor the sample's looping information
|
||||
while streaming from disk
|
||||
- changed interface for 'attenuation_ctrl_t', 'eg1_ctrl_t' and
|
||||
'eg2_ctrl_t': replaced this huge enumeration by a structure which
|
||||
reflects the MIDI controller number in case of an ordinary control
|
||||
change controller (this saves a huge switch-case block in the
|
||||
application of the library user)
|
||||
- renamed following attributes in class 'DimensionRegion':
|
||||
'AttenuationContol' -> 'AttenuationController',
|
||||
'InvertAttenuationControl' -> 'InvertAttenuationController',
|
||||
'AttenuationControlTreshold' -> 'AttenuationControllerThreshold'
|
||||
- minor fix in API documentation for method GetVelocityAttenuation() in
|
||||
class 'DimensionRegion'
|
||||
|
||||
* src/RIFF.cpp, src/RIFF.h:
|
||||
- added additional API documentation
|
||||
- minor fix in Chunk::Read() method (only a minor efficiency issue)
|
||||
|
||||
* src/gigdump.cpp:
|
||||
- added printout of samples' looping informations
|
||||
|
||||
Version 0.6.0 (3 Nov 2003)
|
||||
|
||||
* initial release
|
|
@ -42,6 +42,8 @@ DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
|
|||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \
|
||||
$(top_srcdir)/m4/ac_c99_func_lrintf.m4 \
|
||||
$(top_srcdir)/m4/ax_check_compiler_flags.m4 \
|
||||
$(top_srcdir)/m4/ax_compiler_vendor.m4 \
|
||||
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
|
||||
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
|
||||
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.in
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.61 for sbsms 1.5.0.
|
||||
# Generated by GNU Autoconf 2.61 for sbsms 2.0.0.
|
||||
#
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
@ -721,8 +721,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='sbsms'
|
||||
PACKAGE_TARNAME='sbsms'
|
||||
PACKAGE_VERSION='1.5.0'
|
||||
PACKAGE_STRING='sbsms 1.5.0'
|
||||
PACKAGE_VERSION='2.0.0'
|
||||
PACKAGE_STRING='sbsms 2.0.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
|
||||
ac_unique_file="src/sbsms.cpp"
|
||||
|
@ -1400,7 +1400,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sbsms 1.5.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sbsms 2.0.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1471,7 +1471,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sbsms 1.5.0:";;
|
||||
short | recursive ) echo "Configuration of sbsms 2.0.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1483,9 +1483,11 @@ Optional Features:
|
|||
--enable-fast-install[=PKGS]
|
||||
optimize for fast installation [default=yes]
|
||||
--disable-libtool-lock avoid locking (might break parallel builds)
|
||||
--enable-universal_binary enable universal binary build: (default: disable)
|
||||
--enable-static enable static build: (default: disable)
|
||||
--enable-debug enable debug build: (default: disable)
|
||||
--enable-multithreaded enable multithreaded build: (default: disable)
|
||||
--enable-sse enable SSE optimizations
|
||||
--enable-universal_binary enable universal binary build: (default: disable)
|
||||
--disable-dependency-tracking speeds up one-time build
|
||||
--enable-dependency-tracking do not reject slow dependency extractors
|
||||
--enable-maintainer-mode enable make rules and dependencies not useful
|
||||
|
@ -1574,7 +1576,7 @@ fi
|
|||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sbsms configure 1.5.0
|
||||
sbsms configure 2.0.0
|
||||
generated by GNU Autoconf 2.61
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
|
@ -1588,7 +1590,7 @@ cat >config.log <<_ACEOF
|
|||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sbsms $as_me 1.5.0, which was
|
||||
It was created by sbsms $as_me 2.0.0, which was
|
||||
generated by GNU Autoconf 2.61. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
@ -1947,8 +1949,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
|||
#------------------------------------------------------------------------------------
|
||||
# Library's "official" release version:
|
||||
|
||||
LIBSBSMS_RELEASE_MAJOR=1
|
||||
LIBSBSMS_RELEASE_MINOR=7
|
||||
LIBSBSMS_RELEASE_MAJOR=2
|
||||
LIBSBSMS_RELEASE_MINOR=0
|
||||
LIBSBSMS_RELEASE_BUILD=0
|
||||
|
||||
ac_aux_dir=
|
||||
|
@ -2159,7 +2161,7 @@ fi
|
|||
# 6. If any interfaces have been removed since the last public release, then set age
|
||||
# to 0.
|
||||
|
||||
SHARED_VERSION_INFO="8:0:7"
|
||||
SHARED_VERSION_INFO="10:0:0"
|
||||
|
||||
case `pwd` in
|
||||
*\ * | *\ *)
|
||||
|
@ -3758,13 +3760,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
|
|||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:3761: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3763: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3764: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3766: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3767: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3769: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
|
@ -4986,7 +4988,7 @@ ia64-*-hpux*)
|
|||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 4989 "configure"' > conftest.$ac_ext
|
||||
echo '#line 4991 "configure"' > conftest.$ac_ext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
|
@ -6102,7 +6104,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
|||
else
|
||||
ac_cv_header_stdc=no
|
||||
fi
|
||||
rm -f conftest*
|
||||
rm -f -r conftest*
|
||||
|
||||
fi
|
||||
|
||||
|
@ -6123,7 +6125,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
|||
else
|
||||
ac_cv_header_stdc=no
|
||||
fi
|
||||
rm -f conftest*
|
||||
rm -f -r conftest*
|
||||
|
||||
fi
|
||||
|
||||
|
@ -6807,11 +6809,11 @@ else
|
|||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6810: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6812: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6814: \$? = $ac_status" >&5
|
||||
echo "$as_me:6816: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
|
@ -7146,11 +7148,11 @@ else
|
|||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7149: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7151: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7153: \$? = $ac_status" >&5
|
||||
echo "$as_me:7155: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
|
@ -7251,11 +7253,11 @@ else
|
|||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7254: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7256: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7258: \$? = $ac_status" >&5
|
||||
echo "$as_me:7260: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
|
@ -7306,11 +7308,11 @@ else
|
|||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7309: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7311: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7313: \$? = $ac_status" >&5
|
||||
echo "$as_me:7315: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
|
@ -10075,7 +10077,7 @@ else
|
|||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 10078 "configure"
|
||||
#line 10080 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
|
@ -10171,7 +10173,7 @@ else
|
|||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 10174 "configure"
|
||||
#line 10176 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
|
@ -13176,11 +13178,11 @@ else
|
|||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:13179: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:13181: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:13183: \$? = $ac_status" >&5
|
||||
echo "$as_me:13185: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
|
@ -13275,11 +13277,11 @@ else
|
|||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:13278: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:13280: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:13282: \$? = $ac_status" >&5
|
||||
echo "$as_me:13284: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
|
@ -13327,11 +13329,11 @@ else
|
|||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:13330: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:13332: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:13334: \$? = $ac_status" >&5
|
||||
echo "$as_me:13336: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
|
@ -14527,281 +14529,72 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
|||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for C++ compiler vendor" >&5
|
||||
echo $ECHO_N "checking for C++ compiler vendor... $ECHO_C" >&6; }
|
||||
if test "${ax_cv_cxx_compiler_vendor+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ax_cv_cxx_compiler_vendor=unknown
|
||||
# note: don't check for gcc first since some other compilers define __GNUC__
|
||||
for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale:__PATHCC__,__PATHSCALE__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
|
||||
vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
#if !($vencpp)
|
||||
thisisanerror;
|
||||
#endif
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ax_cv_cxx_compiler_vendor=`echo $ventest | cut -d: -f1`; break
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
done
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ax_cv_cxx_compiler_vendor" >&5
|
||||
echo "${ECHO_T}$ax_cv_cxx_compiler_vendor" >&6; }
|
||||
|
||||
# restore those variables back
|
||||
CFLAGS="$cflags_save"
|
||||
CPPFLAGS="$cppflags_save"
|
||||
CXXFLAGS="$cxxflags_save"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for ac_func in malloc calloc free memcpy memmove
|
||||
do
|
||||
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
|
||||
if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
|
||||
For example, HP-UX 11i <limits.h> declares gettimeofday. */
|
||||
#define $ac_func innocuous_$ac_func
|
||||
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $ac_func (); below.
|
||||
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
|
||||
<limits.h> exists even on freestanding compilers. */
|
||||
|
||||
#ifdef __STDC__
|
||||
# include <limits.h>
|
||||
#else
|
||||
# include <assert.h>
|
||||
#endif
|
||||
|
||||
#undef $ac_func
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char $ac_func ();
|
||||
/* The GNU C library defines this for functions which it implements
|
||||
to always fail with ENOSYS. Some functions are actually named
|
||||
something starting with __ and the normal name is an alias. */
|
||||
#if defined __stub_$ac_func || defined __stub___$ac_func
|
||||
choke me
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return $ac_func ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext &&
|
||||
$as_test_x conftest$ac_exeext; then
|
||||
eval "$as_ac_var=yes"
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
eval "$as_ac_var=no"
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
fi
|
||||
ac_res=`eval echo '${'$as_ac_var'}'`
|
||||
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
||||
echo "${ECHO_T}$ac_res" >&6; }
|
||||
if test `eval echo '${'$as_ac_var'}'` = yes; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for floor in -lm" >&5
|
||||
echo $ECHO_N "checking for floor in -lm... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_lib_m_floor+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lm $LIBS"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char floor ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return floor ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext &&
|
||||
$as_test_x conftest$ac_exeext; then
|
||||
ac_cv_lib_m_floor=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lib_m_floor=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_floor" >&5
|
||||
echo "${ECHO_T}$ac_cv_lib_m_floor" >&6; }
|
||||
if test $ac_cv_lib_m_floor = yes; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBM 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lm $LIBS"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for ac_func in floor sqrt log exp sin cos
|
||||
do
|
||||
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
|
||||
if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
|
||||
For example, HP-UX 11i <limits.h> declares gettimeofday. */
|
||||
#define $ac_func innocuous_$ac_func
|
||||
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $ac_func (); below.
|
||||
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
|
||||
<limits.h> exists even on freestanding compilers. */
|
||||
|
||||
#ifdef __STDC__
|
||||
# include <limits.h>
|
||||
#else
|
||||
# include <assert.h>
|
||||
#endif
|
||||
|
||||
#undef $ac_func
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char $ac_func ();
|
||||
/* The GNU C library defines this for functions which it implements
|
||||
to always fail with ENOSYS. Some functions are actually named
|
||||
something starting with __ and the normal name is an alias. */
|
||||
#if defined __stub_$ac_func || defined __stub___$ac_func
|
||||
choke me
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return $ac_func ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext &&
|
||||
$as_test_x conftest$ac_exeext; then
|
||||
eval "$as_ac_var=yes"
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
eval "$as_ac_var=no"
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
fi
|
||||
ac_res=`eval echo '${'$as_ac_var'}'`
|
||||
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
||||
echo "${ECHO_T}$ac_res" >&6; }
|
||||
if test `eval echo '${'$as_ac_var'}'` = yes; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for lrint" >&5
|
||||
echo $ECHO_N "checking for lrint... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_c99_lrint+set}" = set; then
|
||||
|
@ -14930,14 +14723,6 @@ fi
|
|||
|
||||
|
||||
|
||||
# Check whether --enable-universal_binary was given.
|
||||
if test "${enable_universal_binary+set}" = set; then
|
||||
enableval=$enable_universal_binary; enable_universal_binary=$enableval
|
||||
else
|
||||
enable_universal_binary=no
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-static was given.
|
||||
if test "${enable_static+set}" = set; then
|
||||
enableval=$enable_static; enable_static=$enableval
|
||||
|
@ -14954,7 +14739,31 @@ else
|
|||
fi
|
||||
|
||||
|
||||
SBSMS_CFLAGS="-ffast-math -fstrict-aliasing"
|
||||
# Check whether --enable-multithreaded was given.
|
||||
if test "${enable_multithreaded+set}" = set; then
|
||||
enableval=$enable_multithreaded; enable_multithreaded=$enableval
|
||||
else
|
||||
enable_multithreaded=no
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-sse was given.
|
||||
if test "${enable_sse+set}" = set; then
|
||||
enableval=$enable_sse; enable_sse=$enableval
|
||||
else
|
||||
enable_sse=yes
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-universal_binary was given.
|
||||
if test "${enable_universal_binary+set}" = set; then
|
||||
enableval=$enable_universal_binary; enable_universal_binary=$enableval
|
||||
else
|
||||
enable_universal_binary=no
|
||||
fi
|
||||
|
||||
|
||||
SBSMS_CFLAGS="-ffast-math -funroll-loops"
|
||||
|
||||
if test x$enable_static = xno; then
|
||||
case "$target_os" in
|
||||
|
@ -14966,6 +14775,141 @@ if test x$enable_static = xno; then
|
|||
esac
|
||||
fi
|
||||
|
||||
if test x$enable_debug = xyes; then
|
||||
SBSMS_CFLAGS="$SBSMS_CFLAGS -g -O3"
|
||||
else
|
||||
SBSMS_CFLAGS="$SBSMS_CFLAGS -O3 -fomit-frame-pointer"
|
||||
fi
|
||||
|
||||
if test x$enable_multithreaded = xyes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define MULTITHREADED 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
echo "${ax_cv_cxx_compiler_vendor} XXX"
|
||||
|
||||
if test x$enable_sse = xyes; then
|
||||
|
||||
if test "${ax_cv_cxx_compiler_vendor}" = "gnu"; then
|
||||
{ echo "$as_me:$LINENO: checking whether C++ compiler accepts -msse" >&5
|
||||
echo $ECHO_N "checking whether C++ compiler accepts -msse... $ECHO_C" >&6; }
|
||||
if test "${ax_cv_cxx_flags__msse+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
|
||||
ax_save_FLAGS=$CXXFLAGS
|
||||
CXXFLAGS="-msse"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ax_cv_cxx_flags__msse=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ax_cv_cxx_flags__msse=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
CXXFLAGS=$ax_save_FLAGS
|
||||
fi
|
||||
|
||||
eval ax_check_compiler_flags=$ax_cv_cxx_flags__msse
|
||||
{ echo "$as_me:$LINENO: result: $ax_check_compiler_flags" >&5
|
||||
echo "${ECHO_T}$ax_check_compiler_flags" >&6; }
|
||||
if test "x$ax_check_compiler_flags" = xyes; then
|
||||
SBSMS_CFLAGS="$SBSMS_CFLAGS -msse"
|
||||
else
|
||||
{ { echo "$as_me:$LINENO: error: Need a version of gcc with -msse" >&5
|
||||
echo "$as_me: error: Need a version of gcc with -msse" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <xmmintrin.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
__m128 v,w; float p[8]; v = _mm_loadu_ps(p); _mm_storeu_ps(p,v); w = _mm_loadl_pi(w,(const __m64*)p); w = _mm_loadh_pi(w,(const __m64*)p); _mm_storel_pi((__m64 *)p, w); _mm_storeh_pi((__m64 *)p, w); v = _mm_add_ps(v,w); v = _mm_sub_ps(v,w); v = _mm_mul_ps(v,w); v = _mm_shuffle_ps(v,w,_MM_SHUFFLE(0,1,2,3)); w = _mm_set1_ps(0.0f);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
sse_ok=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
sse_ok=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
if test x$sse_ok = xyes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define ENABLE_SSE 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$enable_universal_binary = xyes; then
|
||||
case "$target_os" in
|
||||
darwin*)
|
||||
|
@ -14976,20 +14920,6 @@ if test x$enable_universal_binary = xyes; then
|
|||
esac
|
||||
fi
|
||||
|
||||
case "$target_os" in
|
||||
darwin*)
|
||||
macosx="yes"
|
||||
;;
|
||||
*)
|
||||
macosx="no"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test x$enable_debug = xyes; then
|
||||
SBSMS_CFLAGS="$SBSMS_CFLAGS -g"
|
||||
else
|
||||
SBSMS_CFLAGS="$SBSMS_CFLAGS -O3"
|
||||
fi
|
||||
|
||||
|
||||
am__api_version='1.10'
|
||||
|
@ -15360,7 +15290,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='sbsms'
|
||||
VERSION='1.5.0'
|
||||
VERSION='2.0.0'
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
@ -16172,7 +16102,7 @@ exec 6>&1
|
|||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sbsms $as_me 1.5.0, which was
|
||||
This file was extended by sbsms $as_me 2.0.0, which was
|
||||
generated by GNU Autoconf 2.61. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -16225,7 +16155,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
|||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
sbsms config.status 1.5.0
|
||||
sbsms config.status 2.0.0
|
||||
configured by $0, generated by GNU Autoconf 2.61,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
AC_INIT([sbsms],[1.5.0])
|
||||
AC_INIT([sbsms],[2.0.0])
|
||||
|
||||
dnl Use the m4/ directory to contain libtool macros that will be needed to
|
||||
dnl go with the ltmain.sh script (both will be created/updated via the command
|
||||
|
@ -8,8 +8,8 @@ AC_CONFIG_MACRO_DIR([m4])
|
|||
#------------------------------------------------------------------------------------
|
||||
# Library's "official" release version:
|
||||
|
||||
LIBSBSMS_RELEASE_MAJOR=1
|
||||
LIBSBSMS_RELEASE_MINOR=7
|
||||
LIBSBSMS_RELEASE_MAJOR=2
|
||||
LIBSBSMS_RELEASE_MINOR=0
|
||||
LIBSBSMS_RELEASE_BUILD=0
|
||||
AC_CONFIG_SRCDIR([src/sbsms.cpp])
|
||||
AC_CANONICAL_TARGET([])
|
||||
|
@ -34,7 +34,7 @@ AC_DISABLE_SHARED dnl allows for optimizations
|
|||
# 6. If any interfaces have been removed since the last public release, then set age
|
||||
# to 0.
|
||||
|
||||
SHARED_VERSION_INFO="8:0:7"
|
||||
SHARED_VERSION_INFO="10:0:0"
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
AM_PROG_LIBTOOL
|
||||
|
@ -47,29 +47,29 @@ cxxflags_save="$CXXFLAGS"
|
|||
AC_LANG([C++])
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CXXCPP
|
||||
AX_COMPILER_VENDOR
|
||||
# restore those variables back
|
||||
CFLAGS="$cflags_save"
|
||||
CPPFLAGS="$cppflags_save"
|
||||
CXXFLAGS="$cxxflags_save"
|
||||
|
||||
AC_CHECK_FUNCS(malloc calloc free memcpy memmove)
|
||||
|
||||
AC_CHECK_LIB([m],floor)
|
||||
AC_CHECK_FUNCS(floor sqrt log exp sin cos)
|
||||
|
||||
AC_C99_FUNC_LRINT()
|
||||
AC_C99_FUNC_LRINTF()
|
||||
|
||||
AC_SUBST(SHLIB_VERSION_ARG)
|
||||
AC_SUBST(SHARED_VERSION_INFO)
|
||||
|
||||
AC_ARG_ENABLE(universal_binary,[ --enable-universal_binary enable universal binary build: (default: disable)],[enable_universal_binary=$enableval],[enable_universal_binary=no])
|
||||
|
||||
AC_ARG_ENABLE(static,[ --enable-static enable static build: (default: disable)],[enable_static=$enableval],[enable_static=no])
|
||||
|
||||
AC_ARG_ENABLE(debug,[ --enable-debug enable debug build: (default: disable)],[enable_debug=$enableval],[enable_debug=no])
|
||||
|
||||
SBSMS_CFLAGS="-ffast-math -fstrict-aliasing"
|
||||
AC_ARG_ENABLE(multithreaded,[ --enable-multithreaded enable multithreaded build: (default: disable)],[enable_multithreaded=$enableval],[enable_multithreaded=no])
|
||||
|
||||
AC_ARG_ENABLE(sse, [AC_HELP_STRING([--enable-sse],[enable SSE optimizations])], enable_sse=$enableval, enable_sse=yes)
|
||||
|
||||
AC_ARG_ENABLE(universal_binary,[ --enable-universal_binary enable universal binary build: (default: disable)],[enable_universal_binary=$enableval],[enable_universal_binary=no])
|
||||
|
||||
SBSMS_CFLAGS="-ffast-math -funroll-loops"
|
||||
|
||||
if test x$enable_static = xno; then
|
||||
case "$target_os" in
|
||||
|
@ -81,6 +81,31 @@ if test x$enable_static = xno; then
|
|||
esac
|
||||
fi
|
||||
|
||||
if test x$enable_debug = xyes; then
|
||||
SBSMS_CFLAGS="$SBSMS_CFLAGS -g -O3"
|
||||
else
|
||||
SBSMS_CFLAGS="$SBSMS_CFLAGS -O3 -fomit-frame-pointer"
|
||||
fi
|
||||
|
||||
if test x$enable_multithreaded = xyes; then
|
||||
AC_DEFINE(MULTITHREADED,1,[Define to compile multithreaded sbsms])
|
||||
fi
|
||||
|
||||
echo "${ax_cv_cxx_compiler_vendor} XXX"
|
||||
|
||||
if test x$enable_sse = xyes; then
|
||||
|
||||
if test "${ax_cv_cxx_compiler_vendor}" = "gnu"; then
|
||||
AX_CHECK_COMPILER_FLAGS(-msse, [SBSMS_CFLAGS="$SBSMS_CFLAGS -msse"],[AC_MSG_ERROR([Need a version of gcc with -msse])])
|
||||
fi
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <xmmintrin.h>]], [[__m128 v,w; float p[8]; v = _mm_loadu_ps(p); _mm_storeu_ps(p,v); w = _mm_loadl_pi(w,(const __m64*)p); w = _mm_loadh_pi(w,(const __m64*)p); _mm_storel_pi((__m64 *)p, w); _mm_storeh_pi((__m64 *)p, w); v = _mm_add_ps(v,w); v = _mm_sub_ps(v,w); v = _mm_mul_ps(v,w); v = _mm_shuffle_ps(v,w,_MM_SHUFFLE(0,1,2,3)); w = _mm_set1_ps(0.0f);]])], [sse_ok=yes], [sse_ok=no])
|
||||
|
||||
if test x$sse_ok = xyes; then
|
||||
AC_DEFINE(ENABLE_SSE,1,[Define to enable sse])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$enable_universal_binary = xyes; then
|
||||
case "$target_os" in
|
||||
darwin*)
|
||||
|
@ -91,20 +116,6 @@ if test x$enable_universal_binary = xyes; then
|
|||
esac
|
||||
fi
|
||||
|
||||
case "$target_os" in
|
||||
darwin*)
|
||||
macosx="yes"
|
||||
;;
|
||||
*)
|
||||
macosx="no"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test x$enable_debug = xyes; then
|
||||
SBSMS_CFLAGS="$SBSMS_CFLAGS -g"
|
||||
else
|
||||
SBSMS_CFLAGS="$SBSMS_CFLAGS -O3"
|
||||
fi
|
||||
AC_SUBST(SBSMS_CFLAGS)
|
||||
|
||||
AM_INIT_AUTOMAKE([])
|
||||
|
|
|
@ -1,172 +1,177 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef SBSMS_INCLUDE
|
||||
#define SBSMS_INCLUDE
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define SBSMS_REAL_FLOAT 1
|
||||
|
||||
namespace _sbsms_ {
|
||||
typedef float real;
|
||||
typedef real interleaved[2];
|
||||
typedef interleaved audio;
|
||||
|
||||
struct sbsms_quality {
|
||||
long inframesize;
|
||||
long maxoutframesize;
|
||||
real minrate;
|
||||
real maxrate;
|
||||
int bands;
|
||||
int M_MAX;
|
||||
int H[5];
|
||||
int N[8];
|
||||
int S[8];
|
||||
int res[8];
|
||||
real pad[8];
|
||||
real P[8];
|
||||
real Q[8];
|
||||
typedef float t_fft[2];
|
||||
typedef t_fft audio;
|
||||
typedef long long int SampleCountType;
|
||||
typedef long long int TimeType;
|
||||
typedef unsigned char TrackIndexType;
|
||||
|
||||
enum {
|
||||
maxBands = 10,
|
||||
numQualityParams = 52
|
||||
};
|
||||
|
||||
extern const sbsms_quality sbsms_quality_standard;
|
||||
extern const sbsms_quality sbsms_quality_fast;
|
||||
struct SBSMSQualityParams {
|
||||
int bands;
|
||||
int H;
|
||||
int N[maxBands];
|
||||
int N0[maxBands];
|
||||
int N1[maxBands];
|
||||
int N2[maxBands];
|
||||
int res[maxBands];
|
||||
};
|
||||
|
||||
struct sbsms_resample_frame {
|
||||
real ratio0;
|
||||
real ratio1;
|
||||
audio *in;
|
||||
class SBSMSQuality {
|
||||
public:
|
||||
SBSMSQuality(const SBSMSQualityParams *params);
|
||||
SBSMSQualityParams params;
|
||||
long getFrameSize();
|
||||
long getMaxPresamples();
|
||||
};
|
||||
|
||||
extern const SBSMSQualityParams SBSMSQualityStandard;
|
||||
|
||||
struct SBSMSFrame {
|
||||
float ratio0;
|
||||
float ratio1;
|
||||
audio *buf;
|
||||
long size;
|
||||
};
|
||||
|
||||
typedef long (*sbsms_cb)(audio *buf, long n, void *data);
|
||||
typedef real (*sbsms_rate_cb)(long nProcessed, void *data);
|
||||
typedef real (*sbsms_pitch_cb)(long nProcessed, void *data);
|
||||
typedef long (*sbsms_resample_cb)(void *cb_data, sbsms_resample_frame *frame);
|
||||
typedef long (*SBSMSResampleCB)(void *cbData, SBSMSFrame *frame);
|
||||
|
||||
class subband;
|
||||
class TrackAllocator;
|
||||
class PeakAllocator;
|
||||
|
||||
struct sbsms {
|
||||
FILE *fp;
|
||||
sbsms_cb getSamplesCB;
|
||||
sbsms_rate_cb getRateCB;
|
||||
sbsms_pitch_cb getPitchCB;
|
||||
subband *top;
|
||||
TrackAllocator *ta;
|
||||
PeakAllocator *pa;
|
||||
long n_prepad, n_postpad, n_prespent, n_processed;
|
||||
bool bWritingComplete;
|
||||
sbsms_quality quality;
|
||||
int channels;
|
||||
audio *ina;
|
||||
void *threadData;
|
||||
};
|
||||
|
||||
class SampleBufBase {
|
||||
class SBSMSInterface {
|
||||
public:
|
||||
SampleBufBase() {};
|
||||
virtual ~SampleBufBase() {};
|
||||
virtual long read(audio *buf, long n)=0;
|
||||
virtual void advance(long n)=0;
|
||||
virtual long n_readable()=0;
|
||||
virtual ~SBSMSInterface() {}
|
||||
virtual long samples(audio *buf, long n) { return 0; }
|
||||
virtual float getStretch(float t)=0;
|
||||
virtual float getPitch(float t)=0;
|
||||
virtual long getPresamples()=0;
|
||||
virtual SampleCountType getSamplesToInput()=0;
|
||||
virtual SampleCountType getSamplesToOutput()=0;
|
||||
};
|
||||
|
||||
class grain;
|
||||
|
||||
class SampleBuf {
|
||||
class SBSMSTrackPoint {
|
||||
public:
|
||||
//SampleBuf() {};
|
||||
SampleBuf(int N);
|
||||
SampleBuf(int N, long delay);
|
||||
void init(int N, long delay);
|
||||
void clear();
|
||||
virtual ~SampleBuf();
|
||||
|
||||
void grow(long pos);
|
||||
long write(audio *buf, long n);
|
||||
long write(grain* g, int h);
|
||||
virtual long read(audio *buf, long n);
|
||||
virtual void advance(long n);
|
||||
virtual long n_readable();
|
||||
audio *getReadBuf();
|
||||
|
||||
long readPos, writePos;
|
||||
long delay;
|
||||
|
||||
int N;
|
||||
long length;
|
||||
audio *buf;
|
||||
virtual ~SBSMSTrackPoint() {}
|
||||
virtual float getF()=0;
|
||||
virtual float getM()=0;
|
||||
virtual float getPhase()=0;
|
||||
};
|
||||
|
||||
class SBSMSTrack {
|
||||
public:
|
||||
virtual ~SBSMSTrack() {}
|
||||
virtual SBSMSTrackPoint *getSBSMSTrackPoint(const TimeType &time)=0;
|
||||
virtual TrackIndexType getIndex()=0;
|
||||
virtual bool isFirst(const TimeType &synthtime)=0;
|
||||
virtual bool isLast(const TimeType &synthtime)=0;
|
||||
};
|
||||
|
||||
class SBSMSRenderer {
|
||||
public:
|
||||
virtual ~SBSMSRenderer() {}
|
||||
virtual void startFrame() {}
|
||||
virtual void startTime(int c, const TimeType &time, int n) {}
|
||||
virtual void render(int c, SBSMSTrack *t) {}
|
||||
virtual void endTime(int c) {}
|
||||
virtual void endFrame() {}
|
||||
virtual void end(const SampleCountType &samples) {}
|
||||
};
|
||||
|
||||
enum SBSMSError {
|
||||
SBSMSErrorNone = 0,
|
||||
SBSMSErrorInvalidRate
|
||||
};
|
||||
|
||||
class SBSMSImp;
|
||||
|
||||
class SBSMS {
|
||||
public:
|
||||
SBSMS(int channels, SBSMSQuality *quality, bool bSynthesize);
|
||||
~SBSMS();
|
||||
|
||||
long read(SBSMSInterface *iface, audio *buf, long n);
|
||||
void addRenderer(SBSMSRenderer *renderer);
|
||||
void removeRenderer(SBSMSRenderer *renderer);
|
||||
long renderFrame(SBSMSInterface *iface);
|
||||
long getInputFrameSize();
|
||||
SBSMSError getError();
|
||||
friend class SBSMSImp;
|
||||
protected:
|
||||
SBSMSImp *imp;
|
||||
};
|
||||
|
||||
enum SlideType {
|
||||
SlideIdentity = 0,
|
||||
SlideConstant,
|
||||
SlideLinearInputRate,
|
||||
SlideLinearOutputRate,
|
||||
SlideLinearInputStretch,
|
||||
SlideLinearOutputStretch,
|
||||
SlideGeometricInput,
|
||||
SlideGeometricOutput
|
||||
};
|
||||
|
||||
class SlideImp;
|
||||
|
||||
class Slide {
|
||||
public:
|
||||
Slide(SlideType slideType, float rate0 = 1.0f, float rate1 = 1.0f, const SampleCountType &n = 0);
|
||||
~Slide();
|
||||
float getTotalStretch();
|
||||
float getStretchedTime(float t);
|
||||
float getRate(float t);
|
||||
float getStretch(float t);
|
||||
float getRate();
|
||||
float getStretch();
|
||||
void step();
|
||||
protected:
|
||||
SlideImp *imp;
|
||||
};
|
||||
|
||||
class SBSMSInterfaceSlidingImp;
|
||||
|
||||
class SBSMSInterfaceSliding : public SBSMSInterface {
|
||||
public:
|
||||
SBSMSInterfaceSliding(Slide *rateSlide,
|
||||
Slide *pitchSlide,
|
||||
bool bPitchReferenceInput,
|
||||
const SampleCountType &samplesToInput,
|
||||
long preSamples,
|
||||
SBSMSQuality *quality);
|
||||
virtual ~SBSMSInterfaceSliding();
|
||||
virtual float getStretch(float t);
|
||||
virtual float getPitch(float t);
|
||||
virtual long getPresamples();
|
||||
virtual SampleCountType getSamplesToInput();
|
||||
virtual SampleCountType getSamplesToOutput();
|
||||
|
||||
friend class SBSMSInterfaceSlidingImp;
|
||||
protected:
|
||||
SBSMSInterfaceSlidingImp *imp;
|
||||
};
|
||||
|
||||
class ResamplerImp;
|
||||
|
||||
class Resampler {
|
||||
public:
|
||||
Resampler(sbsms_resample_cb func, void *data);
|
||||
Resampler(SampleBuf *in, real pitch);
|
||||
Resampler(SBSMSResampleCB func, void *data, SlideType slideType = SlideConstant);
|
||||
~Resampler();
|
||||
long read(audio *audioOut, long frames);
|
||||
void writingComplete();
|
||||
void reset();
|
||||
void init();
|
||||
long samplesInOutput();
|
||||
|
||||
protected:
|
||||
sbsms_resample_frame frame;
|
||||
long startAbs;
|
||||
long midAbs;
|
||||
real midAbsf;
|
||||
long endAbs;
|
||||
long writePosAbs;
|
||||
bool bInput;
|
||||
SampleBuf *out;
|
||||
sbsms_resample_cb cb;
|
||||
void *data;
|
||||
bool bPull;
|
||||
SampleBuf *in;
|
||||
long inOffset;
|
||||
real sincZeros;
|
||||
bool bWritingComplete;
|
||||
ResamplerImp *imp;
|
||||
};
|
||||
|
||||
void sbsms_init(int n);
|
||||
void sbsms_reset(sbsms *sbsmser);
|
||||
void sbsms_seek(sbsms *sbsmser, long framePos, long samplePos);
|
||||
sbsms* sbsms_create(sbsms_cb getSamplesCB, sbsms_rate_cb getRateCB, sbsms_pitch_cb getPitchCB, int channels, sbsms_quality *quality, bool bPreAnalyze, bool bSynthesize);
|
||||
sbsms* sbsms_create(FILE *fp, sbsms_rate_cb getRateCB, sbsms_pitch_cb getPitchCB);
|
||||
void sbsms_destroy(sbsms* sbsmser);
|
||||
long sbsms_read_frame(audio *out, void *data, sbsms *sbsmer, real *pitch0, real *pitch1);
|
||||
long sbsms_write_frame(FILE *fp, void *data, sbsms *sbsmser);
|
||||
long sbsms_samples_processed(sbsms *sbsmser);
|
||||
long sbsms_pre_analyze(sbsms_cb getSamplesCB, void *data, sbsms *sbsmser);
|
||||
void sbsms_pre_analyze_complete(sbsms *sbsmser);
|
||||
|
||||
long sbsms_get_samples_queued(sbsms *sbsmser);
|
||||
long sbsms_get_frames_queued(sbsms *sbsmser);
|
||||
long sbsms_get_last_input_frame_size(sbsms *sbsmser);
|
||||
long sbsms_get_frame_pos(sbsms *sbsmser);
|
||||
|
||||
void sbsms_close_write(FILE *fp, sbsms *sbsmser);
|
||||
FILE *sbsms_open_write(const char *fileName, sbsms *sbsmser, long samples_to_process);
|
||||
void sbsms_close_read(FILE *fp);
|
||||
FILE *sbsms_open_read(const char *fileName);
|
||||
long sbsms_get_samples_to_process(FILE *fp);
|
||||
long sbsms_get_frames_to_process(FILE *fp);
|
||||
long sbsms_get_channels(FILE *fp);
|
||||
void sbsms_get_quality(FILE *fp, sbsms_quality *quality);
|
||||
void sbsms_seek_start_data(FILE *fp);
|
||||
|
||||
struct sbsmsInfo {
|
||||
real rate0, rate1;
|
||||
real pitch0, pitch1;
|
||||
long samplesToProcess;
|
||||
long samplesToGenerate;
|
||||
Resampler *rs;
|
||||
};
|
||||
|
||||
long getLinearOutputSamples(sbsmsInfo *si);
|
||||
real rateCBLinear(long nProcessed, void *userData);
|
||||
real rateCBConstant(long nProcessed, void *userData);
|
||||
real pitchCBLinear(long nProcessed, void *userData);
|
||||
real pitchCBConstant(long nProcessed, void *userData);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
dnl @synopsis AX_CHECK_COMPILER_FLAGS(FLAGS, [ACTION-SUCCESS], [ACTION-FAILURE])
|
||||
dnl @summary check whether FLAGS are accepted by the compiler
|
||||
dnl @category Misc
|
||||
dnl
|
||||
dnl Check whether the given compiler FLAGS work with the current language's
|
||||
dnl compiler, or whether they give an error. (Warnings, however, are
|
||||
dnl ignored.)
|
||||
dnl
|
||||
dnl ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
|
||||
dnl success/failure.
|
||||
dnl
|
||||
dnl @version 2005-05-30
|
||||
dnl @license GPLWithACException
|
||||
dnl @author Steven G. Johnson <stevenj@alum.mit.edu> and Matteo Frigo.
|
||||
AC_DEFUN([AX_CHECK_COMPILER_FLAGS],
|
||||
[AC_PREREQ(2.59) dnl for _AC_LANG_PREFIX
|
||||
AC_MSG_CHECKING([whether _AC_LANG compiler accepts $1])
|
||||
dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname:
|
||||
AS_LITERAL_IF([$1],
|
||||
[AC_CACHE_VAL(AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1), [
|
||||
ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
|
||||
_AC_LANG_PREFIX[]FLAGS="$1"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
|
||||
AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=yes,
|
||||
AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=no)
|
||||
_AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])],
|
||||
[ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
|
||||
_AC_LANG_PREFIX[]FLAGS="$1"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
|
||||
eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=yes,
|
||||
eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=no)
|
||||
_AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])
|
||||
eval ax_check_compiler_flags=$AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)
|
||||
AC_MSG_RESULT($ax_check_compiler_flags)
|
||||
if test "x$ax_check_compiler_flags" = xyes; then
|
||||
m4_default([$2], :)
|
||||
else
|
||||
m4_default([$3], :)
|
||||
fi
|
||||
])dnl AX_CHECK_COMPILER_FLAGS
|
|
@ -0,0 +1,30 @@
|
|||
dnl @synopsis AX_COMPILER_VENDOR
|
||||
dnl @summary find the vendor (gnu, intel, etc.) of the C/C++ compiler
|
||||
dnl @category C
|
||||
dnl @category C++
|
||||
dnl
|
||||
dnl Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm,
|
||||
dnl sun, hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi,
|
||||
dnl microsoft, watcom, etc. The vendor is returned in the cache variable
|
||||
dnl $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++.
|
||||
dnl
|
||||
dnl @version 2007-08-01
|
||||
dnl @license GPLWithACException
|
||||
dnl @author Steven G. Johnson <stevenj@alum.mit.edu> with Matteo Frigo
|
||||
|
||||
AC_DEFUN([AX_COMPILER_VENDOR],
|
||||
[
|
||||
AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
|
||||
[ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown
|
||||
# note: don't check for gcc first since some other compilers define __GNUC__
|
||||
for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale:__PATHCC__,__PATHSCALE__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
|
||||
vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
|
||||
#if !($vencpp)
|
||||
thisisanerror;
|
||||
#endif
|
||||
])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break])
|
||||
done
|
||||
])
|
||||
])
|
||||
|
|
@ -40,6 +40,8 @@ DIST_COMMON = $(libsbsmsinclude_HEADERS) $(srcdir)/Makefile.am \
|
|||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \
|
||||
$(top_srcdir)/m4/ac_c99_func_lrintf.m4 \
|
||||
$(top_srcdir)/m4/ax_check_compiler_flags.m4 \
|
||||
$(top_srcdir)/m4/ax_compiler_vendor.m4 \
|
||||
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
|
||||
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
|
||||
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.in
|
||||
|
@ -59,9 +61,9 @@ am__installdirs = "$(DESTDIR)$(libdir)" \
|
|||
libLTLIBRARIES_INSTALL = $(INSTALL)
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
libsbsms_la_LIBADD =
|
||||
am_libsbsms_la_OBJECTS = peak.lo sms.lo track.lo trackpoint.lo \
|
||||
utils.lo audio.lo resample.lo sbsms.lo fft.lo grain.lo \
|
||||
buffer.lo subband.lo
|
||||
am_libsbsms_la_OBJECTS = sms.lo track.lo trackpoint.lo resample.lo \
|
||||
sbsms.lo fft.lo grain.lo buffer.lo subband.lo dBTable.lo \
|
||||
slide.lo
|
||||
libsbsms_la_OBJECTS = $(am_libsbsms_la_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
|
@ -213,11 +215,11 @@ target_os = @target_os@
|
|||
target_vendor = @target_vendor@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AM_CXXFLAGS = -I../include @SBSMS_CFLAGS@
|
||||
AM_CXXFLAGS = @SBSMS_CFLAGS@ -I../include
|
||||
libsbsmsincludedir = $(includedir)
|
||||
libsbsmsinclude_HEADERS = ../include/sbsms.h
|
||||
lib_LTLIBRARIES = libsbsms.la
|
||||
libsbsms_la_SOURCES = peak.cpp sms.cpp track.cpp trackpoint.cpp utils.cpp audio.cpp resample.cpp sbsms.cpp fft.cpp grain.cpp buffer.cpp subband.cpp audio.h buffer.h fft.h utils.h peak.h trackpoint.h grain.h real.h resample.h ../include/sbsms.h sms.h subband.h track.h
|
||||
libsbsms_la_SOURCES = sms.cpp track.cpp trackpoint.cpp resample.cpp sbsms.cpp fft.cpp grain.cpp buffer.cpp subband.cpp dBTable.cpp buffer.h fft.h sse.h utils.h trackpoint.h grain.h real.h synthTable.h dBTable.h sincCoeffs.h ../include/sbsms.h sms.h subband.h track.h slide.cpp
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-am
|
||||
|
||||
|
@ -305,18 +307,17 @@ mostlyclean-compile:
|
|||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audio.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dBTable.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fft.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grain.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peak.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resample.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sbsms.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slide.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sms.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subband.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/track.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trackpoint.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@
|
||||
|
||||
.cpp.o:
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "audio.h"
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
audio *make_audio_buf(long n) {
|
||||
return (audio*)calloc(n,sizeof(audio));
|
||||
}
|
||||
|
||||
void free_audio_buf(audio *buf) {
|
||||
free(buf);
|
||||
}
|
||||
|
||||
long copy_audio_buf(audio *to, long off1, audio *from, long off2, long n)
|
||||
{
|
||||
memcpy(to+off1,from+off2,n*sizeof(audio));
|
||||
return n;
|
||||
}
|
||||
|
||||
long audio_convert_from(float *to, long off1, audio *from, long off2, long n)
|
||||
{
|
||||
for(int k=0;k<n;k++) {
|
||||
int k2 = (k+off1)<<1;
|
||||
to[k2] = (float)from[k+off2][0];
|
||||
to[k2+1] = (float)from[k+off2][1];
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
long audio_convert_to(audio *to, long off1, float *from, long off2, long n)
|
||||
{
|
||||
for(int k=0;k<n;k++) {
|
||||
int k2 = (k+off2)<<1;
|
||||
to[k+off1][0] = (real)from[k2];
|
||||
to[k+off1][1] = (real)from[k2+1];
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef SBSMS_AUDIO_H
|
||||
#define SBSMS_AUDIO_H
|
||||
|
||||
#include "sbsms.h"
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
audio *make_audio_buf(long);
|
||||
void free_audio_buf(audio *);
|
||||
long copy_audio_buf(audio *, long off1, audio *, long off2, long n);
|
||||
long audio_convert_from(float *to, long off1, audio *from, long off2, long n);
|
||||
long audio_convert_to(audio *to, long off1, float *from, long off2, long n);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -9,162 +9,49 @@ using namespace std;
|
|||
|
||||
namespace _sbsms_ {
|
||||
|
||||
#define INIT_SAMPLEBUF_LENGTH 8192
|
||||
#define INIT_GRAINBUF_LENGTH 128
|
||||
#define INIT_TPLBUF_LENGTH 128
|
||||
|
||||
/****************
|
||||
|
||||
SampleBuf
|
||||
|
||||
****************/
|
||||
|
||||
SampleBuf :: SampleBuf(int N)
|
||||
template<>
|
||||
void SampleBuf :: write(grain *g, int h)
|
||||
{
|
||||
init(N,0);
|
||||
}
|
||||
|
||||
SampleBuf :: SampleBuf(int N, long delay)
|
||||
{
|
||||
init(N,delay);
|
||||
}
|
||||
|
||||
void SampleBuf :: init(int N, long delay)
|
||||
{
|
||||
this->delay = delay;
|
||||
this->N = N;
|
||||
this->length = INIT_SAMPLEBUF_LENGTH;
|
||||
this->buf = make_audio_buf(2*length);
|
||||
this->readPos = 0;
|
||||
this->writePos = 0;
|
||||
}
|
||||
|
||||
SampleBuf :: ~SampleBuf()
|
||||
{
|
||||
free_audio_buf(buf);
|
||||
}
|
||||
|
||||
long SampleBuf :: write(audio *in, long n)
|
||||
{
|
||||
if(n==0) {
|
||||
return 0;
|
||||
}
|
||||
grow(n);
|
||||
memcpy(buf+writePos,in,n*sizeof(audio));
|
||||
writePos += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
void SampleBuf :: grow(long n)
|
||||
{
|
||||
long pos = writePos+n;
|
||||
while(pos >= 2*length) {
|
||||
length *= 2;
|
||||
audio *newBuf = make_audio_buf(2*length);
|
||||
memcpy(newBuf,buf+readPos,(length-readPos)*sizeof(audio));
|
||||
free_audio_buf(buf);
|
||||
buf = newBuf;
|
||||
writePos -= readPos;
|
||||
pos -= readPos;
|
||||
readPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
long SampleBuf :: write(grain *g, int h)
|
||||
{
|
||||
grow(g->N);
|
||||
grow(N);
|
||||
g->synthesize();
|
||||
real f = 2.6666666666666666666666666f/(real)(N/h);
|
||||
|
||||
float f = 2.6666666666666666666666666f/(float)(N/h);
|
||||
for(int c=0;c<2;c++) {
|
||||
int j = 0;
|
||||
for(int k=writePos; k<writePos+g->N; k++) {
|
||||
int kend = writePos + N;
|
||||
for(int k=writePos; k<kend; k++) {
|
||||
buf[k][c] += g->x[j++][c] * f;
|
||||
}
|
||||
}
|
||||
writePos += h;
|
||||
return h;
|
||||
}
|
||||
|
||||
long SampleBuf :: read(audio *outBuf, long n)
|
||||
GrainBuf :: GrainBuf(int N, int h, int N2, int type) :
|
||||
grainAllocator(N,N2,type)
|
||||
{
|
||||
if(n==0)
|
||||
return 0;
|
||||
assert(writePos < 2*length);
|
||||
n = min(n,n_readable());
|
||||
n = max(n,(long)0);
|
||||
memcpy(outBuf,buf+readPos,n*sizeof(audio));
|
||||
return n;
|
||||
}
|
||||
|
||||
long SampleBuf :: n_readable()
|
||||
{
|
||||
return max(writePos-delay - readPos,(long)0);
|
||||
}
|
||||
|
||||
void SampleBuf :: advance(long n) {
|
||||
assert(readPos+n <= writePos);
|
||||
memset(buf+readPos,0,n*sizeof(audio));
|
||||
readPos += n;
|
||||
if(readPos >= length) {
|
||||
long endPos;
|
||||
if(N==0)
|
||||
endPos = 2*length;
|
||||
else
|
||||
endPos = min(2*length,writePos+N);
|
||||
memcpy(buf,buf+readPos,(endPos-readPos)*sizeof(audio));
|
||||
memset(buf+readPos,0,(endPos-readPos)*sizeof(audio));
|
||||
writePos -= readPos;
|
||||
readPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
audio *SampleBuf :: getReadBuf()
|
||||
{
|
||||
return (buf+readPos);
|
||||
}
|
||||
|
||||
void SampleBuf :: clear()
|
||||
{
|
||||
advance(writePos-readPos);
|
||||
}
|
||||
|
||||
/****************
|
||||
|
||||
GrainBuf
|
||||
|
||||
****************/
|
||||
|
||||
GrainBuf :: GrainBuf(int N, int h)
|
||||
{
|
||||
init(N,h,1);
|
||||
}
|
||||
|
||||
GrainBuf :: GrainBuf(int N, int h, real pad)
|
||||
{
|
||||
init(N,h,pad);
|
||||
}
|
||||
|
||||
void GrainBuf :: init(int N, int h, real pad)
|
||||
{
|
||||
this->length = INIT_GRAINBUF_LENGTH;
|
||||
this->length = initGrainBufLength;
|
||||
this->buf = (grain**) calloc(2*length,sizeof(grain*));
|
||||
this->iBuf = (audio*) calloc(N,sizeof(audio));
|
||||
|
||||
this->pad = pad;
|
||||
this->N = N;
|
||||
this->iBuf = (audio*) calloc(N2,sizeof(audio));
|
||||
this->N2 = N2;
|
||||
this->h = h;
|
||||
this->overlap = N2 - h;
|
||||
this->xOffset = (N-N2)>>1;
|
||||
this->iBufWritePos = 0;
|
||||
this->readPos = 0;
|
||||
this->writePos = 0;
|
||||
|
||||
}
|
||||
|
||||
GrainBuf :: ~GrainBuf()
|
||||
{
|
||||
clear();
|
||||
for(int k=readPos;k<writePos;k++) {
|
||||
grainAllocator.forget(buf[k]);
|
||||
}
|
||||
free(buf);
|
||||
free_audio_buf(iBuf);
|
||||
free(iBuf);
|
||||
}
|
||||
|
||||
audio *GrainBuf :: getWindowFFT()
|
||||
{
|
||||
return grainAllocator.W;
|
||||
}
|
||||
|
||||
long GrainBuf :: write(audio *buf2, long n)
|
||||
|
@ -173,48 +60,43 @@ long GrainBuf :: write(audio *buf2, long n)
|
|||
return 0;
|
||||
}
|
||||
long ng = 0;
|
||||
int overlap = N - h;
|
||||
long bufReadPos = 0;
|
||||
|
||||
long nToCopy;
|
||||
while(bufReadPos<n) {
|
||||
long nToCopy = min((n-bufReadPos),N-iBufWritePos);
|
||||
memcpy(iBuf+iBufWritePos, buf2+bufReadPos, nToCopy*sizeof(audio));
|
||||
|
||||
if(nToCopy+iBufWritePos == N) {
|
||||
convert(iBuf);
|
||||
nToCopy = min((n-bufReadPos),N2-iBufWritePos);
|
||||
if(nToCopy+iBufWritePos == N2) {
|
||||
if(buf2) {
|
||||
memcpy(iBuf+iBufWritePos, buf2+bufReadPos, nToCopy*sizeof(audio));
|
||||
} else {
|
||||
memset(iBuf+iBufWritePos, 0, nToCopy*sizeof(audio));
|
||||
}
|
||||
grain *g = grainAllocator.create();
|
||||
memcpy(g->x+xOffset,iBuf,N2*sizeof(audio));
|
||||
write(g);
|
||||
ng++;
|
||||
memcpy(iBuf,iBuf+h,overlap*sizeof(audio));
|
||||
iBufWritePos = overlap;
|
||||
bufReadPos += nToCopy;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// copy the remainder to the iBuf
|
||||
long nToCopy = min((n-bufReadPos),N-iBufWritePos);
|
||||
memcpy(iBuf+iBufWritePos, buf2+bufReadPos, nToCopy*sizeof(audio));
|
||||
nToCopy = min((n-bufReadPos),N2-iBufWritePos);
|
||||
if(buf2) {
|
||||
memcpy(iBuf+iBufWritePos, buf2+bufReadPos, nToCopy*sizeof(audio));
|
||||
} else {
|
||||
memset(iBuf+iBufWritePos, 0, nToCopy*sizeof(audio));
|
||||
}
|
||||
iBufWritePos += nToCopy;
|
||||
|
||||
return ng;
|
||||
}
|
||||
|
||||
void GrainBuf :: convert(audio *timebuf)
|
||||
{
|
||||
grain *g = grain::create(N,pad);
|
||||
memcpy(g->x,timebuf,N*sizeof(audio));
|
||||
g->analyze();
|
||||
g->h = h;
|
||||
write(g);
|
||||
}
|
||||
|
||||
void GrainBuf :: advance(long n)
|
||||
{
|
||||
assert(readPos+n <= writePos);
|
||||
for(int k=readPos;k<readPos+n;k++) {
|
||||
grain :: forget(buf[k]);
|
||||
grainAllocator.forget(buf[k]);
|
||||
}
|
||||
readPos += n;
|
||||
|
||||
//grain::count-=n;
|
||||
if(readPos >= length) {
|
||||
memcpy(buf,buf+readPos,(writePos-readPos)*sizeof(grain*));
|
||||
writePos = writePos - readPos;
|
||||
|
@ -227,35 +109,43 @@ grain* GrainBuf :: read(long k)
|
|||
return buf[k];
|
||||
}
|
||||
|
||||
long GrainBuf :: nReadable()
|
||||
{
|
||||
return writePos - readPos;
|
||||
}
|
||||
|
||||
void GrainBuf :: write(grain *g)
|
||||
{
|
||||
if(writePos >= 2*length) {
|
||||
length *= 2;
|
||||
grain **newBuf = (grain**)calloc(2*length,sizeof(grain*));
|
||||
if(writePos >= length<<1) {
|
||||
length <<= 1;
|
||||
grain **newBuf = (grain**)calloc((length<<1),sizeof(grain*));
|
||||
memcpy(newBuf,buf+readPos,(writePos-readPos)*sizeof(grain*));
|
||||
free(buf);
|
||||
buf = newBuf;
|
||||
writePos -= readPos;
|
||||
readPos = 0;
|
||||
}
|
||||
|
||||
grain :: referenced(g);
|
||||
grainAllocator.reference(g);
|
||||
buf[writePos++] = g;
|
||||
}
|
||||
|
||||
void GrainBuf :: reference(grain *g)
|
||||
{
|
||||
grainAllocator.reference(g);
|
||||
}
|
||||
|
||||
void GrainBuf :: forget(grain *g)
|
||||
{
|
||||
grainAllocator.forget(g);
|
||||
}
|
||||
|
||||
void GrainBuf :: clear()
|
||||
{
|
||||
memset(iBuf,0,N*sizeof(audio));
|
||||
memset(iBuf,0,N2*sizeof(audio));
|
||||
iBufWritePos = 0;
|
||||
advance(n_readable());
|
||||
advance(writePos-readPos);
|
||||
}
|
||||
|
||||
/****************
|
||||
|
||||
Mixer
|
||||
|
||||
****************/
|
||||
|
||||
Mixer :: Mixer(SampleBufBase *b1, SampleBuf *b2)
|
||||
{
|
||||
this->b1 = b1;
|
||||
|
@ -264,86 +154,16 @@ Mixer :: Mixer(SampleBufBase *b1, SampleBuf *b2)
|
|||
|
||||
long Mixer :: read(audio *outBuf, long n)
|
||||
{
|
||||
if(n==0)
|
||||
return 0;
|
||||
n = min(n,n_readable());
|
||||
|
||||
b1->read(outBuf,n);
|
||||
if(n==0) return 0;
|
||||
n = min(n,b2->nReadable());
|
||||
n = b1->read(outBuf,n);
|
||||
audio *buf2 = b2->getReadBuf();
|
||||
|
||||
for(int k=0;k<n;k++) {
|
||||
for(int c=0;c<2;c++)
|
||||
outBuf[k][c] += buf2[k][c];
|
||||
}
|
||||
b2->advance(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
void Mixer::advance(long n)
|
||||
{
|
||||
b1->advance(n);
|
||||
b2->advance(n);
|
||||
}
|
||||
|
||||
long Mixer::n_readable()
|
||||
{
|
||||
return min(b1->n_readable(), b2->n_readable());
|
||||
}
|
||||
|
||||
/********************
|
||||
TrackPointListBuffer
|
||||
********************/
|
||||
|
||||
TrackPointListBuffer :: TrackPointListBuffer() {
|
||||
length = INIT_TPLBUF_LENGTH;
|
||||
buf = (tplist**) calloc(2*length,sizeof(tplist*));
|
||||
readPos = 0;
|
||||
writePos = 0;
|
||||
}
|
||||
|
||||
TrackPointListBuffer :: ~TrackPointListBuffer() {
|
||||
for(int k=readPos;k<writePos;k++)
|
||||
delete buf[k];
|
||||
free(buf);
|
||||
}
|
||||
|
||||
long TrackPointListBuffer :: write(tplist *tpl)
|
||||
{
|
||||
if(writePos >= 2*length) {
|
||||
length *= 2;
|
||||
tplist **newBuf = (tplist**) calloc(2*length,sizeof(tplist*));
|
||||
memcpy(newBuf,buf+readPos,(writePos-readPos)*sizeof(tplist*));
|
||||
free(buf);
|
||||
buf = newBuf;
|
||||
writePos -= readPos;
|
||||
readPos = 0;
|
||||
}
|
||||
|
||||
buf[writePos++] = tpl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
long TrackPointListBuffer :: n_readable()
|
||||
{
|
||||
return writePos-readPos;
|
||||
}
|
||||
|
||||
tplist *TrackPointListBuffer :: read(long k)
|
||||
{
|
||||
return buf[k];
|
||||
}
|
||||
|
||||
void TrackPointListBuffer :: advance(long n)
|
||||
{
|
||||
assert(readPos+n <= writePos);
|
||||
for(int k=readPos;k<readPos+n;k++) {
|
||||
delete buf[k];
|
||||
}
|
||||
readPos += n;
|
||||
if(readPos >= length) {
|
||||
memcpy(buf,buf+readPos,(writePos-readPos)*sizeof(tplist*));
|
||||
writePos = writePos - readPos;
|
||||
readPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef BUFFER_H
|
||||
#define BUFFER_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include "sbsms.h"
|
||||
#include "grain.h"
|
||||
#include "trackpoint.h"
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
typedef list<trackpoint*> tplist;
|
||||
enum {
|
||||
initSampleBufLength = 8192,
|
||||
initGrainBufLength = 256,
|
||||
initRingBufferLength = 64
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class RingBuffer {
|
||||
public:
|
||||
RingBuffer();
|
||||
~RingBuffer();
|
||||
|
||||
long write(T a);
|
||||
T read(long k);
|
||||
long n_readable();
|
||||
T read();
|
||||
long nReadable();
|
||||
void advance(long n);
|
||||
void clear();
|
||||
|
||||
long readPos;
|
||||
long writePos;
|
||||
protected:
|
||||
|
@ -33,8 +33,6 @@ class RingBuffer {
|
|||
long length;
|
||||
};
|
||||
|
||||
#define INIT_RINGBUF_LENGTH 128
|
||||
|
||||
/********************
|
||||
RingBuffer
|
||||
********************/
|
||||
|
@ -42,7 +40,7 @@ class RingBuffer {
|
|||
template <class T>
|
||||
RingBuffer<T> :: RingBuffer()
|
||||
{
|
||||
length = INIT_RINGBUF_LENGTH;
|
||||
length = initRingBufferLength;
|
||||
buf = (T*) calloc(2*length,sizeof(T));
|
||||
readPos = 0;
|
||||
writePos = 0;
|
||||
|
@ -77,7 +75,13 @@ T RingBuffer<T> :: read(long k)
|
|||
}
|
||||
|
||||
template <class T>
|
||||
long RingBuffer<T> :: n_readable()
|
||||
T RingBuffer<T> :: read()
|
||||
{
|
||||
return buf[readPos];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
long RingBuffer<T> :: nReadable()
|
||||
{
|
||||
return writePos-readPos;
|
||||
}
|
||||
|
@ -85,7 +89,6 @@ long RingBuffer<T> :: n_readable()
|
|||
template <class T>
|
||||
void RingBuffer<T> :: advance(long n)
|
||||
{
|
||||
assert(readPos+n <= writePos);
|
||||
readPos += n;
|
||||
if(readPos >= length) {
|
||||
memcpy(buf,buf+readPos,(writePos-readPos)*sizeof(T));
|
||||
|
@ -101,64 +104,159 @@ void RingBuffer<T> :: clear()
|
|||
writePos = 0;
|
||||
}
|
||||
|
||||
class TrackPointListBuffer {
|
||||
class SampleBufBase {
|
||||
public:
|
||||
TrackPointListBuffer();
|
||||
~TrackPointListBuffer();
|
||||
|
||||
long write(tplist *tpl);
|
||||
tplist *read(long k);
|
||||
long n_readable();
|
||||
void advance(long n);
|
||||
|
||||
long readPos;
|
||||
long writePos;
|
||||
|
||||
protected:
|
||||
tplist **buf;
|
||||
long length;
|
||||
SampleBufBase() {};
|
||||
virtual ~SampleBufBase() {};
|
||||
virtual long read(audio *buf, long n)=0;
|
||||
};
|
||||
|
||||
/****************
|
||||
|
||||
SampleBuf
|
||||
|
||||
****************/
|
||||
|
||||
class grain;
|
||||
|
||||
template<class T>
|
||||
class ArrayRingBuffer
|
||||
{
|
||||
public:
|
||||
ArrayRingBuffer(int N);
|
||||
virtual ~ArrayRingBuffer();
|
||||
void clear();
|
||||
void grow(long pos);
|
||||
void write(T *buf, long n);
|
||||
void write(grain *g, int h);
|
||||
void read(T *buf, long n);
|
||||
void advance(long n);
|
||||
long nReadable();
|
||||
T *getReadBuf();
|
||||
long readPos, writePos;
|
||||
int N;
|
||||
long length;
|
||||
T *buf;
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
ArrayRingBuffer<T> :: ArrayRingBuffer(int N)
|
||||
{
|
||||
this->N = N;
|
||||
this->length = initSampleBufLength;
|
||||
this->buf = (T*)calloc(2*length,sizeof(T));
|
||||
this->readPos = 0;
|
||||
this->writePos = 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
ArrayRingBuffer<T> :: ~ArrayRingBuffer()
|
||||
{
|
||||
free(buf);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayRingBuffer<T> :: write(T *in, long n)
|
||||
{
|
||||
grow(n);
|
||||
if(in) memcpy(buf+writePos,in,n*sizeof(T));
|
||||
writePos += n;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayRingBuffer<T> :: grow(long n)
|
||||
{
|
||||
long pos = writePos+n;
|
||||
while(pos >= 2*length) {
|
||||
length *= 2;
|
||||
T *newBuf = (T*)calloc(2*length,sizeof(T));
|
||||
memcpy(newBuf,buf+readPos,(length-readPos)*sizeof(T));
|
||||
free(buf);
|
||||
buf = newBuf;
|
||||
writePos -= readPos;
|
||||
pos -= readPos;
|
||||
readPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayRingBuffer<T> :: read(T *outBuf, long n)
|
||||
{
|
||||
n = max(0L,min(n,nReadable()));
|
||||
memcpy(outBuf,buf+readPos,n*sizeof(T));
|
||||
advance(n);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
long ArrayRingBuffer<T> :: nReadable()
|
||||
{
|
||||
return max(0L,writePos-readPos);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayRingBuffer<T> :: advance(long n) {
|
||||
memset(buf+readPos,0,n*sizeof(T));
|
||||
readPos += n;
|
||||
if(readPos >= length) {
|
||||
long endPos;
|
||||
endPos = writePos+N;
|
||||
memcpy(buf,buf+readPos,(endPos-readPos)*sizeof(T));
|
||||
memset(buf+readPos,0,((length<<1)-readPos)*sizeof(T));
|
||||
writePos -= readPos;
|
||||
readPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T *ArrayRingBuffer<T> :: getReadBuf()
|
||||
{
|
||||
return (buf+readPos);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayRingBuffer<T> :: clear()
|
||||
{
|
||||
advance(writePos-readPos);
|
||||
}
|
||||
|
||||
typedef ArrayRingBuffer<audio> SampleBuf;
|
||||
|
||||
class GrainBuf {
|
||||
public:
|
||||
GrainBuf(int N, int h);
|
||||
GrainBuf(int N, int h, real pad);
|
||||
GrainBuf(int N, int h, int N2, int type);
|
||||
~GrainBuf();
|
||||
|
||||
void init(int N, int h, real pad);
|
||||
long write(audio *buf, long n);
|
||||
void write(grain *g);
|
||||
void advance(long n);
|
||||
long n_readable() { return writePos - readPos; }
|
||||
long nReadable();
|
||||
void clear();
|
||||
grain* read(long k);
|
||||
|
||||
long length;
|
||||
long readPos, writePos;
|
||||
int N,h;
|
||||
real pad;
|
||||
|
||||
void reference(grain *g);
|
||||
void forget(grain *g);
|
||||
audio *getWindowFFT();
|
||||
long readPos;
|
||||
long writePos;
|
||||
protected:
|
||||
void convert(audio *buf);
|
||||
audio *iBuf;
|
||||
long iBufWritePos;
|
||||
grain **buf;
|
||||
|
||||
long length;
|
||||
long N2;
|
||||
long h;
|
||||
long overlap;
|
||||
long xOffset;
|
||||
long iBufWritePos;
|
||||
GrainAllocator grainAllocator;
|
||||
};
|
||||
|
||||
class Mixer : public SampleBufBase {
|
||||
public:
|
||||
Mixer(SampleBufBase *, SampleBuf *);
|
||||
long read(audio *buf, long n);
|
||||
void advance(long n);
|
||||
long n_readable();
|
||||
~Mixer() {}
|
||||
|
||||
virtual long read(audio *buf, long n);
|
||||
protected:
|
||||
SampleBuf *buf;
|
||||
SampleBufBase *b1;
|
||||
SampleBuf *b2;
|
||||
|
||||
SampleBuf *b2;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/* src/config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define to enable sse */
|
||||
#undef ENABLE_SSE
|
||||
|
||||
/* Define to 1 if you have the `calloc' function. */
|
||||
#undef HAVE_CALLOC
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the `floor' function. */
|
||||
#undef HAVE_FLOOR
|
||||
|
||||
/* Define to 1 if you have the `free' function. */
|
||||
#undef HAVE_FREE
|
||||
|
||||
|
@ -18,18 +18,12 @@
|
|||
/* Define to 1 if you have the `m' library (-lm). */
|
||||
#undef HAVE_LIBM
|
||||
|
||||
/* Define to 1 if you have the `log' function. */
|
||||
#undef HAVE_LOG
|
||||
|
||||
/* Define if you have C99's lrint function. */
|
||||
#undef HAVE_LRINT
|
||||
|
||||
/* Define if you have C99's lrintf function. */
|
||||
#undef HAVE_LRINTF
|
||||
|
||||
/* Define to use libmad */
|
||||
#undef HAVE_MAD
|
||||
|
||||
/* Define to 1 if you have the `malloc' function. */
|
||||
#undef HAVE_MALLOC
|
||||
|
||||
|
@ -39,14 +33,8 @@
|
|||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to use libportaudio */
|
||||
#undef HAVE_PORTAUDIO
|
||||
|
||||
/* Define to use libsndfile */
|
||||
#undef HAVE_SNDFILE
|
||||
|
||||
/* Define to 1 if you have the `sqrt' function. */
|
||||
#undef HAVE_SQRT
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#undef HAVE_MEMSET
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,26 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef DBTABLE_H
|
||||
#define DBTABLE_H
|
||||
|
||||
#include "real.h"
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
enum { dBTableSize = 4096, dBTableScale = dBTableSize - 1 };
|
||||
|
||||
extern float dBTable[dBTableSize];
|
||||
|
||||
inline float dBApprox(float x, float y)
|
||||
{
|
||||
if(x < y) {
|
||||
return dBTable[lrintf(x/y*dBTableScale)];
|
||||
} else if(x == 0.0f) {
|
||||
return 0;
|
||||
} else {
|
||||
return dBTable[lrintf(y/x*dBTableScale)];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,737 +1,35 @@
|
|||
#include "fft.h"
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "utils.h"
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
#define REAL(tr,ti,r,i) (tr*r - ti*i)
|
||||
#define IMAG(tr,ti,r,i) (tr*i + ti*r)
|
||||
|
||||
t_fft *make_fft_buf(int N)
|
||||
void fft128(t_fft *x)
|
||||
{
|
||||
return (t_fft*) malloc(N*sizeof(t_fft));
|
||||
fft<128,1>(x);
|
||||
}
|
||||
|
||||
void free_fft_buf(t_fft *buf)
|
||||
void ifft128(t_fft *x)
|
||||
{
|
||||
free(buf);
|
||||
fft<128,-1>(x);
|
||||
}
|
||||
|
||||
void optimizeFactors(int *f)
|
||||
void fft256(t_fft *x)
|
||||
{
|
||||
int n = 0;
|
||||
for(int k=0;;k++) {
|
||||
if(f[k]==0) break;
|
||||
n++;
|
||||
}
|
||||
int *g = (int*)calloc(n+1,sizeof(int));
|
||||
for(int k=0;k<n;k++) {
|
||||
g[k] = f[k];
|
||||
}
|
||||
|
||||
int m = 0;
|
||||
for(int k=0;k<n;k++) {
|
||||
int f2 = g[k] * g[k+1];
|
||||
if(f2 == 6) {
|
||||
f[m++] = 6;
|
||||
k++;
|
||||
} else if(f2 == 4) {
|
||||
f[m++] = 4;
|
||||
k++;
|
||||
} else {
|
||||
f[m++] = g[k];
|
||||
}
|
||||
}
|
||||
f[m] = 0;
|
||||
free(g);
|
||||
fft<256,1>(x);
|
||||
}
|
||||
|
||||
int *getOrder(int n, int *N1, int *N2)
|
||||
void ifft256(t_fft *x)
|
||||
{
|
||||
int N = N1[0]*N2[0];
|
||||
int *order = (int*)calloc(N,sizeof(int));
|
||||
for(int k=0;k<N;k++) {
|
||||
int kr = 0;
|
||||
int k0 = k;
|
||||
for(int i=0;i<n;i++) {
|
||||
int k2 = k0%N2[i];
|
||||
k0 /= N2[i];
|
||||
kr += N1[i]*k2;
|
||||
}
|
||||
order[k] = kr;
|
||||
}
|
||||
|
||||
return order;
|
||||
fft<256,-1>(x);
|
||||
}
|
||||
|
||||
t_fft **calcTwiddles(int n, int *N1, int *N2, int *order, int sign)
|
||||
void fft384(t_fft *x)
|
||||
{
|
||||
t_fft **t = (t_fft**)calloc(n,sizeof(t_fft*));
|
||||
|
||||
for(int i=0;i<n;i++) {
|
||||
int Np = N1[i]*N2[i];
|
||||
t[i] = (t_fft*)calloc(Np,sizeof(t_fft));
|
||||
for(int k=0;k<Np;k++) {
|
||||
t[i][k][0] = cos((real)(-sign)*TWOPI*(real)k/(real)Np);
|
||||
t[i][k][1] = sin((real)(-sign)*TWOPI*(real)k/(real)Np);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
fft<384,1>(x);
|
||||
}
|
||||
|
||||
fft_func *getFuncs(int *f)
|
||||
void fft512(t_fft *x)
|
||||
{
|
||||
int n = 0;
|
||||
for(int k=0;;k++) {
|
||||
if(f[k] == 0) break;
|
||||
n++;
|
||||
}
|
||||
|
||||
fft_func *func = (fft_func*)calloc(n,sizeof(fft_func));
|
||||
for(int k=0;k<n;k++) {
|
||||
switch(f[k]) {
|
||||
case 2 : func[k] = fft2; break;
|
||||
case 3 : func[k] = fft3; break;
|
||||
case 4 : func[k] = fft4; break;
|
||||
case 5 : func[k] = fft5; break;
|
||||
case 6 : func[k] = fft6; break;
|
||||
case 7 : func[k] = fft7; break;
|
||||
}
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
int *getN1(int *f, int N)
|
||||
{
|
||||
int n = 0;
|
||||
for(int k=0;;k++) {
|
||||
if(f[k] == 0) break;
|
||||
n++;
|
||||
}
|
||||
|
||||
int *N1 = (int*)calloc(n,sizeof(int));
|
||||
for(int k=0;k<n;k++) {
|
||||
N /= f[k];
|
||||
N1[k] = N;
|
||||
}
|
||||
return N1;
|
||||
}
|
||||
|
||||
int getNFactors(int *f)
|
||||
{
|
||||
int n = 0;
|
||||
for(int k=0;;k++) {
|
||||
if(f[k] == 0) break;
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
fftplan *planFFT(int N)
|
||||
{
|
||||
int *factors = factor(N);
|
||||
optimizeFactors(factors);
|
||||
|
||||
fftplan *plan = new fftplan;
|
||||
plan->dir = 1;
|
||||
plan->n = getNFactors(factors);
|
||||
plan->N2 = factors;
|
||||
plan->N1 = getN1(factors,N);
|
||||
plan->order = getOrder(plan->n,plan->N1,plan->N2);
|
||||
plan->reorder = (t_fft*)malloc(N*sizeof(t_fft));
|
||||
plan->t = calcTwiddles(plan->n,plan->N1,plan->N2,plan->order,1);
|
||||
plan->f = getFuncs(factors);
|
||||
plan->N = N;
|
||||
plan->norm = 1.0;
|
||||
return plan;
|
||||
}
|
||||
|
||||
fftplan *planIFFT(int N)
|
||||
{
|
||||
int *factors = factor(N);
|
||||
optimizeFactors(factors);
|
||||
fftplan *plan = new fftplan;
|
||||
plan->dir = -1;
|
||||
plan->n = getNFactors(factors);
|
||||
plan->N2 = factors;
|
||||
plan->N1 = getN1(factors,N);
|
||||
plan->order = getOrder(plan->n,plan->N1,plan->N2);
|
||||
plan->reorder = (t_fft*)malloc(N*sizeof(t_fft));
|
||||
plan->t = calcTwiddles(plan->n,plan->N1,plan->N2,plan->order,-1);
|
||||
plan->f = getFuncs(factors);
|
||||
plan->N = N;
|
||||
plan->norm = 1.0f/(real)N;
|
||||
return plan;
|
||||
}
|
||||
|
||||
void destroy_fftplan(fftplan *plan)
|
||||
{
|
||||
free(plan->reorder);
|
||||
free(plan->order);
|
||||
free(plan->f);
|
||||
for(int i=0;i<plan->n;i++)
|
||||
free(plan->t[i]);
|
||||
free(plan->t);
|
||||
free(plan->N1);
|
||||
free(plan->N2);
|
||||
free(plan);
|
||||
}
|
||||
|
||||
void FFT(fftplan *plan, t_fft *x)
|
||||
{
|
||||
fft(plan,x,0,0);
|
||||
|
||||
for(int k=0;k<plan->N;k++) {
|
||||
plan->reorder[k][0] = x[k][0];
|
||||
plan->reorder[k][1] = x[k][1];
|
||||
}
|
||||
for(int k=0;k<plan->N;k++) {
|
||||
int kr = plan->order[k];
|
||||
if(k != kr) {
|
||||
x[k][0] = plan->reorder[kr][0];
|
||||
x[k][1] = plan->reorder[kr][1];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void IFFT(fftplan *plan, t_fft *x)
|
||||
{
|
||||
FFT(plan,x);
|
||||
/*
|
||||
real norm = plan->norm;
|
||||
for(int k=0;k<plan->N;k++) {
|
||||
x[k][0] *= norm;
|
||||
x[k][1] *= norm;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void fft(fftplan *plan, t_fft *x, int r, int i)
|
||||
{
|
||||
int N1 = plan->N1[i];
|
||||
int N2 = plan->N2[i];
|
||||
for(int n1=0;n1<N1;n1++) {
|
||||
(plan->f[i])(x,n1,N1,r,plan->t[i],plan->dir);
|
||||
}
|
||||
if(N1==1) return;
|
||||
for(int k2=0;k2<N2;k2++) {
|
||||
fft(plan,x,r,i+1);
|
||||
r += N1;
|
||||
}
|
||||
}
|
||||
|
||||
void fft2(t_fft *x, int n1, int N1, int r, t_fft *t, int dir)
|
||||
{
|
||||
int i = r+n1;
|
||||
real *x0 = x[i]; i+= N1;
|
||||
real *x1 = x[i];
|
||||
|
||||
real y0 = x0[0] - x1[0];
|
||||
real y1 = x0[1] - x1[1];
|
||||
|
||||
x0[0] += x1[0];
|
||||
x0[1] += x1[1];
|
||||
|
||||
real *t1 = t[n1];
|
||||
real t10 = t1[0];
|
||||
real t11 = t1[1];
|
||||
x1[0] = REAL(t10,t11,y0,y1);
|
||||
x1[1] = IMAG(t10,t11,y0,y1);
|
||||
}
|
||||
|
||||
#define T300 0.5f
|
||||
#define T301 0.86602540378444f
|
||||
void fft3(t_fft *x, int n1, int N1, int r, t_fft *t, int dir)
|
||||
{
|
||||
int i = r+n1;
|
||||
real *x0 = x[i]; i+=N1;
|
||||
real *x1 = x[i]; i+=N1;
|
||||
real *x2 = x[i];
|
||||
|
||||
real z00 = x1[0] + x2[0];
|
||||
real z01 = x1[1] + x2[1];
|
||||
|
||||
real z10 = x0[0] - T300*z00;
|
||||
real z11 = x0[1] - T300*z01;
|
||||
|
||||
real z20;
|
||||
real z21;
|
||||
if(dir==1) {
|
||||
z20 = T301*(x2[0] - x1[0]);
|
||||
z21 = T301*(x2[1] - x1[1]);
|
||||
} else {
|
||||
z20 = T301*(x1[0] - x2[0]);
|
||||
z21 = T301*(x1[1] - x2[1]);
|
||||
}
|
||||
|
||||
x0[0] = z00 + x0[0];
|
||||
x0[1] = z01 + x0[1];
|
||||
|
||||
real z30 = z10 - z21;
|
||||
real z31 = z11 + z20;
|
||||
real *t1 = t[n1];
|
||||
real t10 = t1[0];
|
||||
real t11 = t1[1];
|
||||
x1[0] = REAL(t10,t11,z30,z31);
|
||||
x1[1] = IMAG(t10,t11,z30,z31);
|
||||
|
||||
real z40 = z10 + z21;
|
||||
real z41 = z11 - z20;
|
||||
real *t2 = t[n1<<1];
|
||||
real t20 = t2[0];
|
||||
real t21 = t2[1];
|
||||
x2[0] = REAL(t20,t21,z40,z41);
|
||||
x2[1] = IMAG(t20,t21,z40,z41);
|
||||
}
|
||||
|
||||
void fft4(t_fft *x, int n1, int N1, int r, t_fft *t, int dir)
|
||||
{
|
||||
int i = r+n1;
|
||||
real *x0 = x[i]; i+=N1;
|
||||
real *x1 = x[i]; i+=N1;
|
||||
real *x2 = x[i]; i+=N1;
|
||||
real *x3 = x[i];
|
||||
|
||||
real z20 = x0[0] - x2[0];
|
||||
real z21 = x0[1] - x2[1];
|
||||
real z00 = x0[0] + x2[0];
|
||||
real z01 = x0[1] + x2[1];
|
||||
|
||||
real z10 = x1[0] + x3[0];
|
||||
real z11 = x1[1] + x3[1];
|
||||
|
||||
x0[0] = z00 + z10;
|
||||
x0[1] = z01 + z11;
|
||||
|
||||
real y20 = z00 - z10;
|
||||
real y21 = z01 - z11;
|
||||
real *t2 = t[n1<<1];
|
||||
real t20 = t2[0];
|
||||
real t21 = t2[1];
|
||||
x2[0] = REAL(t20,t21,y20,y21);
|
||||
x2[1] = IMAG(t20,t21,y20,y21);
|
||||
|
||||
real z30;
|
||||
real z31;
|
||||
if(dir==1) {
|
||||
z30 = (x3[0] - x1[0]);
|
||||
z31 = (x3[1] - x1[1]);
|
||||
} else {
|
||||
z30 = (x1[0] - x3[0]);
|
||||
z31 = (x1[1] - x3[1]);
|
||||
}
|
||||
|
||||
real y10 = z20 - z31;
|
||||
real y11 = z21 + z30;
|
||||
real *t1 = t[n1];
|
||||
real t10 = t1[0];
|
||||
real t11 = t1[1];
|
||||
x1[0] = REAL(t10,t11,y10,y11);
|
||||
x1[1] = IMAG(t10,t11,y10,y11);
|
||||
|
||||
real y30 = z20 + z31;
|
||||
real y31 = z21 - z30;
|
||||
real *t3 = t[n1*3];
|
||||
real t30 = t3[0];
|
||||
real t31 = t3[1];
|
||||
x3[0] = REAL(t30,t31,y30,y31);
|
||||
x3[1] = IMAG(t30,t31,y30,y31);
|
||||
}
|
||||
|
||||
#define T500 0.95105651629515f
|
||||
#define T501 0.58778525229247f
|
||||
#define T510 0.55901699437495f
|
||||
#define T511 0.25f
|
||||
|
||||
void fft5(t_fft *x, int n1, int N1, int r, t_fft *t, int dir)
|
||||
{
|
||||
int i = r+n1;
|
||||
real *x0 = x[i]; i+=N1;
|
||||
real *x1 = x[i]; i+=N1;
|
||||
real *x2 = x[i]; i+=N1;
|
||||
real *x3 = x[i]; i+=N1;
|
||||
real *x4 = x[i];
|
||||
|
||||
real z00 = x1[0] + x4[0];
|
||||
real z01 = x1[1] + x4[1];
|
||||
|
||||
real z10 = x2[0] + x3[0];
|
||||
real z11 = x2[1] + x3[1];
|
||||
|
||||
real z20 = x1[0] - x4[0];
|
||||
real z21 = x1[1] - x4[1];
|
||||
|
||||
real z30 = x2[0] - x3[0];
|
||||
real z31 = x2[1] - x3[1];
|
||||
|
||||
real z40 = z00 + z10;
|
||||
real z41 = z01 + z11;
|
||||
|
||||
real z50 = T510*(z00 - z10);
|
||||
real z51 = T510*(z01 - z11);
|
||||
|
||||
real z60 = x0[0] - T511*z40;
|
||||
real z61 = x0[1] - T511*z41;
|
||||
|
||||
real z70 = z50 + z60;
|
||||
real z71 = z51 + z61;
|
||||
|
||||
real z80 = z60 - z50;
|
||||
real z81 = z61 - z51;
|
||||
|
||||
real z90;
|
||||
real z91;
|
||||
if(dir==1) {
|
||||
z90 = -(T500*z20 + T501*z30);
|
||||
z91 = -(T500*z21 + T501*z31);
|
||||
} else {
|
||||
z90 = (T500*z20 + T501*z30);
|
||||
z91 = (T500*z21 + T501*z31);
|
||||
}
|
||||
|
||||
real z100;
|
||||
real z101;
|
||||
if(dir==1) {
|
||||
z100 = (T500*z30 - T501*z20);
|
||||
z101 = (T500*z31 - T501*z21);
|
||||
} else {
|
||||
z100 = (T501*z20 - T500*z30);
|
||||
z101 = (T501*z21 - T500*z31);
|
||||
}
|
||||
|
||||
x0[0] = x0[0] + z40;
|
||||
x0[1] = x0[1] + z41;
|
||||
|
||||
real y10 = z70 - z91;
|
||||
real y11 = z71 + z90;
|
||||
real *t1 = t[n1];
|
||||
real t10 = t1[0];
|
||||
real t11 = t1[1];
|
||||
x1[0] = REAL(t10,t11,y10,y11);
|
||||
x1[1] = IMAG(t10,t11,y10,y11);
|
||||
|
||||
real y20 = z80 - z101;
|
||||
real y21 = z81 + z100;
|
||||
real *t2 = t[n1<<1];
|
||||
real t20 = t2[0];
|
||||
real t21 = t2[1];
|
||||
x2[0] = REAL(t20,t21,y20,y21);
|
||||
x2[1] = IMAG(t20,t21,y20,y21);
|
||||
|
||||
real y30 = z80 + z101;
|
||||
real y31 = z81 - z100;
|
||||
real *t3 = t[n1*3];
|
||||
real t30 = t3[0];
|
||||
real t31 = t3[1];
|
||||
x3[0] = REAL(t30,t31,y30,y31);
|
||||
x3[1] = IMAG(t30,t31,y30,y31);
|
||||
|
||||
real y40 = z70 + z91;
|
||||
real y41 = z71 - z90;
|
||||
real *t4 = t[n1<<2];
|
||||
real t40 = t4[0];
|
||||
real t41 = t4[1];
|
||||
x4[0] = REAL(t40,t41,y40,y41);
|
||||
x4[1] = IMAG(t40,t41,y40,y41);
|
||||
}
|
||||
|
||||
#define T600 0.86602540378444f
|
||||
#define T601 0.5f
|
||||
void fft6(t_fft *x, int n1, int N1, int r, t_fft *t, int dir)
|
||||
{
|
||||
int i = r+n1;
|
||||
real *x0 = x[i]; i+=N1;
|
||||
real *x1 = x[i]; i+=N1;
|
||||
real *x2 = x[i]; i+=N1;
|
||||
real *x3 = x[i]; i+=N1;
|
||||
real *x4 = x[i]; i+=N1;
|
||||
real *x5 = x[i];
|
||||
|
||||
real za00 = x2[0] + x4[0];
|
||||
real za01 = x2[1] + x4[1];
|
||||
|
||||
real za10 = x0[0] - T601*za00;
|
||||
real za11 = x0[1] - T601*za01;
|
||||
|
||||
real za20;
|
||||
real za21;
|
||||
if(dir==1) {
|
||||
za20 = T600*(x4[0] - x2[0]);
|
||||
za21 = T600*(x4[1] - x2[1]);
|
||||
} else {
|
||||
za20 = T600*(x2[0] - x4[0]);
|
||||
za21 = T600*(x2[1] - x4[1]);
|
||||
}
|
||||
|
||||
real a00 = x0[0] + za00;
|
||||
real a01 = x0[1] + za01;
|
||||
|
||||
real a10 = za10 - za21;
|
||||
real a11 = za11 + za20;
|
||||
|
||||
real a20 = za10 + za21;
|
||||
real a21 = za11 - za20;
|
||||
|
||||
real zb00 = x1[0] + x5[0];
|
||||
real zb01 = x1[1] + x5[1];
|
||||
|
||||
real zb10 = x3[0] - T601*zb00;
|
||||
real zb11 = x3[1] - T601*zb01;
|
||||
|
||||
real zb20;
|
||||
real zb21;
|
||||
if(dir==1) {
|
||||
zb20 = T600*(x1[0] - x5[0]);
|
||||
zb21 = T600*(x1[1] - x5[1]);
|
||||
} else {
|
||||
zb20 = T600*(x5[0] - x1[0]);
|
||||
zb21 = T600*(x5[1] - x1[1]);
|
||||
}
|
||||
|
||||
real b00 = x3[0] + zb00;
|
||||
real b01 = x3[1] + zb01;
|
||||
|
||||
real b10 = zb10 - zb21;
|
||||
real b11 = zb11 + zb20;
|
||||
|
||||
real b20 = zb10 + zb21;
|
||||
real b21 = zb11 - zb20;
|
||||
|
||||
x0[0] = a00 + b00;
|
||||
x0[1] = a01 + b01;
|
||||
|
||||
real y10 = a10 - b10;
|
||||
real y11 = a11 - b11;
|
||||
real *t1 = t[n1];
|
||||
real t10 = t1[0];
|
||||
real t11 = t1[1];
|
||||
x1[0] = REAL(t10,t11,y10,y11);
|
||||
x1[1] = IMAG(t10,t11,y10,y11);
|
||||
|
||||
real y20 = a20 + b20;
|
||||
real y21 = a21 + b21;
|
||||
real *t2 = t[n1<<1];
|
||||
real t20 = t2[0];
|
||||
real t21 = t2[1];
|
||||
x2[0] = REAL(t20,t21,y20,y21);
|
||||
x2[1] = IMAG(t20,t21,y20,y21);
|
||||
|
||||
real y30 = a00 - b00;
|
||||
real y31 = a01 - b01;
|
||||
real *t3 = t[n1*3];
|
||||
real t30 = t3[0];
|
||||
real t31 = t3[1];
|
||||
x3[0] = REAL(t30,t31,y30,y31);
|
||||
x3[1] = IMAG(t30,t31,y30,y31);
|
||||
|
||||
real y40 = a10 + b10;
|
||||
real y41 = a11 + b11;
|
||||
real *t4 = t[n1<<2];
|
||||
real t40 = t4[0];
|
||||
real t41 = t4[1];
|
||||
x4[0] = REAL(t40,t41,y40,y41);
|
||||
x4[1] = IMAG(t40,t41,y40,y41);
|
||||
|
||||
real y50 = a20 - b20;
|
||||
real y51 = a21 - b21;
|
||||
real *t5 = t[n1*5];
|
||||
real t50 = t5[0];
|
||||
real t51 = t5[1];
|
||||
x5[0] = REAL(t50,t51,y50,y51);
|
||||
x5[1] = IMAG(t50,t51,y50,y51);
|
||||
}
|
||||
|
||||
#define C71 -1.16666666666667f
|
||||
#define C72 0.79015646852540f
|
||||
#define C73 0.05585426728965f
|
||||
#define C74 0.73430220123575f
|
||||
#define C75 0.44095855184410f
|
||||
#define C76 0.34087293062393f
|
||||
#define C77 -0.53396936033773f
|
||||
#define C78 0.87484229096166f
|
||||
|
||||
void fft7(t_fft *x, int n1, int N1, int r, t_fft *t, int dir)
|
||||
{
|
||||
int i = r+n1;
|
||||
real *x0 = x[i]; i+=N1;
|
||||
real *x1 = x[i]; i+=N1;
|
||||
real *x2 = x[i]; i+=N1;
|
||||
real *x3 = x[i]; i+=N1;
|
||||
real *x4 = x[i]; i+=N1;
|
||||
real *x5 = x[i]; i+=N1;
|
||||
real *x6 = x[i];
|
||||
|
||||
real u00 = x1[0] + x6[0];
|
||||
real u01 = x1[1] + x6[1];
|
||||
|
||||
real u10 = x1[0] - x6[0];
|
||||
real u11 = x1[1] - x6[1];
|
||||
|
||||
real u20 = x2[0] + x5[0];
|
||||
real u21 = x2[1] + x5[1];
|
||||
|
||||
real u30 = x2[0] - x5[0];
|
||||
real u31 = x2[1] - x5[1];
|
||||
|
||||
real u40 = x4[0] + x3[0];
|
||||
real u41 = x4[1] + x3[1];
|
||||
|
||||
real u50 = x4[0] - x3[0];
|
||||
real u51 = x4[1] - x3[1];
|
||||
|
||||
real u60 = u20 + u00;
|
||||
real u61 = u21 + u01;
|
||||
|
||||
real u70 = u50 + u30;
|
||||
real u71 = u51 + u31;
|
||||
|
||||
real b00 = x0[0] + u60 + u40;
|
||||
real b01 = x0[1] + u61 + u41;
|
||||
|
||||
real b10 = C71*(u60 + u40);
|
||||
real b11 = C71*(u61 + u41);
|
||||
|
||||
real b20 = C72*(u00 - u40);
|
||||
real b21 = C72*(u01 - u41);
|
||||
|
||||
real b30 = C73*(u40 - u20);
|
||||
real b31 = C73*(u41 - u21);
|
||||
|
||||
real b40 = C74*(u20 - u00);
|
||||
real b41 = C74*(u21 - u01);
|
||||
|
||||
real b50;
|
||||
real b51;
|
||||
if(dir==1) {
|
||||
b50 = C75*(u70 + u10);
|
||||
b51 = C75*(u71 + u11);
|
||||
} else {
|
||||
b50 = -C75*(u70 + u10);
|
||||
b51 = -C75*(u71 + u11);
|
||||
}
|
||||
|
||||
real b60;
|
||||
real b61;
|
||||
if(dir==1) {
|
||||
b60 = C76*(u10 - u50);
|
||||
b61 = C76*(u11 - u51);
|
||||
} else {
|
||||
b60 = C76*(u50 - u10);
|
||||
b61 = C76*(u51 - u11);
|
||||
}
|
||||
|
||||
real b70;
|
||||
real b71;
|
||||
if(dir==1) {
|
||||
b70 = C77*(u50 - u30);
|
||||
b71 = C77*(u51 - u31);
|
||||
} else {
|
||||
b70 = C77*(u30 - u50);
|
||||
b71 = C77*(u31 - u51);
|
||||
}
|
||||
|
||||
real b80;
|
||||
real b81;
|
||||
if(dir==1) {
|
||||
b80 = C78*(u30 - u10);
|
||||
b81 = C78*(u31 - u11);
|
||||
} else {
|
||||
b80 = C78*(u10 - u30);
|
||||
b81 = C78*(u11 - u31);
|
||||
}
|
||||
|
||||
real T00 = b00 + b10;
|
||||
real T01 = b01 + b11;
|
||||
|
||||
real T10 = b20 + b30;
|
||||
real T11 = b21 + b31;
|
||||
|
||||
real T20 = b40 - b30;
|
||||
real T21 = b41 - b31;
|
||||
|
||||
real T30 = -b20 - b40;
|
||||
real T31 = -b21 - b41;
|
||||
|
||||
real T40 = b60 + b70;
|
||||
real T41 = b61 + b71;
|
||||
|
||||
real T50 = b80 - b70;
|
||||
real T51 = b81 - b71;
|
||||
|
||||
real T60 = -b80 - b60;
|
||||
real T61 = -b81 - b61;
|
||||
|
||||
real T70 = T00 + T10;
|
||||
real T71 = T01 + T11;
|
||||
|
||||
real T80 = T00 + T20;
|
||||
real T81 = T01 + T21;
|
||||
|
||||
real T90 = T00 + T30;
|
||||
real T91 = T01 + T31;
|
||||
|
||||
real T100 = T40 + b50;
|
||||
real T101 = T41 + b51;
|
||||
|
||||
real T110 = T50 + b50;
|
||||
real T111 = T51 + b51;
|
||||
|
||||
real T120 = T60 + b50;
|
||||
real T121 = T61 + b51;
|
||||
|
||||
x0[0] = b00;
|
||||
x0[1] = b01;
|
||||
|
||||
real y10 = T70 + T101;
|
||||
real y11 = T71 - T100;
|
||||
real *t1 = t[n1];
|
||||
real t10 = t1[0];
|
||||
real t11 = t1[1];
|
||||
x1[0] = REAL(t10,t11,y10,y11);
|
||||
x1[1] = IMAG(t10,t11,y10,y11);
|
||||
|
||||
real y20 = T90 + T121;
|
||||
real y21 = T91 - T120;
|
||||
real *t2 = t[n1<<1];
|
||||
real t20 = t2[0];
|
||||
real t21 = t2[1];
|
||||
x2[0] = REAL(t20,t21,y20,y21);
|
||||
x2[1] = IMAG(t20,t21,y20,y21);
|
||||
|
||||
real y30 = T80 - T111;
|
||||
real y31 = T81 + T110;
|
||||
real *t3 = t[n1*3];
|
||||
real t30 = t3[0];
|
||||
real t31 = t3[1];
|
||||
x3[0] = REAL(t30,t31,y30,y31);
|
||||
x3[1] = IMAG(t30,t31,y30,y31);
|
||||
|
||||
real y40 = T80 + T111;
|
||||
real y41 = T81 - T110;
|
||||
real *t4 = t[n1<<2];
|
||||
real t40 = t4[0];
|
||||
real t41 = t4[1];
|
||||
x4[0] = REAL(t40,t41,y40,y41);
|
||||
x4[1] = IMAG(t40,t41,y40,y41);
|
||||
|
||||
real y50 = T90 - T121;
|
||||
real y51 = T91 + T120;
|
||||
real *t5 = t[n1*5];
|
||||
real t50 = t5[0];
|
||||
real t51 = t5[1];
|
||||
x5[0] = REAL(t50,t51,y50,y51);
|
||||
x5[1] = IMAG(t50,t51,y50,y51);
|
||||
|
||||
real y60 = T70 - T101;
|
||||
real y61 = T71 + T100;
|
||||
real *t6 = t[n1*6];
|
||||
real t60 = t6[0];
|
||||
real t61 = t6[1];
|
||||
x6[0] = REAL(t60,t61,y60,y61);
|
||||
x6[1] = IMAG(t60,t61,y60,y61);
|
||||
fft<512,1>(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,51 +1,853 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef FFT_H
|
||||
#define FFT_H
|
||||
|
||||
#include "sbsms.h"
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef ENABLE_SSE
|
||||
#include "sse.h"
|
||||
#endif
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
typedef real t_fft[2];
|
||||
typedef void (*fftplan)(t_fft *x);
|
||||
void fft128(t_fft *x);
|
||||
void ifft128(t_fft *x);
|
||||
void fft256(t_fft *x);
|
||||
void ifft256(t_fft *x);
|
||||
void fft384(t_fft *x);
|
||||
void fft512(t_fft *x);
|
||||
|
||||
typedef void (*fft_func)(t_fft *x, int n1, int N1, int r, t_fft *t, int dir);
|
||||
|
||||
struct fftplan {
|
||||
fft_func *f;
|
||||
int *order;
|
||||
t_fft *reorder;
|
||||
int *N1;
|
||||
int *N2;
|
||||
int N;
|
||||
int n;
|
||||
int dir;
|
||||
real norm;
|
||||
t_fft **t;
|
||||
template<int N>
|
||||
class Factor {
|
||||
public:
|
||||
enum { value = (N%8==0)?8:(N%7==0)?7:(N%4==0)?4:(N%5==0)?5:(N%6==0)?6:(N%3==0)?3:(N%2==0)?2:1 };
|
||||
};
|
||||
|
||||
t_fft *make_fft_buf(int N);
|
||||
void free_fft_buf(t_fft *buf);
|
||||
fftplan *planFFT(int N);
|
||||
fftplan *planIFFT(int N);
|
||||
void destroy_fftplan(fftplan *plan);
|
||||
void FFT(fftplan *plan, t_fft *x);
|
||||
void IFFT(fftplan *plan, t_fft *x);
|
||||
template<int N>
|
||||
class LastFactor {
|
||||
public:
|
||||
enum { radix = Factor<N>::value,
|
||||
stride = N / radix,
|
||||
value = (stride==1?radix:LastFactor<stride>::value) };
|
||||
};
|
||||
|
||||
void fft(fftplan *plan, t_fft *x, int r, int i);
|
||||
void optimizeFactors(int *f);
|
||||
int *getOrder(int n, int *N1, int *N2);
|
||||
t_fft **calcTwiddles(int n, int *N1, int *N2, int dir);
|
||||
fft_func *getFuncs(int *f);
|
||||
int *getN1(int *f, int N);
|
||||
int getNFactors(int *f);
|
||||
template <>
|
||||
class LastFactor<1> {
|
||||
public:
|
||||
enum { value = 1 };
|
||||
};
|
||||
|
||||
void fft2(t_fft *x, int n1, int N1, int r, t_fft *t, int dir);
|
||||
void fft3(t_fft *x, int n1, int N1, int r, t_fft *t, int dir);
|
||||
void fft4(t_fft *x, int n1, int N1, int r, t_fft *t, int dir);
|
||||
void fft5(t_fft *x, int n1, int N1, int r, t_fft *t, int dir);
|
||||
void fft6(t_fft *x, int n1, int N1, int r, t_fft *t, int dir);
|
||||
void fft7(t_fft *x, int n1, int N1, int r, t_fft *t, int dir);
|
||||
template<int istride, int ostride, int radix, int dir>
|
||||
class __fft {
|
||||
public:
|
||||
static inline void execute(t_fft *x, t_fft *y, int step);
|
||||
};
|
||||
|
||||
template <int N, int dir>
|
||||
class FloatTwiddles {
|
||||
public:
|
||||
float c[N];
|
||||
float s[N];
|
||||
FloatTwiddles() {
|
||||
for(int k=0; k<N; k++) {
|
||||
c[k] = cos(TWOPI * (float)k / (float)N);
|
||||
s[k] = sin(TWOPI * (float)(-dir*k) / (float)N);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <int N, int dir>
|
||||
class FloatTwiddle {
|
||||
public:
|
||||
static const float *c;
|
||||
static const float *s;
|
||||
static const FloatTwiddles<N,dir> t;
|
||||
static inline void twiddle(int k, t_fft *x, float r, float i) {
|
||||
float cc = c[k];
|
||||
float ss = s[k];
|
||||
(*x)[0] = cc * r - ss * i;
|
||||
(*x)[1] = ss * r + cc * i;
|
||||
}
|
||||
};
|
||||
|
||||
template <int N, int dir>
|
||||
const FloatTwiddles<N,dir> FloatTwiddle<N,dir>::t;
|
||||
|
||||
template <int N, int dir>
|
||||
const float* FloatTwiddle<N,dir>::c = t.c;
|
||||
|
||||
template <int N, int dir>
|
||||
const float* FloatTwiddle<N,dir>::s = t.s;
|
||||
|
||||
template<int istride, int ostride, int dir>
|
||||
class __fft<istride,ostride,2,dir> {
|
||||
public:
|
||||
enum { i1 = istride, o1 = ostride,
|
||||
ir0 = 0, ii0 = 1, or0 = 0, oi0 = 1,
|
||||
ir1 = i1<<1, ii1 = ir1 + 1, or1 = o1<<1, oi1 = or1 + 1 };
|
||||
static inline void execute(t_fft *_x, t_fft *_y, int step) {
|
||||
float *x = (float*)_x;
|
||||
float *y = (float*)_y;
|
||||
float y0 = x[ir0] - x[ir1]; float y1 = x[ii0] - x[ii1];
|
||||
y[or0] = x[ir0] + x[ir1]; y[oi0] = x[ii0] + x[ii1];
|
||||
y[or1] = y0; y[oi1] = y1;
|
||||
}
|
||||
};
|
||||
|
||||
template<int istride, int ostride, int dir>
|
||||
class __fft<istride,ostride,3,dir> {
|
||||
public:
|
||||
enum { N = istride * 3,
|
||||
i1_ = istride, o1 = ostride,
|
||||
i2_ = istride + istride, o2 = o1 + ostride,
|
||||
i1 = (dir==1?i1_:i2_),
|
||||
i2 = (dir==1?i2_:i1_),
|
||||
ir0 = 0, ii0 = 1, or0 = 0, oi0 = 1,
|
||||
ir1 = i1<<1, ii1 = ir1 + 1, or1 = o1<<1, oi1 = or1 + 1,
|
||||
ir2 = i2<<1, ii2 = ir2 + 1, or2 = o2<<1, oi2 = or2 + 1 };
|
||||
static inline void execute(t_fft *_x, t_fft *_y, int step) {
|
||||
float *x = (float*)_x;
|
||||
float *y = (float*)_y;
|
||||
float z00 = x[ir1] + x[ir2]; float z01 = x[ii1] + x[ii2];
|
||||
float z10 = x[ir0] - 0.5f*z00; float z11 = x[ii0] - 0.5f*z01;
|
||||
float z20 = 0.86602540378444f*(x[ir2] - x[ir1]); float z21 = 0.86602540378444f*(x[ii2] - x[ii1]);
|
||||
y[or0] = x[ir0] + z00; y[oi0] = x[ii0] + z01;
|
||||
if(step) {
|
||||
FloatTwiddle<N,dir>::twiddle(step, _y+o1,z10 - z21,z11 + z20);
|
||||
FloatTwiddle<N,dir>::twiddle(step+step, _y+o2,z10 + z21,z11 - z20);
|
||||
} else {
|
||||
y[or1] = z10 - z21; y[oi1] = z11 + z20;
|
||||
y[or2] = z10 + z21; y[oi2] = z11 - z20;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<int istride, int ostride, int dir>
|
||||
class __fft<istride,ostride,5,dir> {
|
||||
public:
|
||||
enum { N = istride*5,
|
||||
i0 = 0, o0 = 0,
|
||||
i1_ = i0 + istride, o1 = o0 + ostride,
|
||||
i2_ = i1_ + istride, o2 = o1 + ostride,
|
||||
i3_ = i2_ + istride, o3 = o2 + ostride,
|
||||
i4_ = i3_ + istride, o4 = o3 + ostride,
|
||||
i1 = (dir==1?i4_:i1_),
|
||||
i2 = (dir==1?i3_:i2_),
|
||||
i3 = (dir==1?i2_:i3_),
|
||||
i4 = (dir==1?i1_:i4_),
|
||||
ir0 = i0<<1, ii0 = ir0 + 1, or0 = o0<<1, oi0 = or0 + 1,
|
||||
ir1 = i1<<1, ii1 = ir1 + 1, or1 = o1<<1, oi1 = or1 + 1,
|
||||
ir2 = i2<<1, ii2 = ir2 + 1, or2 = o2<<1, oi2 = or2 + 1,
|
||||
ir3 = i3<<1, ii3 = ir3 + 1, or3 = o3<<1, oi3 = or3 + 1,
|
||||
ir4 = i4<<1, ii4 = ir4 + 1, or4 = o4<<1, oi4 = or4 + 1 };
|
||||
static inline void execute(t_fft *_x, t_fft *_y, int step) {
|
||||
float *x = (float*)_x;
|
||||
float *y = (float*)_y;
|
||||
float z00, z01, z10, z11, z20, z21, z30, z31, z40, z41, z50, z51, z60, z61, z70, z71, z80, z81, z90, z91, z100, z101;
|
||||
z00 = x[ir1] + x[ir4]; z01 = x[ii1] + x[ii4];
|
||||
z10 = x[ir2] + x[ir3]; z11 = x[ii2] + x[ii3];
|
||||
z20 = x[ir1] - x[ir4]; z21 = x[ii1] - x[ii4];
|
||||
z30 = x[ir2] - x[ir3]; z31 = x[ii2] - x[ii3];
|
||||
z40 = z00 + z10; z41 = z01 + z11;
|
||||
z50 = 0.55901699437495f*(z00 - z10); z51 = 0.55901699437495f*(z01 - z11);
|
||||
z60 = x[ir0] - 0.25f*z40; z61 = x[ii0] - 0.25f*z41;
|
||||
z70 = z50 + z60; z71 = z51 + z61;
|
||||
z80 = z60 - z50; z81 = z61 - z51;
|
||||
z90 = 0.95105651629515f*z20 + 0.58778525229247f*z30; z91 = 0.95105651629515f*z21 + 0.58778525229247f*z31;
|
||||
z100 = 0.58778525229247f*z20 - 0.95105651629515f*z30; z101 = 0.58778525229247f*z21 - 0.95105651629515f*z31;
|
||||
y[or0] = x[ir0] + z40; y[oi0] = x[ii0] + z41;
|
||||
if(step) {
|
||||
int step2 = step + step;
|
||||
FloatTwiddle<N,dir>::twiddle(step,_y+o1,z70 - z91,z71 + z90);
|
||||
FloatTwiddle<N,dir>::twiddle(step2,_y+o2,z80 - z101,z81 + z100);
|
||||
FloatTwiddle<N,dir>::twiddle(step2+step,_y+o3,z80 + z101,z81 - z100);
|
||||
FloatTwiddle<N,dir>::twiddle(step2+step2,_y+o4,z70 + z91,z71 - z90);
|
||||
} else {
|
||||
y[or1] = z70 - z91; y[oi1] = z71 + z90;
|
||||
y[or2] = z80 - z101; y[oi2] = z81 + z100;
|
||||
y[or3] = z80 + z101; y[oi3] = z81 - z100;
|
||||
y[or4] = z70 + z91; y[oi4] = z71 - z90;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<int istride, int ostride, int dir>
|
||||
class __fft<istride,ostride,6,dir> {
|
||||
public:
|
||||
enum { N = istride*6,
|
||||
i0 = 0, o0 = 0,
|
||||
i1_ = i0 + istride, o1 = o0 + ostride,
|
||||
i2_ = i1_ + istride, o2 = o1 + ostride,
|
||||
i3 = i2_ + istride, o3 = o2 + ostride,
|
||||
i4_ = i3 + istride, o4 = o3 + ostride,
|
||||
i5_ = i4_ + istride, o5 = o4 + ostride,
|
||||
i1 = (dir==1?i1_:i5_),
|
||||
i2 = (dir==1?i2_:i4_),
|
||||
i4 = (dir==1?i4_:i2_),
|
||||
i5 = (dir==1?i5_:i1_),
|
||||
ir0 = i0<<1, ii0 = ir0 + 1, or0 = o0<<1, oi0 = or0 + 1,
|
||||
ir1 = i1<<1, ii1 = ir1 + 1, or1 = o1<<1, oi1 = or1 + 1,
|
||||
ir2 = i2<<1, ii2 = ir2 + 1, or2 = o2<<1, oi2 = or2 + 1,
|
||||
ir3 = i3<<1, ii3 = ir3 + 1, or3 = o3<<1, oi3 = or3 + 1,
|
||||
ir4 = i4<<1, ii4 = ir4 + 1, or4 = o4<<1, oi4 = or4 + 1,
|
||||
ir5 = i5<<1, ii5 = ir5 + 1, or5 = o5<<1, oi5 = or5 + 1 };
|
||||
static inline void execute(t_fft *_x, t_fft *_y, int step) {
|
||||
float *x = (float*)_x;
|
||||
float *y = (float*)_y;
|
||||
float za00, za01, za10, za11, za20, za21;
|
||||
float a00, a01, a10, a11, a20, a21;
|
||||
float zb00, zb01, zb10, zb11, zb20, zb21;
|
||||
float b00, b01, b10, b11, b20, b21;
|
||||
za00 = x[ir2] + x[ir4]; za01 = x[ii2] + x[ii4];
|
||||
za10 = x[ir0] - 0.5f*za00; za11 = x[ii0] - 0.5f*za01;
|
||||
za20 = 0.86602540378444f*(x[ir4] - x[ir2]); za21 = 0.86602540378444f*(x[ii4] - x[ii2]);
|
||||
a00 = x[ir0] + za00; a01 = x[ii0] + za01;
|
||||
a10 = za10 - za21; a11 = za11 + za20;
|
||||
a20 = za10 + za21; a21 = za11 - za20;
|
||||
zb00 = x[ir1] + x[ir5]; zb01 = x[ii1] + x[ii5];
|
||||
zb10 = x[ir3] - 0.5f*zb00; zb11 = x[ii3] - 0.5f*zb01;
|
||||
zb20 = 0.86602540378444f*(x[ir1] - x[ir5]); zb21 = 0.86602540378444f*(x[ii1] - x[ii5]);
|
||||
b00 = x[ir3] + zb00; b01 = x[ii3] + zb01;
|
||||
b10 = zb10 - zb21; b11 = zb11 + zb20;
|
||||
b20 = zb10 + zb21; b21 = zb11 - zb20;
|
||||
y[or0] = a00 + b00; y[oi0] = a01 + b01;
|
||||
if(step) {
|
||||
FloatTwiddle<N,dir>::twiddle(step,_y+o1,a10 - b10,a11 - b11);
|
||||
int step2 = step + step;
|
||||
FloatTwiddle<N,dir>::twiddle(step2,_y+o2,a20 + b20,a21 + b21);
|
||||
int step3 = step2 + step;
|
||||
FloatTwiddle<N,dir>::twiddle(step3,_y+o3,a00 - b00,a01 - b01);
|
||||
FloatTwiddle<N,dir>::twiddle(step2+step2,_y+o4,a10 + b10,a11 + b11);
|
||||
FloatTwiddle<N,dir>::twiddle(step3+step2,_y+o5,a20 - b20,a21 - b21);
|
||||
} else {
|
||||
y[or1] = a10 - b10; y[oi1] = a11 - b11;
|
||||
y[or2] = a20 + b20; y[oi2] = a21 + b21;
|
||||
y[or3] = a00 - b00; y[oi3] = a01 - b01;
|
||||
y[or4] = a10 + b10; y[oi4] = a11 + b11;
|
||||
y[or5] = a20 - b20; y[oi5] = a21 - b21;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<int istride, int ostride, int dir>
|
||||
class __fft<istride,ostride,7,dir> {
|
||||
public:
|
||||
enum { N = istride*7,
|
||||
i0 = 0, o0 = 0,
|
||||
i1 = i0 + istride, o1 = o0 + ostride,
|
||||
i2 = i1 + istride, o2 = o1 + ostride,
|
||||
i3 = i2 + istride, o3 = o2 + ostride,
|
||||
i4 = i3 + istride, o4 = o3 + ostride,
|
||||
i5 = i4 + istride, o5 = o4 + ostride,
|
||||
i6 = i5 + istride, o6 = o5 + ostride,
|
||||
ir0 = i0<<1, ii0 = ir0 + 1, or0 = o0<<1, oi0 = or0 + 1,
|
||||
ir1 = i1<<1, ii1 = ir1 + 1, or1 = o1<<1, oi1 = or1 + 1,
|
||||
ir2 = i2<<1, ii2 = ir2 + 1, or2 = o2<<1, oi2 = or2 + 1,
|
||||
ir3 = i3<<1, ii3 = ir3 + 1, or3 = o3<<1, oi3 = or3 + 1,
|
||||
ir4 = i4<<1, ii4 = ir4 + 1, or4 = o4<<1, oi4 = or4 + 1,
|
||||
ir5 = i5<<1, ii5 = ir5 + 1, or5 = o5<<1, oi5 = or5 + 1,
|
||||
ir6 = i6<<1, ii6 = ir6 + 1, or6 = o6<<1, oi6 = or6 + 1 };
|
||||
static inline void execute(t_fft *_x, t_fft *_y, int step) {
|
||||
float *x = (float*)_x;
|
||||
float *y = (float*)_y;
|
||||
float u00, u01, u10, u11, u20, u21, u30, u31, u40, u41, u50, u51, u60, u61, u70, u71;
|
||||
float b00, b01, b10, b11, b20, b21, b30, b31, b40, b41, b50, b51, b60, b61, b70, b71, b80, b81;
|
||||
float T00, T01, T10, T11, T20, T21, T30, T31, T40, T41, T50, T51, T60, T61, T70, T71, T80, T81, T90, T91, T100, T101, T110, T111, T120, T121;
|
||||
u00 = x[ir1] + x[ir6]; u01 = x[ii1] + x[ii6];
|
||||
u10 = x[ir1] - x[ir6]; u11 = x[ii1] - x[ii6];
|
||||
u20 = x[ir2] + x[ir5]; u21 = x[ii2] + x[ii5];
|
||||
u30 = x[ir2] - x[ir5]; u31 = x[ii2] - x[ii5];
|
||||
u40 = x[ir4] + x[ir3]; u41 = x[ii4] + x[ii3];
|
||||
u50 = x[ir4] - x[ir3]; u51 = x[ii4] - x[ii3];
|
||||
u60 = u20 + u00; u61 = u21 + u01;
|
||||
u70 = u50 + u30; u71 = u51 + u31;
|
||||
b00 = x[ir0] + u60 + u40; b01 = x[ii0] + u61 + u41;
|
||||
b10 = -1.16666666666667f*(u60 + u40); b11 = -1.16666666666667f*(u61 + u41);
|
||||
b20 = 0.79015646852540f*(u00 - u40); b21 = 0.79015646852540f*(u01 - u41);
|
||||
b30 = 0.05585426728965f*(u40 - u20); b31 = 0.05585426728965f*(u41 - u21);
|
||||
b40 = 0.73430220123575f*(u20 - u00); b41 = 0.73430220123575f*(u21 - u01);
|
||||
if(dir==1) {
|
||||
b50 = 0.44095855184410f*(u70 + u10);
|
||||
b51 = 0.44095855184410f*(u71 + u11);
|
||||
b60 = 0.34087293062393f*(u10 - u50);
|
||||
b61 = 0.34087293062393f*(u11 - u51);
|
||||
b70 = -0.53396936033773f*(u50 - u30);
|
||||
b71 = -0.53396936033773f*(u51 - u31);
|
||||
b80 = 0.87484229096166f*(u30 - u10);
|
||||
b81 = 0.87484229096166f*(u31 - u11);
|
||||
} else {
|
||||
b50 = -0.44095855184410f*(u70 + u10);
|
||||
b51 = -0.44095855184410f*(u71 + u11);
|
||||
b60 = 0.34087293062393f*(u50 - u10);
|
||||
b61 = 0.34087293062393f*(u51 - u11);
|
||||
b70 = -0.53396936033773f*(u30 - u50);
|
||||
b71 = -0.53396936033773f*(u31 - u51);
|
||||
b80 = 0.87484229096166f*(u10 - u30);
|
||||
b81 = 0.87484229096166f*(u11 - u31);
|
||||
}
|
||||
T00 = b00 + b10; T01 = b01 + b11;
|
||||
T10 = b20 + b30; T11 = b21 + b31;
|
||||
T20 = b40 - b30; T21 = b41 - b31;
|
||||
T30 = -b20 - b40; T31 = -b21 - b41;
|
||||
T40 = b60 + b70; T41 = b61 + b71;
|
||||
T50 = b80 - b70; T51 = b81 - b71;
|
||||
T60 = -b80 - b60; T61 = -b81 - b61;
|
||||
T70 = T00 + T10; T71 = T01 + T11;
|
||||
T80 = T00 + T20; T81 = T01 + T21;
|
||||
T90 = T00 + T30; T91 = T01 + T31;
|
||||
T100 = T40 + b50; T101 = T41 + b51;
|
||||
T110 = T50 + b50; T111 = T51 + b51;
|
||||
T120 = T60 + b50; T121 = T61 + b51;
|
||||
y[or0] = b00; y[oi0] = b01;
|
||||
if(step) {
|
||||
FloatTwiddle<N,dir>::twiddle(step,_y+o1,T70 + T101,T71 - T100);
|
||||
int step2 = step + step;
|
||||
FloatTwiddle<N,dir>::twiddle(step2,_y+o2,T90 + T121,T91 - T120);
|
||||
int step3 = step2 + step;
|
||||
FloatTwiddle<N,dir>::twiddle(step3,_y+o3,T80 - T111,T81 + T110);
|
||||
FloatTwiddle<N,dir>::twiddle(step2+step2,_y+o4,T80 + T111,T81 - T110);
|
||||
FloatTwiddle<N,dir>::twiddle(step3+step2,_y+o5,T90 - T121,T91 + T120);
|
||||
FloatTwiddle<N,dir>::twiddle(step3+step3,_y+o6,T70 - T101,T71 + T100);
|
||||
} else {
|
||||
y[or1] = T70 + T101; y[oi1] = T71 - T100;
|
||||
y[or2] = T90 + T121; y[oi2] = T91 - T120;
|
||||
y[or3] = T80 - T111; y[oi3] = T81 + T110;
|
||||
y[or4] = T80 + T111; y[oi4] = T81 - T110;
|
||||
y[or5] = T90 - T121; y[oi5] = T91 + T120;
|
||||
y[or6] = T70 - T101; y[oi6] = T71 + T100;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef ENABLE_SSE
|
||||
|
||||
template <int N, int dir>
|
||||
class SSETwiddles {
|
||||
public:
|
||||
simd_vector cs[N];
|
||||
SSETwiddles() {
|
||||
for(int k=0; k<N; k++) {
|
||||
float c = cos(TWOPI * (float)k / (float)N);
|
||||
float s = sin(TWOPI * (float)(-dir*k) / (float)N);
|
||||
simd_vector v = {c,s,c,-s};
|
||||
cs[k] = v;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <int N, int dir>
|
||||
class SSETwiddle {
|
||||
public:
|
||||
static const SSETwiddles<N,dir> t;
|
||||
static const simd_vector *cs;
|
||||
static inline simd_vector twiddle(int k, const simd_vector &v) {
|
||||
return VMUL(cs[k],v);
|
||||
}
|
||||
static inline void twiddle(int k, t_fft *x, const simd_vector &v) {
|
||||
simd_vector y = twiddle(k,v);
|
||||
simd_vector z = VADD(SHUFFLE(y,y,0,1,0,1),SHUFFLE(y,y,3,2,3,2));
|
||||
STOREL(z,x);
|
||||
}
|
||||
static inline void twiddle2(int k1, int k2, t_fft *x1, t_fft *x2, const simd_vector &y1, const simd_vector &y2) {
|
||||
simd_vector v1 = VMUL(cs[k1],y1);
|
||||
simd_vector v2 = VMUL(cs[k2],y2);
|
||||
simd_vector z = VADD(SHUFFLE(v1,v2,0,1,0,1),SHUFFLE(v1,v2,3,2,3,2));
|
||||
STOREL(z,x1);
|
||||
STOREH(z,x2);
|
||||
}
|
||||
};
|
||||
|
||||
template <int N, int dir>
|
||||
const SSETwiddles<N,dir> SSETwiddle<N,dir>::t;
|
||||
|
||||
template <int N, int dir>
|
||||
const simd_vector* SSETwiddle<N,dir>::cs = t.cs;
|
||||
|
||||
template<int istride, int ostride, int dir>
|
||||
class __fft<istride,ostride,4,dir> {
|
||||
public:
|
||||
enum { N = istride * 4,
|
||||
ir0 = 0, or0 = 0,
|
||||
_ir1 = ir0 + istride, or1 = or0 + ostride,
|
||||
ir2 = _ir1 + istride, or2 = or1 + ostride,
|
||||
_ir3 = ir2 + istride, or3 = or2 + ostride,
|
||||
ir1 = (dir==1?_ir3:_ir1),
|
||||
ir3 = (dir==1?_ir1:_ir3) };
|
||||
static inline void execute(t_fft *x, t_fft *y, int step) {
|
||||
simd_vector v1;
|
||||
simd_vector v2;
|
||||
simd_vector v3;
|
||||
simd_vector v4;
|
||||
simd_vector v5;
|
||||
v1 = LOADH(LOADL(v1,x+ir0),x+ir1);
|
||||
v2 = LOADH(LOADL(v2,x+ir2),x+ir3);
|
||||
v3 = VADD(v1,v2);
|
||||
v4 = VSUB(v1,v2);
|
||||
v1 = SHUFFLE(v4,v3,0,1,0,1);
|
||||
v2 = SHUFFLE(v4,v3,3,2,2,3);
|
||||
v3 = VADD(v1,v2);
|
||||
STOREH(v3,y+or0);
|
||||
v4 = VSUB(v1,v2);
|
||||
v1 = SHUFFLE(v4,v3,0,0,1,1);
|
||||
v2 = SHUFFLE(v4,v4,2,2,3,3);
|
||||
v5 = SHUFFLE(v3,v4,0,0,1,1);
|
||||
if(step) {
|
||||
v1 = SSETwiddle<N,dir>::twiddle(step,v1);
|
||||
int step2 = step + step;
|
||||
v2 = SSETwiddle<N,dir>::twiddle(step2,v2);
|
||||
v3 = SSETwiddle<N,dir>::twiddle(step2+step,v5);
|
||||
v3 = VADD(v3,SHUFFLE(v3,v3,3,2,1,0));
|
||||
STOREL(v3,y+or3);
|
||||
v5 = VADD(SHUFFLE(v1,v2,0,1,0,1),SHUFFLE(v1,v2,3,2,3,2));
|
||||
STOREL(v5,y+or1);
|
||||
STOREH(v5,y+or2);
|
||||
} else {
|
||||
v5 = SHUFFLE(v5,v5,0,2,0,2);
|
||||
STOREL(v5,y+or3);
|
||||
v3 = SHUFFLE(v1,v2,0,2,0,2);
|
||||
STOREL(v3,y+or1);
|
||||
STOREH(v3,y+or2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<int istride, int ostride>
|
||||
class __fft<istride,ostride,8,1> {
|
||||
public:
|
||||
enum { N = istride*8,
|
||||
i0 = 0, o0 = 0,
|
||||
i1 = i0 + istride, o1 = o0 + ostride,
|
||||
i2 = i1 + istride, o2 = o1 + ostride,
|
||||
i3 = i2 + istride, o3 = o2 + ostride,
|
||||
i4 = i3 + istride, o4 = o3 + ostride,
|
||||
i5 = i4 + istride, o5 = o4 + ostride,
|
||||
i6 = i5 + istride, o6 = o5 + ostride,
|
||||
i7 = i6 + istride, o7 = o6 + ostride };
|
||||
static inline void execute(t_fft *x, t_fft *y, int step) {
|
||||
simd_vector v1,v2,v3,v4,v5,v6,v7,v8;
|
||||
simd_vector x02,x37,x15,x17,x53,x46;
|
||||
simd_vector w1, w2, w3, w4;
|
||||
w1 = LOADH(LOADL(w1,x+i0),x+i6);
|
||||
w2 = LOADH(LOADL(w2,x+i4),x+i2);
|
||||
w3 = VADD(w1,w2);
|
||||
w4 = VSUB(w1,w2);
|
||||
v1 = LOADH(LOADL(v1,x+i1),x+i7);
|
||||
v2 = LOADH(LOADL(v2,x+i5),x+i3);
|
||||
v3 = VADD(v1,v2);
|
||||
v4 = VSUB(v1,v2);
|
||||
v5 = SHUFFLE(v3,v4,2,1,0,1); //(z10,z01,z20,z21)
|
||||
v6 = SHUFFLE(v3,v4,0,3,3,2); //(z00,z11,z31,z30)
|
||||
v7 = VADD(v5,v6); // (x1,y30,y11)
|
||||
v8 = VSUB(v5,v6); // (x51,x50,y10,y31)
|
||||
x15 = SHUFFLE(v7,v8,0,1,1,0); //(x1,x5)
|
||||
v2 = SHUFFLE(v8,v8,3,3,3,2); //(-,-,y31,y10)
|
||||
v3 = VADD(v7,v2);
|
||||
v4 = VSUB(v7,v2);
|
||||
v5 = SHUFFLE(v3,v4,2,3,2,3);
|
||||
x37 = VMUL(SET(0.7071067811865475f),v5); //(-x71,x30,-x70,x31)
|
||||
v5 = SHUFFLE(w3,w4,0,1,0,1); //(z00,z01,z20,z21)
|
||||
v6 = SHUFFLE(w3,w4,2,3,3,2); //(z10,z11,z31,z30)
|
||||
v7 = VADD(v5,v6); //(x0,y30,y11)
|
||||
v8 = VSUB(v5,v6); //(x4,y10,y31)
|
||||
v1 = SHUFFLE(v7,v8,0,1,0,1); //(x0,x4)
|
||||
v2 = SHUFFLE(v8,v7,3,2,2,3); //(x61,x20,x60,x21)
|
||||
x02 = VADD(v1,x15);
|
||||
x46 = VSUB(v1,x15);
|
||||
x17 = VADD(v2,x37);
|
||||
x53 = VSUB(v2,x37);
|
||||
STOREL(x02,y+o0);
|
||||
if(step) {
|
||||
simd_vector y1;
|
||||
simd_vector y2;
|
||||
int step2 = step + step;
|
||||
y1 = SHUFFLE(x02,x02,2,2,3,3);
|
||||
SSETwiddle<N,1>::twiddle(step2,y+o2,y1);
|
||||
int step3 = step2 + step;
|
||||
y1 = SHUFFLE(x53,x53,1,1,3,3);
|
||||
y2 = SHUFFLE(x53,x53,2,2,0,0);
|
||||
SSETwiddle<N,1>::twiddle2(step3+step2,step3,y+o5,y+o3,y1,y2);
|
||||
int step4 = step2 + step2;
|
||||
y1 = SHUFFLE(x46,x46,0,0,1,1);
|
||||
y2 = SHUFFLE(x46,x46,2,2,3,3);
|
||||
SSETwiddle<N,1>::twiddle2(step4,step3+step3,y+o4,y+o6,y1,y2);
|
||||
y1 = SHUFFLE(x17,x17,1,1,3,3);
|
||||
y2 = SHUFFLE(x17,x17,2,2,0,0);
|
||||
SSETwiddle<N,1>::twiddle2(step,step4+step3,y+o1,y+o7,y1,y2);
|
||||
} else {
|
||||
simd_vector y1;
|
||||
y1 = SHUFFLE(x02,x02,2,3,3,3);
|
||||
STOREL(y1,y+o2);
|
||||
y1 = SHUFFLE(x53,x53,1,3,2,0);
|
||||
STOREL(y1,y+o5);
|
||||
STOREH(y1,y+o3);
|
||||
STOREL(x46,y+o4);
|
||||
STOREH(x46,y+o6);
|
||||
y1 = SHUFFLE(x17,x17,1,3,2,0);
|
||||
STOREL(y1,y+o1);
|
||||
STOREH(y1,y+o7);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<int istride, int ostride>
|
||||
class __fft<istride,ostride,8,-1> {
|
||||
public:
|
||||
enum { N = istride*8,
|
||||
i0 = 0, o0 = 0,
|
||||
i1 = i0 + istride, o1 = o0 + ostride,
|
||||
i2 = i1 + istride, o2 = o1 + ostride,
|
||||
i3 = i2 + istride, o3 = o2 + ostride,
|
||||
i4 = i3 + istride, o4 = o3 + ostride,
|
||||
i5 = i4 + istride, o5 = o4 + ostride,
|
||||
i6 = i5 + istride, o6 = o5 + ostride,
|
||||
i7 = i6 + istride, o7 = o6 + ostride };
|
||||
static inline void execute(t_fft *x, t_fft *y, int step) {
|
||||
simd_vector v1,v2,v3,v4,v5,v6,v7,v8;
|
||||
simd_vector x02,x37,x15,x17,x53,x46;
|
||||
simd_vector w1, w2, w3, w4;
|
||||
w1 = LOADH(LOADL(w1,x+i0),x+i2);
|
||||
w2 = LOADH(LOADL(w2,x+i4),x+i6);
|
||||
w3 = VADD(w1,w2);
|
||||
w4 = VSUB(w1,w2);
|
||||
v1 = LOADH(LOADL(v1,x+i1),x+i3);
|
||||
v2 = LOADH(LOADL(v2,x+i5),x+i7);
|
||||
v3 = VADD(v1,v2);
|
||||
v4 = VSUB(v1,v2);
|
||||
v5 = SHUFFLE(v3,v4,0,3,0,1);
|
||||
v6 = SHUFFLE(v3,v4,2,1,3,2);
|
||||
v7 = VADD(v5,v6);
|
||||
v8 = VSUB(v5,v6);
|
||||
x15 = SHUFFLE(v7,v8,0,1,1,0);
|
||||
v2 = SHUFFLE(v8,v8,3,3,3,2);
|
||||
v3 = VADD(v7,v2);
|
||||
v4 = VSUB(v2,v7);
|
||||
v5 = SHUFFLE(v4,v3,2,3,2,3);
|
||||
x37 = VMUL(SET(0.7071067811865475f),v5);
|
||||
v5 = SHUFFLE(w3,w4,0,1,0,1);
|
||||
v6 = SHUFFLE(w3,w4,2,3,3,2);
|
||||
v7 = VADD(v5,v6);
|
||||
v8 = VSUB(v5,v6);
|
||||
v1 = SHUFFLE(v7,v8,0,1,0,1);
|
||||
v2 = SHUFFLE(v8,v7,3,2,2,3);
|
||||
x02 = VADD(v1,x15);
|
||||
x46 = VSUB(v1,x15);
|
||||
x17 = VADD(v2,x37);
|
||||
x53 = VSUB(v2,x37);
|
||||
STOREL(x02,y+o0);
|
||||
if(step) {
|
||||
simd_vector y1;
|
||||
simd_vector y2;
|
||||
int step2 = step + step;
|
||||
y1 = SHUFFLE(x02,x02,2,2,3,3);
|
||||
SSETwiddle<N,-1>::twiddle(step2,y+o2,y1);
|
||||
int step3 = step2 + step;
|
||||
y1 = SHUFFLE(x53,x53,1,1,3,3);
|
||||
y2 = SHUFFLE(x53,x53,2,2,0,0);
|
||||
SSETwiddle<N,-1>::twiddle2(step3+step2,step3,y+o5,y+o3,y1,y2);
|
||||
int step4 = step2 + step2;
|
||||
y1 = SHUFFLE(x46,x46,0,0,1,1);
|
||||
y2 = SHUFFLE(x46,x46,2,2,3,3);
|
||||
SSETwiddle<N,-1>::twiddle2(step4,step3+step3,y+o4,y+o6,y1,y2);
|
||||
y1 = SHUFFLE(x17,x17,1,1,3,3);
|
||||
y2 = SHUFFLE(x17,x17,2,2,0,0);
|
||||
SSETwiddle<N,-1>::twiddle2(step,step4+step3,y+o1,y+o7,y1,y2);
|
||||
} else {
|
||||
simd_vector y1;
|
||||
y1 = SHUFFLE(x02,x02,2,3,3,3);
|
||||
STOREL(y1,y+o2);
|
||||
y1 = SHUFFLE(x53,x53,1,3,2,0);
|
||||
STOREL(y1,y+o5);
|
||||
STOREH(y1,y+o3);
|
||||
STOREL(x46,y+o4);
|
||||
STOREH(x46,y+o6);
|
||||
y1 = SHUFFLE(x17,x17,1,3,2,0);
|
||||
STOREL(y1,y+o1);
|
||||
STOREH(y1,y+o7);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#else // !ENABLE_SSE
|
||||
|
||||
template<int istride, int ostride, int dir>
|
||||
class __fft<istride,ostride,4,dir> {
|
||||
public:
|
||||
enum { N = istride*4,
|
||||
i0 = 0, o0 = 0,
|
||||
i1_ = i0 + istride, o1 = o0 + ostride,
|
||||
i2 = i1_ + istride, o2 = o1 + ostride,
|
||||
i3_ = i2 + istride, o3 = o2 + ostride,
|
||||
i1 = (dir==1?i1_:i3_),
|
||||
i3 = (dir==1?i3_:i1_),
|
||||
ir0 = i0<<1, ii0 = ir0 + 1, or0 = o0<<1, oi0 = or0 + 1,
|
||||
ir1 = i1<<1, ii1 = ir1 + 1, or1 = o1<<1, oi1 = or1 + 1,
|
||||
ir2 = i2<<1, ii2 = ir2 + 1, or2 = o2<<1, oi2 = or2 + 1,
|
||||
ir3 = i3<<1, ii3 = ir3 + 1, or3 = o3<<1, oi3 = or3 + 1 };
|
||||
static inline void execute(t_fft *_x, t_fft *_y, int step) {
|
||||
float *x = (float*)_x;
|
||||
float *y = (float*)_y;
|
||||
float z00, z01, z10, z11, z20, z21, z30, z31;
|
||||
z20 = x[ir0] - x[ir2]; z21 = x[ii0] - x[ii2];
|
||||
z00 = x[ir0] + x[ir2]; z01 = x[ii0] + x[ii2];
|
||||
z10 = x[ir1] + x[ir3]; z11 = x[ii1] + x[ii3];
|
||||
y[or0] = z00 + z10; y[oi0] = z01 + z11;
|
||||
z30 = x[ir3] - x[ir1]; z31 = x[ii3] - x[ii1];
|
||||
if(step) {
|
||||
int step2 = step + step;
|
||||
FloatTwiddle<N,dir>::twiddle(step,_y+o1,z20 - z31,z21 + z30);
|
||||
FloatTwiddle<N,dir>::twiddle(step2,_y+o2,z00 - z10,z01 - z11);
|
||||
FloatTwiddle<N,dir>::twiddle(step2+step,_y+o3,z20 + z31,z21 - z30);
|
||||
} else {
|
||||
y[or1] = z20 - z31; y[oi1] = z21 + z30;
|
||||
y[or2] = z00 - z10; y[oi2] = z01 - z11;
|
||||
y[or3] = z20 + z31; y[oi3] = z21 - z30;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<int istride, int ostride>
|
||||
class __fft<istride,ostride,8,1> {
|
||||
public:
|
||||
enum { N = istride*8,
|
||||
i0 = 0, o0 = 0,
|
||||
i1 = i0 + istride, o1 = o0 + ostride,
|
||||
i2 = i1 + istride, o2 = o1 + ostride,
|
||||
i3 = i2 + istride, o3 = o2 + ostride,
|
||||
i4 = i3 + istride, o4 = o3 + ostride,
|
||||
i5 = i4 + istride, o5 = o4 + ostride,
|
||||
i6 = i5 + istride, o6 = o5 + ostride,
|
||||
i7 = i6 + istride, o7 = o6 + ostride,
|
||||
ir0 = i0<<1, ii0 = ir0 + 1, or0 = o0<<1, oi0 = or0 + 1,
|
||||
ir1 = i1<<1, ii1 = ir1 + 1, or1 = o1<<1, oi1 = or1 + 1,
|
||||
ir2 = i2<<1, ii2 = ir2 + 1, or2 = o2<<1, oi2 = or2 + 1,
|
||||
ir3 = i3<<1, ii3 = ir3 + 1, or3 = o3<<1, oi3 = or3 + 1,
|
||||
ir4 = i4<<1, ii4 = ir4 + 1, or4 = o4<<1, oi4 = or4 + 1,
|
||||
ir5 = i5<<1, ii5 = ir5 + 1, or5 = o5<<1, oi5 = or5 + 1,
|
||||
ir6 = i6<<1, ii6 = ir6 + 1, or6 = o6<<1, oi6 = or6 + 1,
|
||||
ir7 = i7<<1, ii7 = ir7 + 1, or7 = o7<<1, oi7 = or7 + 1 };
|
||||
static inline void execute(t_fft *_x, t_fft *_y, int step) {
|
||||
float *x = (float*)_x;
|
||||
float *y = (float*)_y;
|
||||
float z00, z01, z10, z11, z20, z21, z30, z31, y10, y11, y30, y31;
|
||||
float yr0, yi0, yr1, yi1, yr2, yi2, yr3, yi3, yr4, yi4, yr5, yi5, yr6, yi6, yr7, yi7;
|
||||
z00 = x[ir1] + x[ir5]; z01 = x[ii1] + x[ii5];
|
||||
z10 = x[ir7] + x[ir3]; z11 = x[ii7] + x[ii3];
|
||||
z20 = x[ir1] - x[ir5]; z21 = x[ii1] - x[ii5];
|
||||
z30 = x[ir7] - x[ir3]; z31 = x[ii7] - x[ii3];
|
||||
y10 = z20 - z31; y11 = z21 + z30;
|
||||
y30 = z20 + z31; y31 = z21 - z30;
|
||||
yr1 = z00 + z10; yi1 = z01 + z11;
|
||||
yr5 = z01 - z11; yi5 = z10 - z00;
|
||||
yr3 = 0.7071067811865475f * (y10 + y11); yi3 = 0.7071067811865475f * (y11 - y10);
|
||||
yr7 = 0.7071067811865475f * (y31 - y30); yi7 = -0.7071067811865475f * (y30 + y31);
|
||||
z20 = x[ir0] - x[ir4]; z21 = x[ii0] - x[ii4];
|
||||
z00 = x[ir0] + x[ir4]; z01 = x[ii0] + x[ii4];
|
||||
z10 = x[ir6] + x[ir2]; z11 = x[ii6] + x[ii2];
|
||||
z30 = x[ir6] - x[ir2]; z31 = x[ii6] - x[ii2];
|
||||
yr0 = z00 + z10; yi0 = z01 + z11;
|
||||
yr4 = z00 - z10; yi4 = z01 - z11;
|
||||
yr2 = z20 - z31; yi2 = z21 + z30;
|
||||
yr6 = z20 + z31; yi6 = z21 - z30;
|
||||
y[or0] = yr0 + yr1; y[oi0] = yi0 + yi1;
|
||||
if(step) {
|
||||
FloatTwiddle<N,1>::twiddle(step,_y+o1,yr2 + yr3, yi2 + yi3);
|
||||
int step2 = step + step;
|
||||
FloatTwiddle<N,1>::twiddle(step2,_y+o2,yr4 + yr5, yi4 + yi5);
|
||||
int step3 = step2 + step;
|
||||
FloatTwiddle<N,1>::twiddle(step3,_y+o3,yr6 + yr7, yi6 + yi7);
|
||||
FloatTwiddle<N,1>::twiddle(step2+step2,_y+o4,yr0 - yr1, yi0 - yi1);
|
||||
FloatTwiddle<N,1>::twiddle(step3+step2,_y+o5,yr2 - yr3, yi2 - yi3);
|
||||
FloatTwiddle<N,1>::twiddle(step3+step3,_y+o6,yr4 - yr5, yi4 - yi5);
|
||||
FloatTwiddle<N,1>::twiddle(step3+step2+step2,_y+o7,yr6 - yr7, yi6 - yi7);
|
||||
} else {
|
||||
y[or1] = yr2 + yr3; y[oi1] = yi2 + yi3;
|
||||
y[or2] = yr4 + yr5; y[oi2] = yi4 + yi5;
|
||||
y[or3] = yr6 + yr7; y[oi3] = yi6 + yi7;
|
||||
y[or4] = yr0 - yr1; y[oi4] = yi0 - yi1;
|
||||
y[or5] = yr2 - yr3; y[oi5] = yi2 - yi3;
|
||||
y[or6] = yr4 - yr5; y[oi6] = yi4 - yi5;
|
||||
y[or7] = yr6 - yr7; y[oi7] = yi6 - yi7;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<int istride, int ostride>
|
||||
class __fft<istride,ostride,8,-1> {
|
||||
public:
|
||||
enum { N = istride*8,
|
||||
i0 = 0, o0 = 0,
|
||||
i1 = i0 + istride, o1 = o0 + ostride,
|
||||
i2 = i1 + istride, o2 = o1 + ostride,
|
||||
i3 = i2 + istride, o3 = o2 + ostride,
|
||||
i4 = i3 + istride, o4 = o3 + ostride,
|
||||
i5 = i4 + istride, o5 = o4 + ostride,
|
||||
i6 = i5 + istride, o6 = o5 + ostride,
|
||||
i7 = i6 + istride, o7 = o6 + ostride,
|
||||
ir0 = i0<<1, ii0 = ir0 + 1, or0 = o0<<1, oi0 = or0 + 1,
|
||||
ir1 = i1<<1, ii1 = ir1 + 1, or1 = o1<<1, oi1 = or1 + 1,
|
||||
ir2 = i2<<1, ii2 = ir2 + 1, or2 = o2<<1, oi2 = or2 + 1,
|
||||
ir3 = i3<<1, ii3 = ir3 + 1, or3 = o3<<1, oi3 = or3 + 1,
|
||||
ir4 = i4<<1, ii4 = ir4 + 1, or4 = o4<<1, oi4 = or4 + 1,
|
||||
ir5 = i5<<1, ii5 = ir5 + 1, or5 = o5<<1, oi5 = or5 + 1,
|
||||
ir6 = i6<<1, ii6 = ir6 + 1, or6 = o6<<1, oi6 = or6 + 1,
|
||||
ir7 = i7<<1, ii7 = ir7 + 1, or7 = o7<<1, oi7 = or7 + 1 };
|
||||
static inline void execute(t_fft *_x, t_fft *_y, int step) {
|
||||
float *x = (float*)_x;
|
||||
float *y = (float*)_y;
|
||||
float z00, z01, z10, z11, z20, z21, z30, z31, y10, y11, y30, y31;
|
||||
float yr0, yi0, yr1, yi1, yr2, yi2, yr3, yi3, yr4, yi4, yr5, yi5, yr6, yi6, yr7, yi7;
|
||||
z00 = x[ir1] + x[ir5]; z01 = x[ii1] + x[ii5];
|
||||
z10 = x[ir3] + x[ir7]; z11 = x[ii3] + x[ii7];
|
||||
z20 = x[ir1] - x[ir5]; z21 = x[ii1] - x[ii5];
|
||||
z30 = x[ir3] - x[ir7]; z31 = x[ii3] - x[ii7];
|
||||
y10 = z20 - z31; y11 = z21 + z30;
|
||||
y30 = z20 + z31; y31 = z21 - z30;
|
||||
yr1 = z00 + z10; yi1 = z01 + z11;
|
||||
yr5 = z11 - z01; yi5 = z00 - z10;
|
||||
yr3 = 0.7071067811865475f * (y10 - y11); yi3 = 0.7071067811865475f * (y10 + y11);
|
||||
yr7 = -0.7071067811865475f * (y30 + y31); yi7 = 0.7071067811865475f * (y30 - y31);
|
||||
z00 = x[ir0] + x[ir4]; z01 = x[ii0] + x[ii4];
|
||||
z10 = x[ir2] + x[ir6]; z11 = x[ii2] + x[ii6];
|
||||
z20 = x[ir0] - x[ir4]; z21 = x[ii0] - x[ii4];
|
||||
z30 = x[ir2] - x[ir6]; z31 = x[ii2] - x[ii6];
|
||||
yr0 = z00 + z10; yi0 = z01 + z11;
|
||||
yr4 = z00 - z10; yi4 = z01 - z11;
|
||||
yr2 = z20 - z31; yi2 = z21 + z30;
|
||||
yr6 = z20 + z31; yi6 = z21 - z30;
|
||||
y[or0] = yr0 + yr1;
|
||||
y[oi0] = yi0 + yi1;
|
||||
if(step) {
|
||||
FloatTwiddle<N,-1>::twiddle(step,_y+o1,yr2 + yr3, yi2 + yi3);
|
||||
int step2 = step + step;
|
||||
FloatTwiddle<N,-1>::twiddle(step2,_y+o2,yr4 + yr5, yi4 + yi5);
|
||||
int step3 = step2 + step;
|
||||
FloatTwiddle<N,-1>::twiddle(step3,_y+o3,yr6 + yr7, yi6 + yi7);
|
||||
FloatTwiddle<N,-1>::twiddle(step2+step2,_y+o4,yr0 - yr1, yi0 - yi1);
|
||||
FloatTwiddle<N,-1>::twiddle(step3+step2,_y+o5,yr2 - yr3, yi2 - yi3);
|
||||
FloatTwiddle<N,-1>::twiddle(step3+step3,_y+o6,yr4 - yr5, yi4 - yi5);
|
||||
FloatTwiddle<N,-1>::twiddle(step3+step2+step2,_y+o7,yr6 - yr7, yi6 - yi7);
|
||||
} else {
|
||||
y[or1] = yr2 + yr3; y[oi1] = yi2 + yi3;
|
||||
y[or2] = yr4 + yr5; y[oi2] = yi4 + yi5;
|
||||
y[or3] = yr6 + yr7; y[oi3] = yi6 + yi7;
|
||||
y[or4] = yr0 - yr1; y[oi4] = yi0 - yi1;
|
||||
y[or5] = yr2 - yr3; y[oi5] = yi2 - yi3;
|
||||
y[or6] = yr4 - yr5; y[oi6] = yi4 - yi5;
|
||||
y[or7] = yr6 - yr7; y[oi7] = yi6 - yi7;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ENABLE_SSE
|
||||
|
||||
template<int k, int stride, int radix, int dir>
|
||||
class _fft {
|
||||
public:
|
||||
enum { N = radix * stride,
|
||||
_radix = Factor<stride>::value,
|
||||
_stride = stride / _radix };
|
||||
static inline void execute(t_fft *x) {
|
||||
for(int step=0; step<stride; step++) {
|
||||
__fft<stride,stride,radix,dir>::execute(x+step,x+step,step);
|
||||
}
|
||||
_fft<N,_stride,_radix,dir>::loop(x+N);
|
||||
}
|
||||
static inline void loop(t_fft *x) {
|
||||
_fft<k-N,stride,radix,dir>::execute(x-N);
|
||||
_fft<k-N,stride,radix,dir>::loop(x-N);
|
||||
}
|
||||
};
|
||||
|
||||
template<int stride, int radix, int dir>
|
||||
class _fft<0,stride,radix,dir> {
|
||||
public:
|
||||
enum { N = radix * stride,
|
||||
_radix = Factor<stride>::value,
|
||||
_stride = stride / _radix };
|
||||
static inline void execute(t_fft *x) {
|
||||
for(int step=0; step<stride; step++) {
|
||||
__fft<stride,stride,radix,dir>::execute(x+step,x+step,step);
|
||||
}
|
||||
_fft<N,_stride,_radix,dir>::loop(x+N);
|
||||
}
|
||||
static inline void loop(t_fft *x) { }
|
||||
};
|
||||
|
||||
template <int k, int radix, int dir>
|
||||
class _fft<k,1,radix,dir> {
|
||||
public:
|
||||
static inline void execute(t_fft *x) { }
|
||||
static inline void loop(t_fft *x) { }
|
||||
};
|
||||
|
||||
template <int radix, int dir>
|
||||
class _fft<0,1,radix,dir> {
|
||||
public:
|
||||
static inline void execute(t_fft *x) { }
|
||||
static inline void loop(t_fft *x) { }
|
||||
};
|
||||
|
||||
template<int N>
|
||||
class fft_order_ {
|
||||
public:
|
||||
static inline int iterate(int k) {
|
||||
static const int N2 = Factor<N>::value;
|
||||
static const int N1 = N/Factor<N>::value;
|
||||
return (k%N2)*N1 + fft_order_<N1>::iterate(k/N2);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class fft_order_<1> {
|
||||
public:
|
||||
static inline int iterate(int k0) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<int N>
|
||||
class fft_order {
|
||||
public:
|
||||
fft_order<N>() {
|
||||
for(int k=0;k<N;k++) {
|
||||
int kr = fft_order_<N>::iterate(k);
|
||||
order[kr] = k;
|
||||
}
|
||||
}
|
||||
int order[N];
|
||||
};
|
||||
|
||||
template<int N, int dir>
|
||||
class fft_reorder {
|
||||
public:
|
||||
enum { radix = LastFactor<N>::value,
|
||||
ostride = N / radix,
|
||||
s = N * sizeof(t_fft) };
|
||||
static const fft_order<N> order;
|
||||
static inline void reorder(t_fft *x) {
|
||||
t_fft y[N];
|
||||
int *o = (int*)order.order;
|
||||
memcpy(y,x,s);
|
||||
for(int r=0; r<N; r+=radix) {
|
||||
__fft<1,ostride,radix,dir>::execute(y+r,x+o[r],0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<int N, int dir>
|
||||
const fft_order<N> fft_reorder<N,dir>::order;
|
||||
|
||||
template<int N, int dir>
|
||||
void fft(t_fft *x) {
|
||||
enum { radix = Factor<N>::value,
|
||||
stride = N / radix };
|
||||
_fft<0,stride,radix,dir>::execute(x);
|
||||
fft_reorder<N,dir>::reorder(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -11,136 +11,132 @@ using namespace std;
|
|||
|
||||
namespace _sbsms_ {
|
||||
|
||||
map<int, map<real, real*> > wwMap;
|
||||
map<int, map<real, audio*> > peakMap;
|
||||
|
||||
map<int, fftplan*> fftPlanMap;
|
||||
map<int, fftplan*> ifftPlanMap;
|
||||
|
||||
grain* grain :: create(int N,real pad)
|
||||
GrainAllocator :: GrainAllocator(int N, int N2, int type)
|
||||
{
|
||||
grain *g = new grain(N,pad);
|
||||
this->N = N;
|
||||
this->N2 = N2;
|
||||
this->type = type;
|
||||
|
||||
switch(N) {
|
||||
case 128:
|
||||
fftPlan = &fft128;
|
||||
ifftPlan = &ifft128;
|
||||
break;
|
||||
case 256:
|
||||
fftPlan = &fft256;
|
||||
ifftPlan = &ifft256;
|
||||
break;
|
||||
case 384:
|
||||
fftPlan = &fft384;
|
||||
//ifftPlan = &ifft384;
|
||||
break;
|
||||
case 512:
|
||||
fftPlan = &fft512;
|
||||
//ifftPlan = &ifft512;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
|
||||
int k1 = (N-N2)/2;
|
||||
|
||||
w = (float*)calloc(N,sizeof(float));
|
||||
for(int k=0;k<N2;k++) {
|
||||
if(type == hann) {
|
||||
w[k+k1] = 0.5f*(1.0f - cos((float)k/(float)N2*TWOPI));
|
||||
} else if(type == hannpoisson) {
|
||||
w[k+k1] = 0.5f*(1.0f - cos((float)k/(float)N2*TWOPI)) * exp(-2.0f*fabs((float)(k-N2/2))/(float)N2);
|
||||
}
|
||||
}
|
||||
|
||||
W = (audio*) calloc(N,sizeof(audio));
|
||||
for(int k=0;k<N;k++) {
|
||||
W[k][0] = w[k] * 2.638502561913447f/(float)N2;
|
||||
}
|
||||
|
||||
fftPlan(W);
|
||||
}
|
||||
|
||||
GrainAllocator :: ~GrainAllocator()
|
||||
{
|
||||
free(w);
|
||||
free(W);
|
||||
}
|
||||
|
||||
grain* GrainAllocator :: create()
|
||||
{
|
||||
grain *g = new grain(N,N2);
|
||||
g->refCount = 0;
|
||||
g->fftPlan = fftPlan;
|
||||
g->ifftPlan = ifftPlan;
|
||||
g->w = w;
|
||||
return g;
|
||||
}
|
||||
|
||||
void grain :: referenced(grain *g)
|
||||
void GrainAllocator :: reference(grain *g)
|
||||
{
|
||||
g->refCount++;
|
||||
}
|
||||
|
||||
void grain :: forget(grain *g)
|
||||
void GrainAllocator :: forget(grain *g)
|
||||
{
|
||||
g->refCount--;
|
||||
if(g->refCount <= 0) {
|
||||
destroy(g);
|
||||
delete g;
|
||||
}
|
||||
}
|
||||
|
||||
void grain :: destroy(grain *g)
|
||||
grain :: grain(int N, int N2)
|
||||
{
|
||||
free_audio_buf(g->x);
|
||||
delete g;
|
||||
}
|
||||
|
||||
grain :: grain(int N, real pad)
|
||||
{
|
||||
this->N = N;
|
||||
this->pad = pad;
|
||||
calc_plans();
|
||||
calc_windows();
|
||||
refCount = 0;
|
||||
x = (audio*) malloc(N*sizeof(audio));
|
||||
this->synthScale = 1.0f / (float)N2;
|
||||
x = (audio*) calloc(N,sizeof(audio));
|
||||
}
|
||||
|
||||
void grain :: analyze()
|
||||
grain :: ~grain()
|
||||
{
|
||||
for(int k=0;k<N;k++) {
|
||||
for(int c=0;c<2;c++) {
|
||||
x[k][c] *= ww[k];
|
||||
}
|
||||
free(x);
|
||||
}
|
||||
|
||||
void grain :: analyze()
|
||||
{
|
||||
float *x = (float*)this->x;
|
||||
float *end = x + (N<<1);
|
||||
float *w = this->w;
|
||||
while(x != end) {
|
||||
*(x++) *= *w;
|
||||
*(x++) *= *(w++);
|
||||
}
|
||||
FFT(fftPlan,x);
|
||||
|
||||
fftPlan(this->x);
|
||||
}
|
||||
|
||||
void grain :: synthesize()
|
||||
{
|
||||
IFFT(ifftPlan,x);
|
||||
real f = pad/(real)N;
|
||||
ifftPlan(x);
|
||||
for(int k=0;k<N;k++) {
|
||||
for(int c=0;c<2;c++) {
|
||||
x[k][c] *= ww[k] * f;
|
||||
x[k][c] *= w[k] * synthScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void grain :: calc_plans()
|
||||
void grain :: downsample(grain *g2)
|
||||
{
|
||||
fftPlan = fftPlanMap[N];
|
||||
if(fftPlan == NULL) {
|
||||
fftPlanMap[N] = (fftPlan = planFFT(N));
|
||||
}
|
||||
|
||||
ifftPlan = ifftPlanMap[N];
|
||||
if(ifftPlan == NULL) {
|
||||
ifftPlanMap[N] = (ifftPlan = planIFFT(N));
|
||||
}
|
||||
}
|
||||
|
||||
void grain :: calc_windows()
|
||||
{
|
||||
int N2 = round2int(N/pad);
|
||||
ww = wwMap[N][pad];
|
||||
if(ww == NULL) {
|
||||
wwMap[N][pad] = (ww = (real*)calloc(N,sizeof(real)));
|
||||
for(int k=0;k<N2;k++) {
|
||||
ww[k+(N-N2)/2] = 0.5f*(1.0f - cos((real)k/(real)N2*TWOPI));
|
||||
}
|
||||
}
|
||||
|
||||
peak = peakMap[N][pad];
|
||||
if(peak == NULL) {
|
||||
peakMap[N][pad] = (peak = (audio*) calloc(N,sizeof(audio)));
|
||||
for(int k=0;k<N;k++) {
|
||||
peak[k][0] = ww[k]/(real)(N2/2);
|
||||
}
|
||||
FFT(fftPlan,peak);
|
||||
}
|
||||
}
|
||||
|
||||
grain* grain :: upsample()
|
||||
{
|
||||
grain *g2 = grain::create(2*N,pad);
|
||||
grain *g = this;
|
||||
|
||||
int N2 = N/2;
|
||||
int N4 = N/4;
|
||||
for(int c=0;c<2;c++) {
|
||||
for(int k=0;k<=N/2;k++)
|
||||
g2->x[k][c] = g->x[k][c];
|
||||
|
||||
for(int k=N/2+1;k<=N/2+N;k++)
|
||||
g2->x[k][c] = 0;
|
||||
|
||||
for(int k=N/2+N+1;k<2*N;k++)
|
||||
g2->x[k][c] = g->x[k-N][c];
|
||||
for(int k=0;k<N4;k++) {
|
||||
g2->x[k][c] = 0.5f * g->x[k][c];
|
||||
}
|
||||
g2->x[N4][c] = 0.25f * (g->x[N4][c] + g->x[N-N4][c]);
|
||||
for(int k=N4+1;k<N2;k++) {
|
||||
g2->x[k][c] = 0.5f * g->x[k+N2][c];
|
||||
}
|
||||
}
|
||||
return g2;
|
||||
}
|
||||
|
||||
grain* grain :: downsample()
|
||||
{
|
||||
grain *g2 = grain::create(N/2,pad);
|
||||
grain *g = this;
|
||||
|
||||
for(int c=0;c<2;c++) {
|
||||
for(int k=0;k<=N/4-1;k++)
|
||||
g2->x[k][c] = g->x[k][c];
|
||||
|
||||
g2->x[N/4][c] = 0.5f*(g->x[N/4][c] + g->x[N-N/4][c] );
|
||||
|
||||
for(int k=N/4+1;k<N/2;k++)
|
||||
g2->x[k][c] = g->x[k+N/2][c];
|
||||
}
|
||||
|
||||
return g2;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,37 +1,54 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef GRAIN_H
|
||||
#define GRAIN_H
|
||||
|
||||
#include "fft.h"
|
||||
#include "audio.h"
|
||||
#include "sbsms.h"
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
enum windowType {
|
||||
hann,
|
||||
hannpoisson
|
||||
};
|
||||
|
||||
class GrainAllocator;
|
||||
|
||||
class grain {
|
||||
public:
|
||||
static grain* create(int N, real pad);
|
||||
static void destroy(grain *g);
|
||||
static void referenced(grain *g);
|
||||
static void forget(grain *g);
|
||||
|
||||
t_fft *x;
|
||||
int N;
|
||||
int h;
|
||||
real pad;
|
||||
int refCount;
|
||||
audio *peak;
|
||||
|
||||
~grain();
|
||||
void analyze();
|
||||
void synthesize();
|
||||
grain* upsample();
|
||||
grain* downsample();
|
||||
|
||||
void downsample(grain *gdown);
|
||||
audio *x;
|
||||
friend class GrainAllocator;
|
||||
protected:
|
||||
grain(int N,real pad);
|
||||
void calc_plans();
|
||||
void calc_windows();
|
||||
real *ww;
|
||||
fftplan *fftPlan, *ifftPlan;
|
||||
grain(int N, int N2);
|
||||
float *w;
|
||||
int N;
|
||||
float synthScale;
|
||||
int refCount;
|
||||
fftplan fftPlan;
|
||||
fftplan ifftPlan;
|
||||
};
|
||||
|
||||
class GrainAllocator {
|
||||
public:
|
||||
GrainAllocator(int N, int N2, int type);
|
||||
~GrainAllocator();
|
||||
grain *create();
|
||||
void reference(grain *g);
|
||||
void forget(grain *g);
|
||||
friend class grain;
|
||||
friend class GrainBuf;
|
||||
protected:
|
||||
int N;
|
||||
int N2;
|
||||
int type;
|
||||
float *w;
|
||||
audio *W;
|
||||
fftplan fftPlan;
|
||||
fftplan ifftPlan;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
#include "peak.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
PeakAllocator :: PeakAllocator()
|
||||
{
|
||||
size = 0;
|
||||
count = 0;
|
||||
peaks = NULL;
|
||||
}
|
||||
|
||||
PeakAllocator :: ~PeakAllocator()
|
||||
{
|
||||
if(peaks) free(peaks);
|
||||
}
|
||||
|
||||
peak *PeakAllocator :: create()
|
||||
{
|
||||
if(count >= size) {
|
||||
if(size == 0)
|
||||
size = 1024;
|
||||
else
|
||||
size *= 2;
|
||||
|
||||
peak *newpeaks = (peak*)malloc(size*sizeof(peak));
|
||||
if(peaks) {
|
||||
memcpy(newpeaks,peaks,count*sizeof(peak));
|
||||
free(peaks);
|
||||
}
|
||||
peaks = newpeaks;
|
||||
}
|
||||
return peaks+(count++);
|
||||
}
|
||||
|
||||
void PeakAllocator :: destroy(peak *p)
|
||||
{
|
||||
count--;
|
||||
}
|
||||
|
||||
void PeakAllocator :: destroyAll()
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef PEAK_H
|
||||
#define PEAK_H
|
||||
|
||||
/*
|
||||
Semantics are such that if destroy(p) or destroyAll() is called then all peaks create()'d after p are invalid. It is OK to create() a peak, destroy it before calling create() again, then create() another, or to create() a set of peaks, then destroy them ALL in any order, and repeat.
|
||||
*/
|
||||
|
||||
#include "sbsms.h"
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
class peak {
|
||||
public:
|
||||
peak *tp;
|
||||
peak *tn;
|
||||
peak *tp2;
|
||||
peak *tn2;
|
||||
real x;
|
||||
real y;
|
||||
real y2;
|
||||
int k;
|
||||
real m;
|
||||
};
|
||||
|
||||
class PeakAllocator {
|
||||
public:
|
||||
PeakAllocator();
|
||||
~PeakAllocator();
|
||||
peak *create();
|
||||
void destroy(peak *p);
|
||||
void destroyAll();
|
||||
|
||||
protected:
|
||||
long count;
|
||||
long size;
|
||||
peak *peaks;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,3 +1,4 @@
|
|||
// -*- mode: c++ -*-
|
||||
/*
|
||||
** Copyright (C) 2001-2003 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
|
@ -203,10 +204,4 @@
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef SBSMS_REAL_FLOAT
|
||||
#define round2int(x) lrintf(x)
|
||||
#else
|
||||
#define round2int(x) lrint(x)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,225 +6,244 @@
|
|||
#include "real.h"
|
||||
#include "utils.h"
|
||||
#include <algorithm>
|
||||
#include "buffer.h"
|
||||
using namespace std;
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
#define SBSMS_RESAMPLE_CHUNK_SIZE 8192L
|
||||
enum { resampleChunkSize = 8192 };
|
||||
|
||||
class ResamplerImp {
|
||||
public:
|
||||
ResamplerImp(SBSMSResampleCB func, void *data, SlideType slideType = SlideConstant);
|
||||
~ResamplerImp();
|
||||
inline long read(audio *audioOut, long frames);
|
||||
inline void writingComplete();
|
||||
inline void reset();
|
||||
inline void init();
|
||||
inline long samplesInOutput();
|
||||
protected:
|
||||
SBSMSFrame frame;
|
||||
SampleCountType startAbs;
|
||||
SampleCountType midAbs;
|
||||
float midAbsf;
|
||||
SampleCountType endAbs;
|
||||
SampleCountType writePosAbs;
|
||||
bool bInput;
|
||||
SampleBuf *out;
|
||||
SBSMSResampleCB cb;
|
||||
void *data;
|
||||
long inOffset;
|
||||
SlideType slideType;
|
||||
Slide *slide;
|
||||
bool bWritingComplete;
|
||||
};
|
||||
|
||||
Resampler :: Resampler(sbsms_resample_cb cb, void *data)
|
||||
Resampler :: Resampler(SBSMSResampleCB cb, void *data, SlideType slideType)
|
||||
{
|
||||
imp = new ResamplerImp(cb,data,slideType);
|
||||
}
|
||||
|
||||
ResamplerImp :: ResamplerImp(SBSMSResampleCB cb, void *data, SlideType slideType)
|
||||
{
|
||||
init();
|
||||
this->cb = cb;
|
||||
this->data = data;
|
||||
bPull = true;
|
||||
bInput = true;
|
||||
this->slideType = slideType;
|
||||
frame.size = 0;
|
||||
}
|
||||
|
||||
Resampler :: Resampler(SampleBuf *in, real ratio)
|
||||
{
|
||||
init();
|
||||
bPull = false;
|
||||
this->in = in;
|
||||
bInput = true;
|
||||
frame.ratio0 = ratio;
|
||||
frame.ratio1 = ratio;
|
||||
}
|
||||
|
||||
void Resampler :: init()
|
||||
void ResamplerImp :: init()
|
||||
{
|
||||
inOffset = 0;
|
||||
startAbs = 0;
|
||||
midAbs = 0;
|
||||
endAbs = 0;
|
||||
writePosAbs = 0;
|
||||
midAbsf = 0.0;
|
||||
midAbsf = 0.0f;
|
||||
out = new SampleBuf(0);
|
||||
slide = NULL;
|
||||
bWritingComplete = false;
|
||||
sincZeros = SBSMS_SINC_SAMPLES;
|
||||
}
|
||||
|
||||
void Resampler :: reset()
|
||||
void Resampler :: reset() { imp->reset(); }
|
||||
void ResamplerImp :: reset()
|
||||
{
|
||||
if(slide) delete slide;
|
||||
delete out;
|
||||
init();
|
||||
frame.size = 0;
|
||||
bInput = true;
|
||||
}
|
||||
|
||||
long Resampler :: read(audio *audioOut, long samples)
|
||||
Resampler :: ~Resampler() { delete imp; }
|
||||
ResamplerImp :: ~ResamplerImp()
|
||||
{
|
||||
if(!bPull) {
|
||||
frame.in = in->getReadBuf();
|
||||
frame.size = in->n_readable();
|
||||
if(frame.size) bInput = true;
|
||||
}
|
||||
if(slide) delete slide;
|
||||
delete out;
|
||||
}
|
||||
|
||||
long nRead = out->n_readable();
|
||||
void updateSlide(Slide *slide, float *f, float *scale, int *maxDist, float *ratio)
|
||||
{
|
||||
float stretch = slide->getStretch();
|
||||
slide->step();
|
||||
if(stretch <= 1.0f) {
|
||||
*f = resampleSincRes;
|
||||
*scale = stretch;
|
||||
*maxDist = lrintf(resampleSincSamples);
|
||||
} else {
|
||||
*f = resampleSincRes / stretch;
|
||||
*scale = 1.0f;
|
||||
*maxDist = lrintf(resampleSincSamples * stretch);
|
||||
}
|
||||
*ratio = stretch;
|
||||
}
|
||||
|
||||
long Resampler :: read(audio *audioOut, long samples) { return imp->read(audioOut,samples); }
|
||||
long ResamplerImp :: read(audio *audioOut, long samples)
|
||||
{
|
||||
long nRead = out->nReadable();
|
||||
while(nRead < samples && bInput) {
|
||||
if(bInput && inOffset == frame.size) {
|
||||
if(!bPull) {
|
||||
in->advance(frame.size);
|
||||
bInput = false;
|
||||
cb(data,&frame);
|
||||
if(frame.size) {
|
||||
if(slide) delete slide;
|
||||
slide = new Slide(slideType,1.0f/frame.ratio0,1.0f/frame.ratio1,frame.size);
|
||||
} else {
|
||||
cb(data,&frame);
|
||||
if(!frame.size)
|
||||
bWritingComplete = true;
|
||||
bWritingComplete = true;
|
||||
}
|
||||
if(bWritingComplete) {
|
||||
bInput = false;
|
||||
out->grow(midAbs - writePosAbs);
|
||||
out->writePos += midAbs - writePosAbs;
|
||||
out->delay = 0;
|
||||
bInput = false;
|
||||
long n = (long)(midAbs - writePosAbs);
|
||||
out->grow(n);
|
||||
out->writePos += n;
|
||||
}
|
||||
inOffset = 0;
|
||||
}
|
||||
if(frame.size) {
|
||||
real dratio = 1.0f/(real)frame.size*(frame.ratio1-frame.ratio0);
|
||||
|
||||
real ratio = frame.ratio0 + (real)inOffset*dratio;
|
||||
real ratiorec = ratio<1.0f?1.0f:1.0f/ratio;
|
||||
real f = ratiorec*SBSMS_SINC_RES;
|
||||
int fi = round2int(f-0.5f);
|
||||
real ff = f - fi;
|
||||
if(ff<0.0f) {
|
||||
ff += 1.0f;
|
||||
fi--;
|
||||
}
|
||||
real scale = ratio<1.0f?ratio:1.0f;
|
||||
int maxDist = round2int(sincZeros*ratio-0.5f);
|
||||
// absolute start position
|
||||
startAbs = max((long)0,midAbs-maxDist);
|
||||
// samples to advance
|
||||
long advance = max((long)0,startAbs - maxDist - writePosAbs);
|
||||
writePosAbs += advance;
|
||||
// absolute end position
|
||||
endAbs = midAbs + maxDist;
|
||||
// starting position in output
|
||||
int start = startAbs - writePosAbs;
|
||||
assert(start>=0);
|
||||
// zero point in output
|
||||
int mid = midAbs - writePosAbs;
|
||||
// ending position in output
|
||||
int end = endAbs - writePosAbs;
|
||||
// provide extra delay for variable rate ratio
|
||||
out->delay = maxDist<<1;
|
||||
out->writePos += advance;
|
||||
|
||||
if(fabs(ratio-1.0f) < 1e-6f && fabs(dratio) < 1e-8f ) {
|
||||
// how far ahead to write
|
||||
int nAhead = mid+frame.size;
|
||||
out->N = nAhead;
|
||||
out->grow(nAhead);
|
||||
long nWrite = min(SBSMS_RESAMPLE_CHUNK_SIZE,frame.size-inOffset);
|
||||
for(int j=0;j<nWrite;j++) {
|
||||
out->buf[out->writePos+mid+j][0] += frame.in[j+inOffset][0];
|
||||
out->buf[out->writePos+mid+j][1] += frame.in[j+inOffset][1];
|
||||
}
|
||||
inOffset += nWrite;
|
||||
midAbsf += ratio*nWrite;
|
||||
int nWritten = round2int(midAbsf);
|
||||
midAbsf -= nWritten;
|
||||
midAbs += nWritten;
|
||||
if(slideType == SlideIdentity) {
|
||||
out->write(frame.buf,frame.size);
|
||||
inOffset = frame.size;
|
||||
} else {
|
||||
long nWrite = min(SBSMS_RESAMPLE_CHUNK_SIZE,frame.size-inOffset);
|
||||
audio *i = &(frame.in[inOffset]);
|
||||
for(int j=0;j<nWrite;j++) {
|
||||
// how far ahead to write
|
||||
int nAhead = end;
|
||||
out->N = nAhead;
|
||||
out->grow(nAhead);
|
||||
audio *o = &(out->buf[out->writePos+start]);
|
||||
real d = (start-mid-midAbsf)*f;
|
||||
int di = round2int(d-0.5f);
|
||||
real df = d-di;
|
||||
if(df<0.0f) {
|
||||
df += 1.0f;
|
||||
di--;
|
||||
}
|
||||
real i0 = (*i)[0];
|
||||
real i1 = (*i)[1];
|
||||
for(int k=start;k<end;k++) {
|
||||
int k0 = (di<0)?-di:di;
|
||||
int k1 = (di<0)?k0-1:k0+1;
|
||||
real sinc;
|
||||
if(k1>=SBSMS_SINC_SIZE) {
|
||||
if(k0>=SBSMS_SINC_SIZE) {
|
||||
sinc = 0.0f;
|
||||
} else {
|
||||
sinc = scale*sincTable[k0];
|
||||
}
|
||||
} else if(k0>=SBSMS_SINC_SIZE) {
|
||||
sinc = scale*sincTable[k1];
|
||||
} else {
|
||||
sinc = scale*((1.0f-df)*sincTable[k0] + df*sincTable[k1]);
|
||||
}
|
||||
(*o)[0] += i0 * sinc;
|
||||
(*o)[1] += i1 * sinc;
|
||||
di += fi;
|
||||
df += ff;
|
||||
if(!(df<1.0f)) {
|
||||
df -= 1.0f;
|
||||
di++;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
i++;
|
||||
midAbsf += ratio;
|
||||
|
||||
if(dratio != 0.0f) {
|
||||
ratio += dratio;
|
||||
ratiorec = ratio<1.0f?1.0f:1.0f/ratio;
|
||||
f = ratiorec*SBSMS_SINC_RES;
|
||||
fi = round2int(f-0.5f);
|
||||
ff = f - fi;
|
||||
if(ff<0.0f) {
|
||||
ff += 1.0f;
|
||||
fi--;
|
||||
}
|
||||
scale = ratio<1.0f?ratio:1.0f;
|
||||
maxDist = round2int(sincZeros*ratio-0.5f);
|
||||
}
|
||||
|
||||
int nWritten = round2int(midAbsf);
|
||||
midAbsf -= nWritten;
|
||||
midAbs += nWritten;
|
||||
startAbs = max((long)0,midAbs-maxDist);
|
||||
endAbs = midAbs + maxDist;
|
||||
start = startAbs - writePosAbs;
|
||||
mid = midAbs - writePosAbs;
|
||||
end = endAbs - writePosAbs;
|
||||
}
|
||||
inOffset += nWrite;
|
||||
bool bNoSinc = false;
|
||||
if(fabs(frame.ratio0-1.0f) < 1e-6f &&
|
||||
fabs((float)(frame.ratio1 - frame.ratio0)/(float)frame.size) < 1e-9f) {
|
||||
bNoSinc = true;
|
||||
}
|
||||
float f;
|
||||
float scale;
|
||||
int maxDist;
|
||||
float ratio;
|
||||
updateSlide(slide,&f,&scale,&maxDist,&ratio);
|
||||
int fi = lrintf(f);
|
||||
float ff = f - fi;
|
||||
if(ff<0.0f) {
|
||||
ff += 1.0f;
|
||||
fi--;
|
||||
}
|
||||
startAbs = max((SampleCountType)0,midAbs-maxDist);
|
||||
long advance = max(0L,(long)(startAbs - maxDist - writePosAbs));
|
||||
writePosAbs += advance;
|
||||
endAbs = midAbs + maxDist;
|
||||
long start = (long)(startAbs - writePosAbs);
|
||||
long mid = (long)(midAbs - writePosAbs);
|
||||
long end = (long)(endAbs - writePosAbs);
|
||||
out->writePos += advance;
|
||||
if(bNoSinc) {
|
||||
int nAhead = mid+frame.size;
|
||||
out->N = nAhead;
|
||||
out->grow(nAhead);
|
||||
long nWrite = min((long)resampleChunkSize,frame.size-inOffset);
|
||||
for(int j=0;j<nWrite;j++) {
|
||||
out->buf[out->writePos+mid+j][0] += frame.buf[j+inOffset][0];
|
||||
out->buf[out->writePos+mid+j][1] += frame.buf[j+inOffset][1];
|
||||
}
|
||||
inOffset += nWrite;
|
||||
midAbsf += nWrite;
|
||||
int nWritten = lrintf(midAbsf);
|
||||
midAbsf -= nWritten;
|
||||
midAbs += nWritten;
|
||||
} else {
|
||||
long nWrite = min((long)resampleChunkSize,frame.size-inOffset);
|
||||
audio *i = &(frame.buf[inOffset]);
|
||||
for(int j=0;j<nWrite;j++) {
|
||||
int nAhead = end;
|
||||
out->N = nAhead;
|
||||
out->grow(nAhead);
|
||||
audio *o = &(out->buf[out->writePos+start]);
|
||||
float d = (start-mid-midAbsf)*f;
|
||||
int di = lrintf(d);
|
||||
float df = d-di;
|
||||
if(df<0.0f) {
|
||||
df += 1.0f;
|
||||
di--;
|
||||
}
|
||||
float i0 = (*i)[0];
|
||||
float i1 = (*i)[1];
|
||||
for(int k=start;k<end;k++) {
|
||||
int k0 = (di<0)?-di:di;
|
||||
int k1 = (di<0)?k0-1:k0+1;
|
||||
float sinc;
|
||||
if(k1>=resampleSincSize) {
|
||||
if(k0>=resampleSincSize) {
|
||||
sinc = 0.0f;
|
||||
} else {
|
||||
sinc = scale*sincTable[k0];
|
||||
}
|
||||
} else if(k0>=resampleSincSize) {
|
||||
sinc = scale*sincTable[k1];
|
||||
} else {
|
||||
sinc = scale*((1.0f-df)*sincTable[k0] + df*sincTable[k1]);
|
||||
}
|
||||
(*o)[0] += i0 * sinc;
|
||||
(*o)[1] += i1 * sinc;
|
||||
di += fi;
|
||||
df += ff;
|
||||
if(!(df<1.0f)) {
|
||||
df -= 1.0f;
|
||||
di++;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
i++;
|
||||
updateSlide(slide,&f,&scale,&maxDist,&ratio);
|
||||
fi = lrintf(f);
|
||||
ff = f - fi;
|
||||
if(ff<0.0f) {
|
||||
ff += 1.0f;
|
||||
fi--;
|
||||
}
|
||||
midAbsf += ratio;
|
||||
int nWritten = lrintf(midAbsf);
|
||||
midAbsf -= nWritten;
|
||||
midAbs += nWritten;
|
||||
startAbs = max((SampleCountType)0,midAbs-maxDist);
|
||||
endAbs = midAbs + maxDist;
|
||||
start = (long)(startAbs - writePosAbs);
|
||||
mid = (long)(midAbs - writePosAbs);
|
||||
end = (long)(endAbs - writePosAbs);
|
||||
}
|
||||
inOffset += nWrite;
|
||||
}
|
||||
}
|
||||
nRead = out->nReadable();
|
||||
}
|
||||
nRead = out->n_readable();
|
||||
}
|
||||
|
||||
nRead = min(samples,out->n_readable());
|
||||
if(nRead) {
|
||||
out->read(audioOut,nRead);
|
||||
out->advance(nRead);
|
||||
}
|
||||
|
||||
return nRead;
|
||||
out->read(audioOut,samples);
|
||||
return samples;
|
||||
}
|
||||
|
||||
long Resampler :: samplesInOutput()
|
||||
long Resampler :: samplesInOutput() { return imp->samplesInOutput(); }
|
||||
long ResamplerImp :: samplesInOutput()
|
||||
{
|
||||
long samplesFromBuffer = round2int(0.5f*(frame.ratio0+frame.ratio1)*(frame.size-inOffset));
|
||||
return out->writePos + midAbs - writePosAbs - out->readPos + samplesFromBuffer;
|
||||
long samplesFromBuffer = lrintf(0.5f*(frame.ratio0+frame.ratio1)*(frame.size-inOffset));
|
||||
return (long)(out->writePos + (midAbs - writePosAbs) - out->readPos + samplesFromBuffer);
|
||||
}
|
||||
|
||||
void Resampler :: writingComplete()
|
||||
void ResamplerImp :: writingComplete()
|
||||
{
|
||||
bWritingComplete = true;
|
||||
}
|
||||
|
||||
Resampler :: ~Resampler()
|
||||
{
|
||||
delete out;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,18 +1,14 @@
|
|||
#ifndef SBSMS_SINCCOEFFS_H
|
||||
#define SBSMS_SINCCOEFFS_H
|
||||
// -*- mode: c++ -*-
|
||||
#ifndef SINCCOEFFS_H
|
||||
#define SINCCOEFFS_H
|
||||
|
||||
#include "sbsms.h"
|
||||
#define SBSMS_SINC_SIZE 5286
|
||||
#ifdef SBSMS_REAL_FLOAT
|
||||
#define SBSMS_SINC_RES 128.0f
|
||||
#define SBSMS_SINC_SAMPLES 41.0f
|
||||
#else
|
||||
#define SBSMS_SINC_RES 128.0
|
||||
#define SBSMS_SINC_SAMPLES 41.0
|
||||
#endif
|
||||
enum {
|
||||
resampleSincSize = 5286,
|
||||
resampleSincRes = 128,
|
||||
resampleSincSamples = 41 };
|
||||
|
||||
namespace _sbsms_ {
|
||||
real sincTable[SBSMS_SINC_SIZE] =
|
||||
float sincTable[resampleSincSize] =
|
||||
{
|
||||
0.920381425342433f,
|
||||
0.920302993473145f,
|
||||
|
|
|
@ -0,0 +1,476 @@
|
|||
#include "sbsms.h"
|
||||
#include "real.h"
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
class SlideImp {
|
||||
public:
|
||||
virtual ~SlideImp() {}
|
||||
virtual float getTotalStretch()=0;
|
||||
virtual float getStretchedTime(float t)=0;
|
||||
virtual float getRate(float t)=0;
|
||||
virtual float getStretch(float t)=0;
|
||||
virtual float getRate()=0;
|
||||
virtual float getStretch()=0;
|
||||
virtual void step()=0;
|
||||
};
|
||||
|
||||
class IdentitySlide : public SlideImp {
|
||||
public:
|
||||
IdentitySlide() {
|
||||
}
|
||||
float getTotalStretch() {
|
||||
return 1.0f;
|
||||
}
|
||||
float getStretchedTime(float t) {
|
||||
return t;
|
||||
}
|
||||
float getRate(float t) {
|
||||
return 1.0f;
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return 1.0f;
|
||||
}
|
||||
float getRate() {
|
||||
return 1.0f;
|
||||
}
|
||||
float getStretch() {
|
||||
return 1.0f;
|
||||
}
|
||||
void step() {
|
||||
}
|
||||
};
|
||||
|
||||
class ConstantSlide : public SlideImp {
|
||||
public:
|
||||
ConstantSlide(float rate) {
|
||||
this->rate = rate;
|
||||
}
|
||||
float getTotalStretch() {
|
||||
return 1.0f / rate;
|
||||
}
|
||||
float getStretchedTime(float t) {
|
||||
return t / rate;
|
||||
}
|
||||
float getRate(float t) {
|
||||
return rate;
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return 1.0f / rate;
|
||||
}
|
||||
float getRate() {
|
||||
return rate;
|
||||
}
|
||||
float getStretch() {
|
||||
return 1.0f / rate;
|
||||
}
|
||||
void step() {
|
||||
}
|
||||
protected:
|
||||
float rate;
|
||||
};
|
||||
|
||||
class LinearInputRateSlide : public SlideImp {
|
||||
public:
|
||||
LinearInputRateSlide(float rate0, float rate1, const SampleCountType &n) {
|
||||
this->rate0 = rate0;
|
||||
this->rate1 = rate1;
|
||||
if(n) {
|
||||
val = rate0;
|
||||
inc = (rate1 - rate0) / (double)n;
|
||||
}
|
||||
}
|
||||
float getTotalStretch() {
|
||||
return log(rate1 / rate0) / (rate1 - rate0);
|
||||
}
|
||||
float getStretchedTime(float t) {
|
||||
float ratet = getRate(t);
|
||||
return log(ratet / rate0) / (rate1 - rate0);
|
||||
}
|
||||
float getRate(float t) {
|
||||
return rate0 + (rate1 - rate0) * t;
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return 1.0f / getRate(t);
|
||||
}
|
||||
float getRate() {
|
||||
return (float)val;
|
||||
}
|
||||
float getStretch() {
|
||||
return (float)(1.0 / val);
|
||||
}
|
||||
void step() {
|
||||
val += inc;
|
||||
}
|
||||
protected:
|
||||
float rate0, rate1;
|
||||
double val, inc;
|
||||
};
|
||||
|
||||
class LinearOutputRateSlide : public SlideImp {
|
||||
public:
|
||||
LinearOutputRateSlide(float rate0, float rate1, const SampleCountType &n) {
|
||||
this->rate0 = rate0;
|
||||
this->rate1 = rate1;
|
||||
if(n) {
|
||||
val = 0.0;
|
||||
inc = 1.0 / (double)n;
|
||||
}
|
||||
}
|
||||
float getTotalStretch() {
|
||||
return 2.0f / (rate0 + rate1);
|
||||
}
|
||||
float getStretchedTime(float t) {
|
||||
return (sqrt(rate0 * rate0 + (rate1 * rate1 - rate0 * rate0) * t) - rate0) * 2.0f / (rate1 * rate1 - rate0 * rate0);
|
||||
}
|
||||
float getRate(float t) {
|
||||
return rate0 + (sqrt(rate0 * rate0 + (rate1 * rate1 - rate0 * rate0) * t) - rate0);
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return 1.0f / getRate(t);
|
||||
}
|
||||
float getRate() {
|
||||
return getRate((float)val);
|
||||
}
|
||||
float getStretch() {
|
||||
return getStretch((float)val);
|
||||
}
|
||||
void step() {
|
||||
val += inc;
|
||||
}
|
||||
protected:
|
||||
float rate0, rate1;
|
||||
double val, inc;
|
||||
};
|
||||
|
||||
class LinearInputStretchSlide : public SlideImp {
|
||||
public:
|
||||
LinearInputStretchSlide(float rate0, float rate1, const SampleCountType &n) {
|
||||
this->rate0 = rate0;
|
||||
this->rate1 = rate1;
|
||||
if(n) {
|
||||
val = 1.0 / rate0;
|
||||
inc = (1.0 / rate1 - 1.0 / rate0) / (double)n;
|
||||
}
|
||||
}
|
||||
float getTotalStretch() {
|
||||
return 0.5f / rate0 + 0.5f / rate1;
|
||||
}
|
||||
float getStretchedTime(float t) {
|
||||
return t / rate0 * (1.0f + 0.5f * t * (rate0 / rate1 - 1.0f));
|
||||
}
|
||||
float getRate(float t) {
|
||||
return 1.0f / getStretch(t);
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return (1.0f / rate0 + (1.0f / rate1 - 1.0f / rate0) * t);
|
||||
}
|
||||
float getRate() {
|
||||
return (float)(1.0 / val);
|
||||
}
|
||||
float getStretch() {
|
||||
return (float)val;
|
||||
}
|
||||
void step() {
|
||||
val += inc;
|
||||
}
|
||||
protected:
|
||||
float rate0, rate1;
|
||||
double val, inc;
|
||||
};
|
||||
|
||||
class LinearOutputStretchSlide : public SlideImp {
|
||||
public:
|
||||
LinearOutputStretchSlide(float rate0, float rate1, const SampleCountType &n) {
|
||||
this->rate0 = rate0;
|
||||
this->rate1 = rate1;
|
||||
c0 = rate0 / rate1;
|
||||
c1 = 1.0f / (rate0 * log(c0));
|
||||
if(n) {
|
||||
val = 0.0;
|
||||
inc = 1.0 / (double)n;
|
||||
}
|
||||
}
|
||||
float getTotalStretch() {
|
||||
return c1 * (c0 - 1.0f);
|
||||
}
|
||||
float getStretchedTime(float t) {
|
||||
return c1 * (pow(c0, t) - 1.0f);
|
||||
}
|
||||
float getRate(float t) {
|
||||
return rate0 * pow(c0, -t);
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return pow(c0, t) / rate0;
|
||||
}
|
||||
float getRate() {
|
||||
return getRate((float)val);
|
||||
}
|
||||
float getStretch() {
|
||||
return getStretch((float)val);
|
||||
}
|
||||
void step() {
|
||||
val += inc;
|
||||
}
|
||||
protected:
|
||||
float rate0, rate1;
|
||||
double val, inc;
|
||||
float c0, c1;
|
||||
};
|
||||
|
||||
class GeometricInputSlide : public SlideImp {
|
||||
public:
|
||||
GeometricInputSlide(float rate0, float rate1, const SampleCountType &n) {
|
||||
this->rate0 = rate0;
|
||||
this->rate1 = rate1;
|
||||
if(n) {
|
||||
val = rate0;
|
||||
inc = pow((double)rate1 / rate0, 1.0 / (double)n);
|
||||
}
|
||||
}
|
||||
float getTotalStretch() {
|
||||
return (rate1 - rate0) / (log(rate1 / rate0) * (rate0 * rate1));
|
||||
}
|
||||
float getStretchedTime(float t) {
|
||||
return (float)(pow(rate0 / rate1, t) - 1.0) / (rate0 * log(rate0 / rate1));
|
||||
}
|
||||
float getRate(float t) {
|
||||
return rate0 * pow(rate1 / rate0, t);
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return 1.0f / getRate(t);
|
||||
}
|
||||
float getRate() {
|
||||
return (float)val;
|
||||
}
|
||||
float getStretch() {
|
||||
return (float)(1.0 / val);
|
||||
}
|
||||
void step() {
|
||||
val *= inc;
|
||||
}
|
||||
protected:
|
||||
float rate0, rate1;
|
||||
double val, inc;
|
||||
};
|
||||
|
||||
class GeometricOutputSlide : public SlideImp {
|
||||
public:
|
||||
GeometricOutputSlide(float rate0, float rate1, const SampleCountType &n) {
|
||||
this->rate0 = rate0;
|
||||
this->rate1 = rate1;
|
||||
log10 = log(rate1 / rate0);
|
||||
r10 = rate1 - rate0;
|
||||
totalStretch = getTotalStretch();
|
||||
if(n) {
|
||||
val = 0.0;
|
||||
inc = 1.0 / (double)n;
|
||||
}
|
||||
}
|
||||
float getTotalStretch() {
|
||||
return log(rate1 / rate0) / (rate1 - rate0);
|
||||
}
|
||||
float getStretchedTime(float t) {
|
||||
return log(r10 / rate0 * t + 1.0f) / r10;
|
||||
}
|
||||
float getRate(float t) {
|
||||
float t1 = getStretchedTime(t) / totalStretch;
|
||||
return rate0 * pow(rate1 / rate0, t1);
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return 1.0f / getRate(t);
|
||||
}
|
||||
float getRate() {
|
||||
return getRate((float)val);
|
||||
}
|
||||
float getStretch() {
|
||||
return getStretch((float)val);
|
||||
}
|
||||
void step() {
|
||||
val += inc;
|
||||
}
|
||||
protected:
|
||||
float rate0, rate1;
|
||||
float log10, r10, totalStretch;
|
||||
double val, inc;
|
||||
};
|
||||
|
||||
|
||||
Slide :: Slide(SlideType slideType, float rate0, float rate1, const SampleCountType &n)
|
||||
{
|
||||
if(slideType == SlideIdentity) {
|
||||
imp = new IdentitySlide();
|
||||
} else if(slideType == SlideConstant || rate0 == rate1) {
|
||||
imp = new ConstantSlide(rate0);
|
||||
} else if(slideType == SlideLinearInputRate) {
|
||||
imp = new LinearInputRateSlide(rate0,rate1,n);
|
||||
} else if(slideType == SlideLinearOutputRate) {
|
||||
imp = new LinearOutputRateSlide(rate0,rate1,n);
|
||||
} else if(slideType == SlideLinearInputStretch) {
|
||||
imp = new LinearInputStretchSlide(rate0,rate1,n);
|
||||
} else if(slideType == SlideLinearOutputStretch) {
|
||||
imp = new LinearOutputStretchSlide(rate0,rate1,n);
|
||||
} else if(slideType == SlideGeometricInput) {
|
||||
imp = new GeometricInputSlide(rate0,rate1,n);
|
||||
} else if(slideType == SlideGeometricOutput) {
|
||||
imp = new GeometricOutputSlide(rate0,rate1,n);
|
||||
}
|
||||
}
|
||||
|
||||
Slide :: ~Slide()
|
||||
{
|
||||
delete imp;
|
||||
}
|
||||
|
||||
float Slide :: getTotalStretch()
|
||||
{
|
||||
return imp->getTotalStretch();
|
||||
}
|
||||
|
||||
float Slide :: getRate(float t)
|
||||
{
|
||||
if(t > 1.0f) t = 1.0f;
|
||||
return imp->getRate(t);
|
||||
}
|
||||
|
||||
float Slide :: getStretch(float t)
|
||||
{
|
||||
if(t > 1.0f) t = 1.0f;
|
||||
return imp->getStretch(t);
|
||||
}
|
||||
|
||||
float Slide :: getStretchedTime(float t)
|
||||
{
|
||||
if(t > 1.0f) t = 1.0f;
|
||||
return imp->getStretchedTime(t);
|
||||
}
|
||||
|
||||
float Slide :: getRate()
|
||||
{
|
||||
return imp->getRate();
|
||||
}
|
||||
|
||||
float Slide :: getStretch()
|
||||
{
|
||||
return imp->getStretch();
|
||||
}
|
||||
|
||||
void Slide :: step()
|
||||
{
|
||||
imp->step();
|
||||
}
|
||||
|
||||
class SBSMSInterfaceSlidingImp {
|
||||
public:
|
||||
friend class SBSMSInterfaceSliding;
|
||||
SBSMSInterfaceSlidingImp(Slide *rateSlide,
|
||||
Slide *pitchSlide,
|
||||
bool bPitchReferenceInput,
|
||||
const SampleCountType &samplesToInput,
|
||||
long preSamples,
|
||||
SBSMSQuality *quality);
|
||||
~SBSMSInterfaceSlidingImp() {}
|
||||
inline float getStretch(float t);
|
||||
inline float getPitch(float t);
|
||||
inline long getPresamples();
|
||||
SampleCountType getSamplesToInput();
|
||||
SampleCountType getSamplesToOutput();
|
||||
protected:
|
||||
Slide *stretchSlide;
|
||||
Slide *pitchSlide;
|
||||
bool bPitchReferenceInput;
|
||||
float totalStretch;
|
||||
float stretchScale;
|
||||
long preSamples;
|
||||
SampleCountType samplesToInput;
|
||||
SampleCountType samplesToOutput;
|
||||
};
|
||||
|
||||
|
||||
SBSMSInterfaceSlidingImp :: SBSMSInterfaceSlidingImp(Slide *stretchSlide,
|
||||
Slide *pitchSlide,
|
||||
bool bPitchReferenceInput,
|
||||
const SampleCountType &samplesToInput,
|
||||
long preSamples,
|
||||
SBSMSQuality *quality)
|
||||
{
|
||||
this->stretchSlide = stretchSlide;
|
||||
this->pitchSlide = pitchSlide;
|
||||
this->bPitchReferenceInput = bPitchReferenceInput;
|
||||
this->samplesToInput = samplesToInput;
|
||||
this->preSamples = preSamples;
|
||||
this->totalStretch = stretchSlide->getTotalStretch();
|
||||
this->samplesToOutput = (SampleCountType)((float)samplesToInput * totalStretch);
|
||||
stretchScale = 1.0f;
|
||||
|
||||
if(quality) {
|
||||
SampleCountType samplesIn = 0;
|
||||
SampleCountType samplesOut = 0;
|
||||
float outFrameSizefloat = 0.0f;
|
||||
float stretch = 1.0f;
|
||||
int inFrameSize = quality->getFrameSize();
|
||||
while(samplesIn < samplesToInput) {
|
||||
float t = (float)samplesIn / (float)samplesToInput;
|
||||
stretch = stretchSlide->getStretch(t);
|
||||
outFrameSizefloat += stretch * inFrameSize;
|
||||
int outFrameSize = (int) outFrameSizefloat;
|
||||
outFrameSizefloat -= (float) outFrameSize;
|
||||
samplesIn += inFrameSize;
|
||||
samplesOut += outFrameSize;
|
||||
}
|
||||
SampleCountType samplesOutputed = samplesOut - lrintf(stretch * (samplesIn - samplesToInput));
|
||||
stretchScale = (float)samplesToOutput / (float)samplesOutputed;
|
||||
}
|
||||
}
|
||||
|
||||
float SBSMSInterfaceSliding :: getStretch(float t) { return imp->getStretch(t); }
|
||||
float SBSMSInterfaceSlidingImp :: getStretch(float t)
|
||||
{
|
||||
return stretchScale * stretchSlide->getStretch(t);
|
||||
}
|
||||
|
||||
float SBSMSInterfaceSliding :: getPitch(float t) { return imp->getPitch(t); }
|
||||
float SBSMSInterfaceSlidingImp :: getPitch(float t)
|
||||
{
|
||||
if(bPitchReferenceInput) return pitchSlide->getRate(t);
|
||||
else return pitchSlide->getRate(min(1.0f,stretchSlide->getStretchedTime(t) / totalStretch));
|
||||
}
|
||||
|
||||
long SBSMSInterfaceSliding :: getPresamples() { return imp->getPresamples(); }
|
||||
long SBSMSInterfaceSlidingImp :: getPresamples()
|
||||
{
|
||||
return preSamples;
|
||||
}
|
||||
|
||||
SampleCountType SBSMSInterfaceSliding :: getSamplesToInput() { return imp->getSamplesToInput(); }
|
||||
SampleCountType SBSMSInterfaceSlidingImp :: getSamplesToInput()
|
||||
{
|
||||
return samplesToInput;
|
||||
}
|
||||
|
||||
SampleCountType SBSMSInterfaceSliding :: getSamplesToOutput() { return imp->getSamplesToOutput(); }
|
||||
SampleCountType SBSMSInterfaceSlidingImp :: getSamplesToOutput()
|
||||
{
|
||||
return samplesToOutput;
|
||||
}
|
||||
|
||||
SBSMSInterfaceSliding :: SBSMSInterfaceSliding(Slide *stretchSlide,
|
||||
Slide *pitchSlide,
|
||||
bool bPitchReferenceInput,
|
||||
const SampleCountType &samplesToInput,
|
||||
long preSamples,
|
||||
SBSMSQuality *quality)
|
||||
{
|
||||
imp = new SBSMSInterfaceSlidingImp(stretchSlide, pitchSlide, bPitchReferenceInput,
|
||||
samplesToInput, preSamples, quality);
|
||||
}
|
||||
|
||||
SBSMSInterfaceSliding :: ~SBSMSInterfaceSliding()
|
||||
{
|
||||
delete imp;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,141 +1,196 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef SMS_H
|
||||
#define SMS_H
|
||||
|
||||
#include "track.h"
|
||||
#include "grain.h"
|
||||
#include "buffer.h"
|
||||
#include "peak.h"
|
||||
#include "sbsms.h"
|
||||
#include "config.h"
|
||||
#ifdef MULTITHREADED
|
||||
#include "pthread.h"
|
||||
#endif
|
||||
|
||||
#include "sbsms.h"
|
||||
#include "track.h"
|
||||
#include "grain.h"
|
||||
#include "buffer.h"
|
||||
#include <queue>
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
class renderer;
|
||||
class sms : public SampleBufBase {
|
||||
friend class renderer;
|
||||
enum {
|
||||
minTrial2Band = 1,
|
||||
minTrial1Band = 2
|
||||
};
|
||||
|
||||
class SynthRenderer : public SBSMSRenderer, public SampleBufBase {
|
||||
public:
|
||||
sms(int N, unsigned short M, unsigned short M_MAX, int res, int latency, real p, real q, real pad, int Nlo, int channels, TrackAllocator *ta, PeakAllocator *pa);
|
||||
void reset();
|
||||
void readTrackPointsFromFile(FILE *fp);
|
||||
int writeTrackPointsToFile(FILE *fp);
|
||||
void setH(unsigned short h);
|
||||
long addTrackPoints(grain *g0, grain *g1, grain *g2);
|
||||
long assignTrackPoints(long offset, sms *hi, sms *lo, int c);
|
||||
long startNewTracks(long offset, int c);
|
||||
void markDuplicates(long offset, sms *hi, sms *lo, int c);
|
||||
bool connectTrackPoints(trackpoint *tp0, trackpoint *tp1, sms *hi, sms *lo, real dtlo, int c);
|
||||
bool adoptTrack(track *precursor, sms *lender, trackpoint *tp, real m, real dt, int c);
|
||||
void synthTracks(real a, real f0, real f1);
|
||||
void advanceTrackPoints(int c);
|
||||
long nTrackPoints();
|
||||
SynthRenderer(int channels, int h);
|
||||
~SynthRenderer();
|
||||
void startTime(int c, const TimeType &time, int n);
|
||||
void render(int c, SBSMSTrack *t);
|
||||
void endTime(int c);
|
||||
long read(audio *out, long n);
|
||||
long n_readable();
|
||||
void advance(long n);
|
||||
void zeroPad(long n);
|
||||
void addTrack(int c, track *t);
|
||||
~sms();
|
||||
|
||||
|
||||
bool bPhaseLock;
|
||||
int res;
|
||||
int N;
|
||||
unsigned short M;
|
||||
real m;
|
||||
int Nover2;
|
||||
RingBuffer<unsigned short> hSynth;
|
||||
real h2cum;
|
||||
long samplePos;
|
||||
TrackPointListBuffer* trackPointListBuffer[2];
|
||||
|
||||
|
||||
#ifdef MULTITHREADED
|
||||
pthread_mutex_t dataMutex;
|
||||
pthread_mutex_t tplbMutex[2];
|
||||
pthread_mutex_t bufferMutex;
|
||||
pthread_mutex_t trackMutex[2];
|
||||
#endif
|
||||
|
||||
protected:
|
||||
unsigned short encodeReal(real x, real min, real max);
|
||||
float decodeReal(unsigned short x, real min, real max);
|
||||
unsigned short encodeRealLog(real x);
|
||||
float decodeRealLog(unsigned short x);
|
||||
bool terminal;
|
||||
void markDuplicatesLo(long offset, sms *lo, long offsetlo, int c);
|
||||
long assignTrackPoints_(long offset, sms *hi, sms *lo, real dtlo, long offsetlo, int c);
|
||||
void deleteTrackPoint(trackpoint *tp);
|
||||
void adjustPeaks(list<peak*> &peaks,
|
||||
real *mag0,
|
||||
real *mag1,
|
||||
real *mag2,
|
||||
real *dec,
|
||||
int peakWidth);
|
||||
long assignTrackPoints(long offset, sms *hi, sms *lo, real dtlo, long offsetlo, int c);
|
||||
bool contTrack(track *t, trackpoint *tp, int c);
|
||||
void extractTrackPoints(grain *g, real *mag0, real *mag1, real *mag2, long currtime, TrackPointListBuffer *tplb, unsigned short h1, int c);
|
||||
bool nearestTrackPoint(tplist *tpl, trackpoint *tp0, real m0, real m1, real dt, tplist::iterator *minpos, real *minFx, real maxMerit2, real maxDF2);
|
||||
int prune(trackpoint *tp);
|
||||
real merit(trackpoint *tp0, trackpoint *tp1, real m0, real m1, real dt, real dMCoeff, real *df, real maxDF2);
|
||||
void calcmags(real *mag, grain *g, real q);
|
||||
peak *makePeak(real *mag, real *mag2, int k);
|
||||
|
||||
TrackAllocator *ta;
|
||||
PeakAllocator *pa;
|
||||
char *pData;
|
||||
int datasize;
|
||||
int channels;
|
||||
real p,q;
|
||||
int peakWidth;
|
||||
int maxPrunes;
|
||||
real peakThresh;
|
||||
real startThresh;
|
||||
real maxMerit2;
|
||||
real maxDF2;
|
||||
real dMCoeff;
|
||||
real maxMerit2Match;
|
||||
real maxDF2Match;
|
||||
real dMCoeffMatch;
|
||||
int minNpts;
|
||||
real maxdBIncr;
|
||||
real maxdBIncrStitch;
|
||||
real maxFMatch;
|
||||
real minFMatch;
|
||||
float *synthBuf[2];
|
||||
int synthBufLength[2];
|
||||
ArrayRingBuffer<float> *sines[2];
|
||||
TimeType time[2];
|
||||
int n[2];
|
||||
#ifdef MULTITHREADED
|
||||
pthread_mutex_t bufferMutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
class SMS {
|
||||
public:
|
||||
SMS(SMS *lo, int N, int band, int bandMax, int h, int res, int N0, int N1, int N2, int channels, audio *peak2);
|
||||
~SMS();
|
||||
void render(int c, list<SBSMSRenderer*> &renderers);
|
||||
void add(grain *g0, grain *g1, grain *g2, int c);
|
||||
void assignStart(long offset, int c);
|
||||
void assignInit(long offset, int c);
|
||||
void assignFind(long offset, int c);
|
||||
bool assignConnect(long offset, int c, bool bLastDitch);
|
||||
void start(long offset, int c);
|
||||
void splitMerge(int c);
|
||||
void mark(long offset, int c);
|
||||
void advance(int c);
|
||||
void trial2(int c);
|
||||
void trial2Start(int c);
|
||||
void trial2End(int c);
|
||||
void adjust2();
|
||||
void trial1(int c);
|
||||
void trial1Start(int c);
|
||||
void trial1End(int c);
|
||||
void adjust1(float stretch, float pitch0, float pitch1);
|
||||
void adjustInit(ArrayRingBuffer<float> **trialRingBuf,
|
||||
GrainBuf *trialGrainBuf);
|
||||
void adjust(GrainBuf *trialGrainBuf,
|
||||
queue<float*> *magQueue,
|
||||
int minCutSep,
|
||||
float **_mag1,
|
||||
float **_dmag1,
|
||||
audio **x1,
|
||||
const TimeType &time,
|
||||
Slice **slice);
|
||||
void prepad1(audio *buf, long n);
|
||||
void prepad0(audio *buf, long n);
|
||||
int getTrial2Latency();
|
||||
|
||||
protected:
|
||||
void connect(TrackPoint *tp0, TrackPoint *tp1, int ilo, int c);
|
||||
void mark(long offset, long offsetlo, int c);
|
||||
TrackPoint *nearestForward(TrackPoint **begin, TrackPoint *tp0, float *minCost2, float maxCost2, float maxDF2, float dMCoeff2, float dNCoeff2 = 0.0f);
|
||||
TrackPoint *nearestReverse(TrackPoint **begin, TrackPoint *tp0, float *minCost2, float maxCost2, float maxDF2, float dMCoeff2, float dNCoeff2 = 0.0f);
|
||||
TrackPoint *nearestForward2(TrackPoint **begin, TrackPoint *tp0, float *minCost2, float maxCost2, float maxDF2, float dMCoeff2, float dNCoeff2 = 0.0f);
|
||||
TrackPoint *nearestReverse2(TrackPoint **begin, TrackPoint *tp0, float *minCost2, float maxCost2, float maxDF2, float dMCoeff2, float dNCoeff2 = 0.0f);
|
||||
float interp2(int k, int ko1, float kf);
|
||||
float findExtremum(float *mag, float *mag2, int k, float *y);
|
||||
void calcmags(float *mag, audio *x);
|
||||
int findCut(float *dmag, int k, int maxK);
|
||||
Track *createTrack(int c, TrackPoint *tp, const TimeType &time, bool bStitch);
|
||||
void returnTrackIndex(int c, Track *t);
|
||||
|
||||
list<TrackPoint*> ended[2];
|
||||
list<TrackPoint*> started[2];
|
||||
int minTrackSize;
|
||||
int peakWidth0;
|
||||
int peakWidth1;
|
||||
int peakWidth2;
|
||||
int minCutSep1;
|
||||
int minCutSep2;
|
||||
int minK;
|
||||
int maxK;
|
||||
float peakThresh;
|
||||
float maxCost2;
|
||||
float maxDF;
|
||||
float dMCoeff2;
|
||||
float dNCoeff2;
|
||||
float maxDFSplitMerge;
|
||||
float maxCost2SplitMerge;
|
||||
float dMCoeff2SplitMerge;
|
||||
float maxCost2Match;
|
||||
float maxDFMatch;
|
||||
float dMCoeff2Match;
|
||||
float maxCost2Stereo;
|
||||
float maxDFStereo;
|
||||
float dMCoeff2Stereo;
|
||||
float maxFMatchM;
|
||||
float minFMatchL;
|
||||
float minFLo;
|
||||
float maxFHi;
|
||||
float minFMid;
|
||||
float maxFMid;
|
||||
int kStart;
|
||||
int kEnd;
|
||||
real mNorm;
|
||||
real minPeakTopRatio;
|
||||
real localFavorRatio;
|
||||
real maxDecRatio;
|
||||
|
||||
list<track*> **trax;
|
||||
long currtime;
|
||||
long assigntime[2];
|
||||
long marktime[2];
|
||||
long synthtime;
|
||||
|
||||
SampleBuf *sines2, *outMixer;
|
||||
grain* x0[2];
|
||||
grain* x1[2];
|
||||
grain* x2[2];
|
||||
|
||||
void c2evenodd(grain *g, grain *, grain *);
|
||||
|
||||
real* dec;
|
||||
real* dec2;
|
||||
real* mag0[2];
|
||||
real* mag1[2];
|
||||
real* mag2[2];
|
||||
real *peak1;
|
||||
bool bPeakSet;
|
||||
real sqrtmagmax;
|
||||
real magmax;
|
||||
|
||||
int kLo;
|
||||
int kHi;
|
||||
float mNorm;
|
||||
float localFavorRatio;
|
||||
queue<Slice*> adjust2SliceQueue[2];
|
||||
queue<Slice*> adjust1SliceQueue[2];
|
||||
RingBuffer<Slice*> sliceBuffer[2];
|
||||
Slice* sliceM0[2];
|
||||
Slice* sliceL0[2];
|
||||
Slice* sliceH0[2];
|
||||
Slice* sliceM1[2];
|
||||
Slice* sliceL1[2];
|
||||
Slice* sliceM2[2];
|
||||
Slice* sliceH1[2];
|
||||
audio* x10[2];
|
||||
audio* x11[2];
|
||||
float* dmag1[2];
|
||||
float* mag11[2];
|
||||
audio* x00[2];
|
||||
audio* x01[2];
|
||||
float* dmag0[2];
|
||||
float* mag01[2];
|
||||
float *mag2[2];
|
||||
audio* x2[2];
|
||||
float* dec2[2];
|
||||
float *peak20;
|
||||
float *peak2N;
|
||||
int N;
|
||||
int Nover2;
|
||||
SMS *lo;
|
||||
SMS *hi;
|
||||
queue<TrackIndexType> trackIndex[2];
|
||||
queue<float*> mag1Queue[2];
|
||||
queue<float*> mag0Queue[2];
|
||||
float *trial2Buf[2];
|
||||
ArrayRingBuffer<float> *trial2RingBuf[2];
|
||||
GrainBuf *trial2GrainBuf;
|
||||
float *trial1Buf[2];
|
||||
ArrayRingBuffer<float> *trial1RingBuf[2];
|
||||
GrainBuf *trial1GrainBuf;
|
||||
list<Track*> assignTracks[2];
|
||||
list<Track*> renderTracks[2];
|
||||
TimeType addtime[2];
|
||||
TimeType assigntime[2];
|
||||
TimeType trial2time[2];
|
||||
TimeType adjust2time;
|
||||
TimeType trial1time[2];
|
||||
TimeType adjust1time;
|
||||
TimeType synthtime[2];
|
||||
queue<int> nRender[2];
|
||||
double h2cum;
|
||||
int channels;
|
||||
long res;
|
||||
long resMask;
|
||||
int h;
|
||||
float M;
|
||||
double h1;
|
||||
int band;
|
||||
#ifdef MULTITHREADED
|
||||
pthread_mutex_t sliceMutex[2];
|
||||
pthread_mutex_t magMutex[2];
|
||||
pthread_mutex_t renderMutex[2];
|
||||
pthread_mutex_t trial2Mutex[2];
|
||||
pthread_mutex_t trial1Mutex[2];
|
||||
pthread_mutex_t trackMutex[2];
|
||||
#endif
|
||||
bool bAssignDone[2];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef SSE_H
|
||||
#define SSE_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef ENABLE_SSE
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
typedef __m128 simd_vector;
|
||||
#define LOAD(p) _mm_loadu_ps((float*)(p))
|
||||
#define STORE(v,p) _mm_storeu_ps((float*)(p),v)
|
||||
#define LOAD16(p) _mm_load_ps((float*)(p))
|
||||
#define STORE16(v,p) _mm_store_ps((float*)(p),v)
|
||||
#define LOADL(v,p) _mm_loadl_pi(v,(const __m64*)(p))
|
||||
#define LOADH(v,p) _mm_loadh_pi(v,(const __m64*)(p))
|
||||
#define STOREL(v,p) _mm_storel_pi((__m64 *)(p), v)
|
||||
#define STOREH(v,p) _mm_storeh_pi((__m64 *)(p), v)
|
||||
#define VADD(v1,v2) _mm_add_ps(v1,v2)
|
||||
#define VSUB(v1,v2) _mm_sub_ps(v1,v2)
|
||||
#define VMUL(v1,v2) _mm_mul_ps(v1,v2)
|
||||
#define SHUFFLE(a,b,w,x,y,z) _mm_shuffle_ps(a,b,_MM_SHUFFLE(z,y,x,w))
|
||||
#define SET(f) _mm_set1_ps(f)
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,9 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef SUBBAND_H
|
||||
#define SUBBAND_H
|
||||
|
||||
#include "real.h"
|
||||
#include "buffer.h"
|
||||
#include "audio.h"
|
||||
#include "sms.h"
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
|
@ -13,164 +13,172 @@
|
|||
|
||||
namespace _sbsms_ {
|
||||
|
||||
class renderer;
|
||||
enum {
|
||||
NDownSample = 256,
|
||||
SDownSample = 4,
|
||||
subBufSize = 512,
|
||||
hSub = NDownSample/(2*SDownSample)
|
||||
};
|
||||
|
||||
class subband {
|
||||
friend class renderer;
|
||||
class SubBand {
|
||||
public:
|
||||
subband(subband *parent, unsigned short M, int channels, sbsms_quality *quality, int latency, bool bPreAnalysis, TrackAllocator *ta, PeakAllocator *pa);
|
||||
~subband();
|
||||
SubBand(SubBand *parent, int band, int channels, SBSMSQuality *quality, bool bSynthesize);
|
||||
~SubBand();
|
||||
|
||||
long write(audio *buf, long n, real a, real ratio);
|
||||
void process();
|
||||
long read(audio *buf, real *ratio0, real *ratio1);
|
||||
long n_readable();
|
||||
bool isframe_readable();
|
||||
void writingComplete();
|
||||
long readFromFile(FILE *fp, real a, real ratio);
|
||||
long synth();
|
||||
long getFramesWrittenToFile();
|
||||
long writeToFile(FILE *fp);
|
||||
void init();
|
||||
void reset();
|
||||
void seek(long framePos);
|
||||
long getSamplesQueued();
|
||||
long getFramesQueued();
|
||||
long getFramesAtFront();
|
||||
long getFramesAtBack();
|
||||
long getLastInputFrameSize();
|
||||
long getFramePos();
|
||||
void write_(audio *buf, long n, real a, real ratio);
|
||||
long write(audio *buf, long n, float stretch, float pitch);
|
||||
long read(audio *buf, long n);
|
||||
long getInputFrameSize();
|
||||
|
||||
void writeFramePositionsToFile(FILE *fp);
|
||||
long addInit(bool);
|
||||
void addTrackPoints();
|
||||
long markInit(bool, int c);
|
||||
void markDuplicates(int c);
|
||||
long assignInit(bool,int c);
|
||||
long assignTrackPoints(int c);
|
||||
void startNewTracks(int c);
|
||||
void advanceTrackPoints(int c);
|
||||
long synthInit(bool);
|
||||
void synthTracks();
|
||||
long readInit(bool);
|
||||
long writeTracksToFile(FILE *fp);
|
||||
void readTrackPointsFromFile(FILE *fp);
|
||||
long writeTrackPointsToFile(FILE *fp);
|
||||
void stepAddFrame();
|
||||
void stepMarkFrame(int c);
|
||||
void stepAssignFrame(int c);
|
||||
void stepSynthFrame();
|
||||
bool writeInit();
|
||||
long analyzeInit(int,bool,long n=0);
|
||||
long extractInit(int,bool);
|
||||
long markInit(int,bool);
|
||||
long assignInit(int,bool);
|
||||
long trial2Init(int,bool);
|
||||
long adjust2Init(bool);
|
||||
long trial1Init(int,bool);
|
||||
long adjust1Init(bool);
|
||||
long renderInit(int,bool);
|
||||
long writeFromFileInit(int,bool);
|
||||
long readInit();
|
||||
|
||||
void analyze(int);
|
||||
void extract(int);
|
||||
void mark(int);
|
||||
void assign(int);
|
||||
void trial2(int);
|
||||
void trial2Start(int);
|
||||
void trial2Trial(int);
|
||||
void trial2End(int);
|
||||
void adjust2();
|
||||
void trial1(int);
|
||||
void trial1Start(int);
|
||||
void trial1Trial(int);
|
||||
void trial1End(int);
|
||||
void adjust1();
|
||||
void advance(int);
|
||||
void render(int);
|
||||
|
||||
void assignStart(int c);
|
||||
void assignInit(int c);
|
||||
void assignFind(int c);
|
||||
bool assignConnect(int c);
|
||||
void assignStep(int c);
|
||||
void splitMerge(int c);
|
||||
void addRenderer(SBSMSRenderer *);
|
||||
void removeRenderer(SBSMSRenderer *);
|
||||
long renderSynchronous();
|
||||
void renderComplete(const SampleCountType &samples);
|
||||
void process(bool);
|
||||
|
||||
void stepAnalyzeFrame(int);
|
||||
void stepExtractFrame(int);
|
||||
void stepMarkFrame(int);
|
||||
void stepAssignFrame(int);
|
||||
void stepTrial2Frame(int);
|
||||
void stepAdjust2Frame();
|
||||
void stepTrial1Frame(int);
|
||||
void stepAdjust1Frame();
|
||||
void stepRenderFrame(int);
|
||||
void stepReadFrame();
|
||||
void readSubSamples();
|
||||
void setA(real a);
|
||||
void setAMod(real a);
|
||||
void setAForH(real a);
|
||||
void setH(real ratio);
|
||||
void setF(real f);
|
||||
void setFrameSize(int inputSize, real a, real ratio);
|
||||
void setRatio(real ratio);
|
||||
void setFramesInFile(long frames);
|
||||
long zeroPad();
|
||||
long zeroPad_();
|
||||
|
||||
long preAnalyze(audio *buf, long n, real a, real ratio);
|
||||
void preAnalyzeComplete();
|
||||
|
||||
FILE *fp;
|
||||
|
||||
long getFramesAssigned();
|
||||
long getFramesMarked();
|
||||
|
||||
bool isWriteReady();
|
||||
bool isAddReady();
|
||||
bool isMarkReady();
|
||||
bool isAssignReady();
|
||||
bool isSynthReady();
|
||||
#ifdef MULTITHREADED
|
||||
pthread_mutex_t dataMutex;
|
||||
pthread_mutex_t bufferMutex;
|
||||
pthread_mutex_t grainMutex[3];
|
||||
#endif
|
||||
|
||||
long nLatency;
|
||||
long nLatencyOriginal;
|
||||
friend class SBSMSImp;
|
||||
|
||||
protected:
|
||||
long read(audio *buf, long n);
|
||||
void calculateA(long kstart, long kend);
|
||||
real calculateOnset(grain *g1, grain *g2);
|
||||
void resetNoRecurse();
|
||||
|
||||
long getFramesAtFront(int);
|
||||
void readSubSamples();
|
||||
void setStretch(float stretch);
|
||||
void setPitch(float pitch);
|
||||
|
||||
TrackAllocator *ta;
|
||||
PeakAllocator *pa;
|
||||
|
||||
RingBuffer<real> aPreAnalysis;
|
||||
RingBuffer<real> aMod;
|
||||
RingBuffer<real> aSynth;
|
||||
RingBuffer<real> aForH;
|
||||
RingBuffer<real> fSynth;
|
||||
RingBuffer<int> inputFrameSize;
|
||||
int nMarkLatency;
|
||||
int nAssignLatency;
|
||||
int nTrial2Latency;
|
||||
int nAdjust2Latency;
|
||||
int nTrial1Latency;
|
||||
int nAdjust1Latency;
|
||||
int nRenderLatency;
|
||||
int nWriteSlack;
|
||||
int nExtractSlack;
|
||||
int nAnalyzeSlack;
|
||||
int nMarkSlack;
|
||||
int nAssignSlack;
|
||||
int nTrial2Slack;
|
||||
int nAdjust2Slack;
|
||||
int nTrial1Slack;
|
||||
int nAdjust1Slack;
|
||||
int nRenderSlack;
|
||||
list<SBSMSRenderer*> renderers;
|
||||
RingBuffer<float> stretchRender;
|
||||
RingBuffer<float> pitchRender;
|
||||
int inputFrameSize;
|
||||
RingBuffer<int> outputFrameSize;
|
||||
RingBuffer<real> frameRatio;
|
||||
RingBuffer<int> frameBytes;
|
||||
RingBuffer<real> onset;
|
||||
grain *gPrev;
|
||||
|
||||
real getOnset(long k);
|
||||
int lastInputFrameSize;
|
||||
int lastOutputFrameSize;
|
||||
real samplesQueued;
|
||||
real lastFrameA;
|
||||
real lastFrameRatio;
|
||||
real totalSizef;
|
||||
bool bPreAnalyze;
|
||||
sbsms_quality *quality;
|
||||
float totalSizef;
|
||||
SBSMSQuality *quality;
|
||||
int channels;
|
||||
int N;
|
||||
int h;
|
||||
unsigned short M;
|
||||
int s;
|
||||
int res;
|
||||
int nGrainsPerFrame;
|
||||
int resTotal;
|
||||
long nDropped;
|
||||
long nToDrop;
|
||||
int band;
|
||||
long nReadFromOutputFrame;
|
||||
long nToWriteForGrain;
|
||||
long res;
|
||||
long resMask;
|
||||
long nGrainsPerFrame;
|
||||
long nToDrop0;
|
||||
long nToDrop1;
|
||||
long nToDrop2;
|
||||
long nToPrepad1;
|
||||
long nToPrepad0;
|
||||
bool bSynthesize;
|
||||
|
||||
long nTrackPointsToAdd;
|
||||
long nTrackPointsToMark[2];
|
||||
long nTrackPointsToAssign[2];
|
||||
long nTrackPointsToAdvance[2];
|
||||
long nTrackPointsToSynth;
|
||||
long nGrainsToAnalyze[3];
|
||||
long nGrainsToExtract[2];
|
||||
long nGrainsToMark[2];
|
||||
long nGrainsToAssign[2];
|
||||
long nGrainsToAdvance[2];
|
||||
long nGrainsToTrial2[2];
|
||||
long nGrainsToAdjust2;
|
||||
long nGrainsToTrial1[2];
|
||||
long nGrainsToAdjust1;
|
||||
long nGrainsToRender[2];
|
||||
long nGrainsWritten;
|
||||
long nGrainsMarked[2];
|
||||
long nGrainsAssigned[2];
|
||||
long nGrainsTrialed2[2];
|
||||
long nGrainsAdjusted2;
|
||||
long nGrainsTrialed1[2];
|
||||
long nGrainsAdjusted1;
|
||||
long nGrainsAdvanced[2];
|
||||
long nGrainsRendered[2];
|
||||
long nGrainsRead;
|
||||
|
||||
long nTrackPointsMarked[2];
|
||||
long nTrackPointsAssigned[2];
|
||||
long nTrackPointsStarted[2];
|
||||
long nTrackPointsAdvanced[2];
|
||||
long nTrackPointsSynthed;
|
||||
long nTrackPointsRead;
|
||||
long nFramesSkipped;
|
||||
long nFramesWritten;
|
||||
long nFramesAdded;
|
||||
long nFramesAnalyzed[3];
|
||||
long nFramesExtracted[2];
|
||||
long nFramesMarked[2];
|
||||
long nFramesAssigned[2];
|
||||
long nFramesTrialed2[2];
|
||||
long nFramesAdjusted2;
|
||||
long nFramesTrialed1[2];
|
||||
long nFramesAdjusted1;
|
||||
long nFramesRendered[2];
|
||||
long nFramesRead;
|
||||
long nFramesSynthed;
|
||||
long nFramesInFile;
|
||||
long nTrackPointsWritten;
|
||||
|
||||
bool bWritingComplete;
|
||||
subband *parent;
|
||||
subband *sub;
|
||||
GrainBuf *in0,*in1,*in2;
|
||||
SubBand *parent;
|
||||
SubBand *sub;
|
||||
SampleBufBase *outMixer;
|
||||
sms *smser;
|
||||
SampleBuf *subIn;
|
||||
SampleBuf *subOut;
|
||||
GrainBuf *in;
|
||||
GrainBuf *inPre;
|
||||
|
||||
grain *x1[2];
|
||||
grain *x2[2];
|
||||
|
||||
SynthRenderer *synthRenderer;
|
||||
SMS *sms;
|
||||
SampleBuf *samplesSubIn;
|
||||
SampleBuf *samplesSubOut;
|
||||
GrainBuf *grains[3];
|
||||
GrainBuf *analyzedGrains[3][2];
|
||||
GrainBuf *grainsIn;
|
||||
GrainAllocator *downSampledGrainAllocator;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,309 +1,341 @@
|
|||
#include "track.h"
|
||||
#include <math.h>
|
||||
#include "utils.h"
|
||||
#include "real.h"
|
||||
#include "sbsms.h"
|
||||
#include "sms.h"
|
||||
#include <vector>
|
||||
#include "dBTable.h"
|
||||
#include "synthTable.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
#define SBSMS_TRACK_BLOCK 2048
|
||||
|
||||
TrackAllocator :: TrackAllocator(bool bManageIndex)
|
||||
Track :: Track(float h, TrackIndexType index, TrackPoint *p, const TimeType &time, bool bStitch)
|
||||
{
|
||||
this-> bManageIndex = bManageIndex;
|
||||
}
|
||||
|
||||
TrackAllocator :: TrackAllocator(bool bManageIndex, unsigned short maxtrackindex)
|
||||
{
|
||||
this-> bManageIndex = bManageIndex;
|
||||
gTrack.resize(maxtrackindex);
|
||||
init();
|
||||
}
|
||||
|
||||
TrackAllocator :: ~TrackAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
void TrackAllocator :: init()
|
||||
{
|
||||
for(unsigned short k=0;k<gTrack.size();k++)
|
||||
gTrack[k] = NULL;
|
||||
while(!gTrackIndex.empty())
|
||||
gTrackIndex.pop();
|
||||
#ifdef MULTITHREADED
|
||||
pthread_mutex_init(&taMutex,NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
track *TrackAllocator :: getTrack(unsigned short index)
|
||||
{
|
||||
return gTrack[index];
|
||||
}
|
||||
|
||||
int TrackAllocator :: size()
|
||||
{
|
||||
return gTrack.size();
|
||||
}
|
||||
|
||||
track *TrackAllocator :: create(track *precursor, sms *owner, int res, unsigned short index)
|
||||
{
|
||||
track *t = new track(precursor,owner,res);
|
||||
t->index = index;
|
||||
gTrack[index] = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
track *TrackAllocator :: create(track *precursor, sms *owner, int res)
|
||||
{
|
||||
#ifdef MULTITHREADED
|
||||
pthread_mutex_lock(&taMutex);
|
||||
#endif
|
||||
if(gTrackIndex.empty()) {
|
||||
unsigned short n = gTrack.size();
|
||||
gTrack.resize(n+SBSMS_TRACK_BLOCK);
|
||||
for(int k=n+SBSMS_TRACK_BLOCK-1;k>=n;k--) {
|
||||
gTrackIndex.push(k);
|
||||
gTrack[k] = NULL;
|
||||
}
|
||||
}
|
||||
unsigned short index = gTrackIndex.top();
|
||||
gTrackIndex.pop();
|
||||
#ifdef MULTITHREADED
|
||||
pthread_mutex_unlock(&taMutex);
|
||||
#endif
|
||||
return create(precursor, owner, res, index);
|
||||
}
|
||||
|
||||
void TrackAllocator :: destroy(track *t)
|
||||
{
|
||||
#ifdef MULTITHREADED
|
||||
pthread_mutex_lock(&taMutex);
|
||||
#endif
|
||||
gTrack[t->index] = NULL;
|
||||
if(bManageIndex)
|
||||
gTrackIndex.push(t->index);
|
||||
delete t;
|
||||
#ifdef MULTITHREADED
|
||||
pthread_mutex_unlock(&taMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
track :: track(track *precursor, sms *owner, int res)
|
||||
{
|
||||
this->owner = owner;
|
||||
this->res = res;
|
||||
this->descendant = NULL;
|
||||
this->precursor = precursor;
|
||||
this->end = LONG_MAX;
|
||||
this->rise = 0.3f;
|
||||
this->fall = 0.5f;
|
||||
tailEnd = 0;
|
||||
tailStart = 0;
|
||||
m_p = 0.0;
|
||||
currtime = 0;
|
||||
}
|
||||
|
||||
|
||||
void track :: endTrack(bool bTail)
|
||||
{
|
||||
end = back()->time;
|
||||
if(bTail) {
|
||||
this->fall = min(1.5f,.25f + back()->y / point[point.size()-2]->y);
|
||||
tailEnd = 1;
|
||||
end++;
|
||||
trackpoint *f = new trackpoint(back());
|
||||
f->time = back()->time + 1;
|
||||
point.push_back(f);
|
||||
}
|
||||
}
|
||||
|
||||
void track :: synth(SampleBuf *out,
|
||||
long writePos,
|
||||
int c,
|
||||
long synthtime,
|
||||
int steps,
|
||||
real fScale0,
|
||||
real fScale1,
|
||||
real mScale) {
|
||||
if(point.size()==0) return;
|
||||
long k = synthtime - start;
|
||||
if(k>=(long)point.size()-1) return;
|
||||
currtime = synthtime;
|
||||
if(k<0) return;
|
||||
int k1 = k + 1;
|
||||
|
||||
tpoint *tp0 = point[k];
|
||||
tpoint *tp1 = point[k1];
|
||||
|
||||
real w0 = tp0->f;
|
||||
real w1 = tp1->f;
|
||||
real ph0 = tp0->ph;
|
||||
real ph1 = tp1->ph;
|
||||
real h = tp0->h;
|
||||
|
||||
real dp = ph1 - ph0;
|
||||
if(dp>PI) dp-=TWOPI;
|
||||
else if(dp<-PI) dp+=TWOPI;
|
||||
real dp0 = 0.5f*h*(w0 + w1);
|
||||
real dw = canon(dp - dp0)/h;
|
||||
|
||||
if(k==0) {
|
||||
if(precursor) {
|
||||
m_p = precursor->m_pDescendant;
|
||||
} else {
|
||||
dw = 0;
|
||||
}
|
||||
}
|
||||
|
||||
real dt = (real)steps;
|
||||
w0 = (w0+dw);
|
||||
w1 = (w1+dw);
|
||||
w0 = w0*fScale0;
|
||||
w1 = w1*fScale1;
|
||||
dp = dt*0.5f*(w0 + w1);
|
||||
real b = (w1 - w0)/(2.0f*dt);
|
||||
|
||||
bool bEnd = (k1==(long)point.size()-1);
|
||||
bool bStart = (k==0);
|
||||
|
||||
if(bStart && tailStart) {
|
||||
if(w0 < PI && w0 > -PI) {
|
||||
real ph = m_p;
|
||||
int rise = round2int(this->rise * (real)steps);
|
||||
real dm = mScale*tp1->y/(real)rise;
|
||||
real m = mScale*tp1->y - dm;
|
||||
for(int i=steps-1;i>=steps-rise+1;i--) {
|
||||
ph -= w0;
|
||||
if(ph<-PI) ph += TWOPI;
|
||||
else if(ph>PI) ph -= TWOPI;
|
||||
out->buf[writePos+i][c] += m * COS(ph);
|
||||
m -= dm;
|
||||
}
|
||||
}
|
||||
} else if(bEnd && tailEnd) {
|
||||
if(w0 < PI && w0 > -PI) {
|
||||
real ph = m_p;
|
||||
int fall = round2int(this->fall * (real)steps);
|
||||
real dm = mScale*tp0->y/(real)fall;
|
||||
real m = mScale*tp0->y;
|
||||
for(int i=0;i<fall;i++) {
|
||||
out->buf[writePos+i][c] += m * COS(ph);
|
||||
ph += w0;
|
||||
if(ph<-PI) ph += TWOPI;
|
||||
else if(ph>PI) ph -= TWOPI;
|
||||
m -= dm;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
real m = mScale*tp0->y;
|
||||
real dm = mScale*(tp1->y0 - tp0->y)/dt;
|
||||
real ph = m_p;
|
||||
real b2tt1 = b;
|
||||
real b2 = 2.0f*b;
|
||||
real dph;
|
||||
|
||||
audio *o = &(out->buf[writePos]);
|
||||
for(int i=0;i<steps;i++) {
|
||||
dph = w0 + b2tt1;
|
||||
if(dph < PI && dph > -PI) (*o)[c] += m * COS(ph);
|
||||
ph += dph;
|
||||
if(ph<-PI) ph += TWOPI;
|
||||
else if(ph>PI) ph -= TWOPI;
|
||||
b2tt1 += b2;
|
||||
m += dm;
|
||||
o++;
|
||||
}
|
||||
}
|
||||
|
||||
if(bEnd) {
|
||||
if(descendant && descendant->back()->M < tp0->M) {
|
||||
m_pDescendant = canon(m_p + dp/dt*(real)(descendant->owner->samplePos - owner->samplePos));
|
||||
}
|
||||
} else if(bStart && tailStart) {
|
||||
this->h = h;
|
||||
jumpThresh2 = 1.0e-5f * h;
|
||||
this->index = index;
|
||||
bEnd = false;
|
||||
bEnded = false;
|
||||
bRender = false;
|
||||
bSplit = false;
|
||||
bMerge = false;
|
||||
first = time;
|
||||
start = time;
|
||||
if(bStitch) {
|
||||
this->bStitch = true;
|
||||
} else {
|
||||
m_p = canon(m_p + dp);
|
||||
if(descendant && descendant->back()->M > tp0->M && (k1+res==(long)point.size()-1)) {
|
||||
m_pDescendant = canon(m_p + dp/dt*(real)(descendant->owner->samplePos - (owner->samplePos+steps)));
|
||||
this->bStitch = false;
|
||||
if(start > 0) {
|
||||
start--;
|
||||
}
|
||||
}
|
||||
point.push_back(p);
|
||||
p->owner = this;
|
||||
p->refCount++;
|
||||
end = time;
|
||||
last = time;
|
||||
}
|
||||
|
||||
Track :: ~Track() {
|
||||
for(vector<TrackPoint*>::iterator i = point.begin();
|
||||
i != point.end();
|
||||
++i) {
|
||||
TrackPoint *tp = (*i);
|
||||
if(tp) tp->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
TrackIndexType Track :: getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
bool Track :: isFirst(const TimeType &time)
|
||||
{
|
||||
return (time == first);
|
||||
}
|
||||
|
||||
bool Track :: isLast(const TimeType &time)
|
||||
{
|
||||
return (time == last);
|
||||
}
|
||||
|
||||
TimeType Track :: size()
|
||||
{
|
||||
return point.size();
|
||||
}
|
||||
|
||||
TrackPoint *Track :: back()
|
||||
{
|
||||
return point.back();
|
||||
}
|
||||
|
||||
TrackPoint *Track :: getTrackPoint(const TimeType &time)
|
||||
{
|
||||
return point[time - first];
|
||||
}
|
||||
|
||||
SBSMSTrackPoint *Track :: getSBSMSTrackPoint(const TimeType &time)
|
||||
{
|
||||
return getTrackPoint(time);
|
||||
}
|
||||
|
||||
bool Track :: jump(TrackPoint *tp0, TrackPoint *tp1)
|
||||
{
|
||||
if(tp1->m > tp0->m) {
|
||||
float cost = 1.0e-4f * dBApprox(tp0->m,tp1->m);
|
||||
return (cost > jumpThresh2);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
TrackPoint *Track :: updateFPH(const TimeType &time, int mode, int n, float f0, float f1)
|
||||
{
|
||||
if(time == start && time < first) {
|
||||
TrackPoint *tp1 = getTrackPoint(time+1);
|
||||
tp1->fSynth1 = max(0.0f,min(6.0f,f1 * tp1->f));
|
||||
tp1->fSynth0 = tp1->fSynth1;
|
||||
tp1->phSynth = tp1->ph;
|
||||
if(mode == synthModeOutput && tp1->dupStereo) {
|
||||
return tp1;
|
||||
}
|
||||
} else if(time == last) {
|
||||
if(last < end) {
|
||||
TrackPoint *tp0 = getTrackPoint(time);
|
||||
tp0->fSynth0 = tp0->fSynth1;
|
||||
}
|
||||
} else {
|
||||
TrackPoint *tp0 = getTrackPoint(time);
|
||||
TrackPoint *tp1 = getTrackPoint(time+1);
|
||||
|
||||
if(mode == synthModeOutput) {
|
||||
if(tp0->dupStereo && tp1->dupStereo && tp0->dupStereo->owner == tp1->dupStereo->owner) {
|
||||
float dp = tp1->ph - tp0->ph;
|
||||
float dp0 = 0.5f*h*(tp0->f + tp1->f);
|
||||
float dw = canonPI(dp - dp0)/h;
|
||||
float dpStereo = tp1->dupStereo->ph - tp0->dupStereo->ph;
|
||||
float dp0Stereo = 0.5f*h*(tp0->dupStereo->f + tp1->dupStereo->f);
|
||||
float dwStereo = canonPI(dpStereo - dp0Stereo)/h;
|
||||
if(dw > .0013f * (tp0->f + tp1->f)) {
|
||||
dw = 0;
|
||||
dwStereo = 0;
|
||||
} else if(dwStereo > .0013f * (tp0->dupStereo->f + tp1->dupStereo->f)) {
|
||||
dwStereo = 0;
|
||||
}
|
||||
float w0 = 0.5f * (tp0->f + tp0->dupStereo->f + dw + dwStereo);
|
||||
float w1 = 0.5f * (tp1->f + tp1->dupStereo->f + dw + dwStereo);
|
||||
float dwSynth = 0.5f * canonPI(dp - dpStereo) / n;
|
||||
if(!(bSplit && time == first)) {
|
||||
tp0->fSynth0 = max(0.0f,min(6.0f,f0 * (w0 + dwSynth)));
|
||||
}
|
||||
if(!(bMerge && time + 1 == last)) {
|
||||
tp1->fSynth1 = max(0.0f,min(6.0f,f1 * (w1 + dwSynth)));
|
||||
}
|
||||
} else {
|
||||
float dp = tp1->ph - tp0->ph;
|
||||
float dp0 = 0.5f*h*(tp0->f + tp1->f);
|
||||
float dw = canonPI(dp - dp0)/h;
|
||||
if(dw > .0013f * (tp0->f + tp1->f)) {
|
||||
dw = 0;
|
||||
}
|
||||
if(!(bSplit && time == first)) {
|
||||
tp0->fSynth0 = max(0.0f,min(6.0f,f0 * (tp0->f + dw)));
|
||||
}
|
||||
if(!(bMerge && time + 1 == last)) {
|
||||
tp1->fSynth1 = max(0.0f,min(6.0f,f1 * (tp1->f + dw)));
|
||||
}
|
||||
}
|
||||
|
||||
if(!(tp0->bSplit || tp0->bMerge || tp1->bSplit || tp1->bMerge) && jump(tp0,tp1)) {
|
||||
tp1->bJump = true;
|
||||
if(tp0->dupStereo && tp1->dupStereo) {
|
||||
if(tp0->dupStereo->owner == tp1->dupStereo->owner) {
|
||||
tp1->bSyncStereo = !jump(tp0->dupStereo,tp1->dupStereo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!tp0->bSplit) {
|
||||
if(tp0->bJump) {
|
||||
if(tp0->bSyncStereo) {
|
||||
tp0->phSynth = canon2PI(tp0->dupStereo->phSynth + tp0->ph - tp0->dupStereo->ph);
|
||||
} else {
|
||||
tp0->phSynth = tp0->ph;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(bMerge && time + 1 == last)) {
|
||||
tp1->phSynth = canon2PI(tp0->phSynth + 0.5f * (tp0->fSynth0 + tp1->fSynth1) * n);
|
||||
}
|
||||
} else {
|
||||
float dp = tp1->ph - tp0->ph;
|
||||
float dp0 = 0.5f*h*(tp0->f + tp1->f);
|
||||
float dw = canonPI(dp - dp0)/h;
|
||||
if(dw > .0013f * (tp0->f + tp1->f)) {
|
||||
dw = 0;
|
||||
}
|
||||
if(!(bSplit && time == first)) {
|
||||
tp0->fSynth0 = max(0.0f,min(6.0f,f0 * (tp0->f + dw)));
|
||||
tp0->phSynth = tp0->ph;
|
||||
}
|
||||
if(!(bMerge && time + 1 == last)) {
|
||||
tp1->fSynth1 = max(0.0f,min(6.0f,f1 * (tp1->f + dw)));
|
||||
tp1->phSynth = tp1->ph;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Track :: updateM(const TimeType &time, int mode)
|
||||
{
|
||||
if(mode == synthModeTrial2) {
|
||||
if(time == first && time == start) {
|
||||
TrackPoint *tp0 = getTrackPoint(time);
|
||||
tp0->m = (tp0->m2>0.0f?sqrt(tp0->m2):0.0f);
|
||||
}
|
||||
if(time < last) {
|
||||
TrackPoint *tp1 = getTrackPoint(time+1);
|
||||
tp1->m = (tp1->m2>0.0f?sqrt(tp1->m2):0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool track :: isEnded()
|
||||
void Track :: step(const TimeType &time)
|
||||
{
|
||||
return (end!=LONG_MAX);
|
||||
if(time > first && time < last) {
|
||||
TrackPoint *tp = point[time-first];
|
||||
tp->destroy();
|
||||
point[time-first] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void track :: push_back_tpoint(tpoint *p)
|
||||
{
|
||||
point.push_back(p);
|
||||
}
|
||||
|
||||
void track :: push_back(trackpoint *p)
|
||||
void Track :: push_back(TrackPoint *p)
|
||||
{
|
||||
point.push_back(p);
|
||||
p->owner = this;
|
||||
p->refCount++;
|
||||
last++;
|
||||
end++;
|
||||
}
|
||||
|
||||
void track :: startTrack(trackpoint *p, bool bTail)
|
||||
|
||||
void Track :: endTrack(bool bStitch)
|
||||
{
|
||||
push_back(p);
|
||||
start = p->time;
|
||||
m_pDescendant = p->ph;
|
||||
if(bTail) {
|
||||
tailStart = 1;
|
||||
start--;
|
||||
trackpoint *s = new trackpoint(p);
|
||||
s->time = p->time - 1;
|
||||
point.insert(point.begin(),s);
|
||||
m_p = p->ph;
|
||||
if(bStitch) {
|
||||
this->bStitch = true;
|
||||
} else {
|
||||
end++;
|
||||
}
|
||||
currtime = p->time-1;
|
||||
bEnded = true;
|
||||
}
|
||||
|
||||
trackpoint *track :: back()
|
||||
void Track :: synth(float *out,
|
||||
const TimeType &time,
|
||||
int n,
|
||||
int mode,
|
||||
int c)
|
||||
{
|
||||
return (trackpoint*)point.back();
|
||||
}
|
||||
float m0, m1;
|
||||
float w0, w1;
|
||||
float dw;
|
||||
float ph0, ph1;
|
||||
bool bTailStart;
|
||||
bool bTailEnd;
|
||||
if(time >= end) return;
|
||||
if(time < last) {
|
||||
TrackPoint *tp1 = getTrackPoint(time+1);
|
||||
w1 = tp1->fSynth1;
|
||||
m1 = tp1->m;
|
||||
ph1 = tp1->phSynth;
|
||||
if(bMerge && time + 1 == last) {
|
||||
m1 = 0.0f;
|
||||
}
|
||||
bTailStart = tp1->bJump;
|
||||
bTailEnd = tp1->bJump;
|
||||
} else {
|
||||
bTailStart = false;
|
||||
bTailEnd = (last != end);
|
||||
}
|
||||
if(time >= first) {
|
||||
TrackPoint *tp0 = getTrackPoint(time);
|
||||
w0 = tp0->fSynth0;
|
||||
m0 = tp0->m;
|
||||
ph0 = tp0->phSynth;
|
||||
if(bSplit && time == first) {
|
||||
m0 = 0.0f;
|
||||
}
|
||||
} else {
|
||||
bTailStart = true;
|
||||
}
|
||||
|
||||
trackpoint *track :: getTrackPoint(long time)
|
||||
{
|
||||
long k = time-start;
|
||||
if(k<0 || k >= (long)point.size())
|
||||
return NULL;
|
||||
else
|
||||
return (trackpoint*)point[k];
|
||||
}
|
||||
if(bTailEnd) {
|
||||
int fall = min(n,w0==0.0f?384:min(384,(int)lrintf(PI * 4.0f / w0)));
|
||||
float dm = m0 / (float)fall;
|
||||
float w = w0;
|
||||
float *out2 = out;
|
||||
float *end = out + fall;
|
||||
long iph = lrintf(ph0 * WScale);
|
||||
if(iph>=W2PI) iph -= W2PI;
|
||||
long iw = lrintf(w * WScale);
|
||||
while(out2 != end) {
|
||||
if(iw < WPI) {
|
||||
long f = (iph>>PhShift)&Ph1;
|
||||
long i = iph>>WShift;
|
||||
*out2 += m0 * (float)(synthTable1[i] + f * synthTable2[i]);
|
||||
}
|
||||
out2++;
|
||||
m0 -= dm;
|
||||
iph += iw;
|
||||
iph &= W2PIMask;
|
||||
}
|
||||
}
|
||||
|
||||
bool track :: isStart(long synthtime)
|
||||
{
|
||||
return (synthtime == start);
|
||||
}
|
||||
if(bTailStart) {
|
||||
int rise = min(n,w1==0.0f?384:min(384,(int)lrintf(PI * 3.0f / w1)));
|
||||
float dm = m1 / (float)rise;
|
||||
float w = w1;
|
||||
out += n;
|
||||
float *end = out-rise;
|
||||
long iph = lrintf(ph1 * WScale);
|
||||
iph &= W2PIMask;
|
||||
long iw = lrintf(w * WScale);
|
||||
while(out != end) {
|
||||
out--;
|
||||
m1 -= dm;
|
||||
iph -= iw;
|
||||
if(iph<0) iph += W2PI;
|
||||
if(iw < WPI) {
|
||||
long f = (iph>>PhShift)&Ph1;
|
||||
long i = iph>>WShift;
|
||||
*out += m1 * (float)(synthTable1[i] + f * synthTable2[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool track :: isEnd(long synthtime)
|
||||
{
|
||||
return (synthtime == end);
|
||||
}
|
||||
if(!(bTailStart || bTailEnd)) {
|
||||
float dw = (w1 - w0) / n;
|
||||
float w = w0 + 0.5f * dw;
|
||||
float dm = (m1 - m0) / n;
|
||||
long iph = lrintf(ph0 * WScale);
|
||||
if(iph>=W2PI) iph -= W2PI;
|
||||
long iw = lrintf(w * WScale);
|
||||
long idw = lrintf(dw * WScale) + 1;
|
||||
|
||||
bool track :: isDone()
|
||||
{
|
||||
return (currtime-start+1 >= (long)point.size()-1);
|
||||
}
|
||||
|
||||
long track :: size()
|
||||
{
|
||||
return 1+end-start-tailEnd-tailStart;
|
||||
}
|
||||
|
||||
track :: ~track() {
|
||||
if(precursor) precursor->descendant = NULL;
|
||||
if(descendant) descendant->precursor = NULL;
|
||||
for(vector<tpoint*>::iterator i = point.begin();
|
||||
i != point.end();
|
||||
i++) {
|
||||
delete (*i);
|
||||
float *end = out + n;
|
||||
while(out != end) {
|
||||
if(iw < WPI) {
|
||||
long f = (iph>>PhShift)&Ph1;
|
||||
long i = iph>>WShift;
|
||||
*out += m0 * (float)(synthTable1[i] + f * synthTable2[i]);
|
||||
}
|
||||
iph += iw;
|
||||
iw += idw;
|
||||
iph &= W2PIMask;
|
||||
m0 += dm;
|
||||
out++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,90 +1,82 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef TRACK_H
|
||||
#define TRACK_H
|
||||
|
||||
#include "buffer.h"
|
||||
#include "trackpoint.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef MULTITHREADED
|
||||
#include "pthread.h"
|
||||
#endif
|
||||
#include <stack>
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
class sms;
|
||||
class renderer;
|
||||
|
||||
class track {
|
||||
friend class renderer;
|
||||
public:
|
||||
void endTrack(bool bTail);
|
||||
bool isEnded();
|
||||
bool isDone();
|
||||
void startTrack(trackpoint *p, bool bTail);
|
||||
void push_back(trackpoint *p);
|
||||
void push_back_tpoint(tpoint *p);
|
||||
long size();
|
||||
void synth(SampleBuf *out,
|
||||
long writePos,
|
||||
int c,
|
||||
long synthtime,
|
||||
int steps,
|
||||
real fScale0,
|
||||
real fScale1,
|
||||
real mScale);
|
||||
trackpoint *getTrackPoint(long time);
|
||||
bool isStart(long synthtime);
|
||||
bool isEnd(long synthtime);
|
||||
trackpoint *back();
|
||||
|
||||
vector<tpoint*> point;
|
||||
|
||||
unsigned short index;
|
||||
bool bEnd;
|
||||
track *descendant;
|
||||
track *precursor;
|
||||
long tailEnd;
|
||||
long tailStart;
|
||||
long currtime;
|
||||
real rise;
|
||||
real fall;
|
||||
long start;
|
||||
long end;
|
||||
real m_p;
|
||||
real m_pDescendant;
|
||||
int res;
|
||||
sms *owner;
|
||||
|
||||
protected:
|
||||
friend class TrackAllocator;
|
||||
track(track *precursor,sms *owner,int res);
|
||||
~track();
|
||||
enum {
|
||||
trackIndexNone = 0
|
||||
};
|
||||
|
||||
class TrackAllocator {
|
||||
public:
|
||||
TrackAllocator(bool bManageIndex);
|
||||
TrackAllocator(bool bManageIndex, unsigned short maxtrackindex);
|
||||
void init();
|
||||
int size();
|
||||
~TrackAllocator();
|
||||
#define PhShift 5
|
||||
#define WShift 21
|
||||
#define Ph1 65535
|
||||
#define WPI 536870912
|
||||
#define W2PI 1073741824
|
||||
#define W2PIMask 1073741823
|
||||
#define WScale 1.708913188941079e8f
|
||||
#define MScale 4.656683928435187e-10f
|
||||
|
||||
track *getTrack(unsigned short index);
|
||||
track *create(track *precursor,sms *owner, int res, unsigned short index);
|
||||
track *create(track *precursor,sms *owner, int res);
|
||||
void destroy(track *t);
|
||||
enum SynthMode {
|
||||
synthModeOutput = 0,
|
||||
synthModeTrial2,
|
||||
synthModeTrial1
|
||||
};
|
||||
|
||||
class SMS;
|
||||
|
||||
class Track : public SBSMSTrack {
|
||||
public:
|
||||
Track(float h, TrackIndexType index, TrackPoint *p, const TimeType &time, bool bStitch);
|
||||
~Track();
|
||||
|
||||
SBSMSTrackPoint *getSBSMSTrackPoint(const TimeType &time);
|
||||
TrackIndexType getIndex();
|
||||
bool isFirst(const TimeType &synthtime);
|
||||
bool isLast(const TimeType &synthtime);
|
||||
|
||||
protected:
|
||||
void push_back(TrackPoint *p);
|
||||
TrackPoint *back();
|
||||
void endTrack(bool bStitch);
|
||||
TrackPoint *getTrackPoint(const TimeType &time);
|
||||
TimeType size();
|
||||
TrackPoint *updateFPH(const TimeType &time, int mode, int n, float f0, float f1);
|
||||
void updateM(const TimeType &time, int mode);
|
||||
void step(const TimeType &time);
|
||||
void synth(float *out, const TimeType &synthtime, int n, int mode, int c);
|
||||
bool jump(TrackPoint *tp0, TrackPoint *tp1);
|
||||
|
||||
friend class SMS;
|
||||
friend class SynthRenderer;
|
||||
friend class TrackPoint;
|
||||
|
||||
protected:
|
||||
#ifdef MULTITHREADED
|
||||
pthread_mutex_t taMutex;
|
||||
#endif
|
||||
long gIdCount;
|
||||
stack<unsigned short> gTrackIndex;
|
||||
vector<track*> gTrack;
|
||||
bool bManageIndex;
|
||||
|
||||
vector<TrackPoint*> point;
|
||||
float h;
|
||||
float jumpThresh1;
|
||||
float jumpThresh2;
|
||||
TrackIndexType index;
|
||||
TimeType start;
|
||||
TimeType first;
|
||||
TimeType end;
|
||||
TimeType last;
|
||||
bool bEnd;
|
||||
bool bEnded;
|
||||
bool bRender;
|
||||
bool bStitch;
|
||||
bool bSplit;
|
||||
bool bMerge;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,99 +1,170 @@
|
|||
#include <math.h>
|
||||
#include "real.h"
|
||||
#include "utils.h"
|
||||
#include "track.h"
|
||||
#include "trackpoint.h"
|
||||
#include "grain.h"
|
||||
#include "track.h"
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
trackpoint :: trackpoint(trackpoint *tp)
|
||||
void TrackPoint :: destroy()
|
||||
{
|
||||
init();
|
||||
f = tp->f;
|
||||
y = tp->y;
|
||||
y0 = tp->y0;
|
||||
h = tp->h;
|
||||
M = tp->M;
|
||||
ph = tp->ph;
|
||||
owner = tp->owner;
|
||||
refCount--;
|
||||
if(refCount <= 0) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
trackpoint :: ~trackpoint()
|
||||
TrackPoint :: TrackPoint(Slice *slice, float *peak, audio *gx, float *mag, float *mag2, int k, int N, int band)
|
||||
{
|
||||
refCount = 0;
|
||||
for(int d=0;d<3;d++) {
|
||||
if(dup[d]) {
|
||||
dup[d]->dup[2-d] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trackpoint :: trackpoint(grain *g, real x, real y, int N, short M, short h, long time)
|
||||
{
|
||||
init();
|
||||
real k = x;
|
||||
int ki = round2int(k);
|
||||
real kf = ki<k?k-ki:ki-k;
|
||||
|
||||
real norm0 = square(g->x[ki][0]) + square(g->x[ki][1]);
|
||||
real ph0;
|
||||
if(norm0 > 0.0f) {
|
||||
ph0 = atan2(g->x[ki][1],g->x[ki][0]);
|
||||
} else {
|
||||
ph0 = 0.0f;
|
||||
}
|
||||
|
||||
int ki1 = ki<k?ki+1:ki-1;
|
||||
real norm1, ph1;
|
||||
if(ki == N-1) {
|
||||
norm1 = norm0;
|
||||
ph1 = ph0;
|
||||
} else {
|
||||
norm1 = square(g->x[ki1][0]) + square(g->x[ki1][1]);
|
||||
if(norm1 > 0.0f) {
|
||||
ph1 = atan2(g->x[ki1][1],g->x[ki1][0]);
|
||||
} else {
|
||||
ph1 = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
real ifreq = TWOPI*k/(real)N;
|
||||
ph0 = ph0 + (real)ki*PI;
|
||||
ph1 = ph1 + (real)ki1*PI;
|
||||
if(kf < 0.5) {
|
||||
real dp = canon(ph1 - ph0);
|
||||
ph1 = ph0 + dp;
|
||||
} else {
|
||||
real dp = canon(ph0 - ph1);
|
||||
ph0 = ph1 + dp;
|
||||
}
|
||||
real ph = ((1.0f-kf)*ph0 + kf*ph1);
|
||||
|
||||
this->time = time;
|
||||
this->y = y;
|
||||
this->y0 = y;
|
||||
this->M = M;
|
||||
this->h = h;
|
||||
this->f = ifreq;
|
||||
this->ph = canon(ph);
|
||||
}
|
||||
|
||||
trackpoint :: trackpoint()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void trackpoint :: init()
|
||||
{
|
||||
for(int d=0;d<3;d++)
|
||||
dup[d] = NULL;
|
||||
contF = 1e9;
|
||||
cont = NULL;
|
||||
dupcont = NULL;
|
||||
}
|
||||
dupStereo = NULL;
|
||||
bJump = false;
|
||||
y01 = 0.0f;
|
||||
pp = NULL;
|
||||
pn = NULL;
|
||||
bSyncStereo = false;
|
||||
bConnect = false;
|
||||
bConnected = false;
|
||||
bDelete = false;
|
||||
bOwned = false;
|
||||
bMarked = false;
|
||||
bSplit = false;
|
||||
bMerge = false;
|
||||
owner = NULL;
|
||||
this->slice = slice;
|
||||
this->peak = peak;
|
||||
float y0 = mag[k-1];
|
||||
float y1 = mag[k];
|
||||
float y2 = mag[k+1];
|
||||
float d = (y0 + y2 - y1 - y1);
|
||||
x = (d==0.0f?k:k + 0.5f * (y0 - y2) / d);
|
||||
int ki = lrintf(x);
|
||||
int ki1;
|
||||
float kf;
|
||||
if(ki<x) {
|
||||
ki1 = ki + 1;
|
||||
kf = x - ki;
|
||||
} else {
|
||||
ki1 = ki - 1;
|
||||
kf = ki - x;
|
||||
}
|
||||
y = ((1.0f-kf)*mag2[ki] + kf*mag2[ki1]);
|
||||
f = TWOPI*x/(float)(N*(1<<band));
|
||||
float norm0 = square(gx[ki][0]) + square(gx[ki][1]);
|
||||
float ph0;
|
||||
if(norm0 > 0.0f) {
|
||||
ph0 = atan2(gx[ki][1],gx[ki][0]);
|
||||
} else {
|
||||
ph0 = 0.0f;
|
||||
}
|
||||
float ph1;
|
||||
float norm1 = square(gx[ki1][0]) + square(gx[ki1][1]);
|
||||
if(norm1 > 0.0f) {
|
||||
ph1 = atan2(gx[ki1][1],gx[ki1][0]);
|
||||
} else {
|
||||
ph1 = 0.0f;
|
||||
}
|
||||
ph0 += (float)(ki&1)*PI;
|
||||
ph1 += (float)(ki1&1)*PI;
|
||||
if(kf < 0.5f) {
|
||||
ph1 = ph0 + canonPI(ph1 - ph0);
|
||||
} else {
|
||||
ph0 = ph1 + canonPI(ph0 - ph1);
|
||||
}
|
||||
ph = canon2PI((1.0f-kf)*ph0 + kf*ph1);
|
||||
phSynth = ph;
|
||||
}
|
||||
|
||||
TrackPoint :: ~TrackPoint()
|
||||
{
|
||||
for(int d=0;d<3;d++) {
|
||||
if(dup[d]) {
|
||||
m2 = 0.0f;
|
||||
dup[d]->dup[2-d] = NULL;
|
||||
}
|
||||
}
|
||||
m2 = 0;
|
||||
if(slice) slice->remove(this);
|
||||
if(pp && pn) {
|
||||
pp->pn = pn;
|
||||
pn->pp = pp;
|
||||
if(!(owner && owner->bRender)) {
|
||||
if(pp->y * peak[lrintf(pp->x - x)] > pn->y * peak[lrintf(pn->x - x)]) {
|
||||
pp->m2 += m2;
|
||||
pp->xtn2 = xtn2;
|
||||
pn->xtp2 = xtn2;
|
||||
} else {
|
||||
pn->m2 += m2;
|
||||
pp->xtn2 = xtp2;
|
||||
pn->xtp2 = xtp2;
|
||||
}
|
||||
}
|
||||
} else if(pp) {
|
||||
pp->pn = NULL;
|
||||
if(!(owner && owner->bRender)) {
|
||||
if(y01 == 0.0f || y01 * peak[lrintf(x01 - x)] < pp->y * peak[lrintf(pp->x - x)]) {
|
||||
pp->x01 = x01;
|
||||
pp->y01 = y01;
|
||||
pp->m2 += m2;
|
||||
pp->xtn2 = xtn2;
|
||||
}
|
||||
}
|
||||
} else if(pn) {
|
||||
pn->pp = NULL;
|
||||
if(!(owner && owner->bRender)) {
|
||||
if(y01 == 0.0f || y01 * peak[lrintf(x01 - x)] < pn->y * peak[lrintf(pn->x - x)]) {
|
||||
pn->x01 = x01;
|
||||
pn->y01 = y01;
|
||||
pn->m2 += m2;
|
||||
pn->xtp2 = xtp2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float TrackPoint :: getF()
|
||||
{
|
||||
return f;
|
||||
}
|
||||
|
||||
float TrackPoint :: getM()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
float TrackPoint :: getPhase()
|
||||
{
|
||||
return ph;
|
||||
}
|
||||
|
||||
Slice :: Slice(int band, const TimeType &time)
|
||||
{
|
||||
this->band = band;
|
||||
this->time = time;
|
||||
bottom = NULL;
|
||||
top = NULL;
|
||||
}
|
||||
|
||||
void Slice :: remove(TrackPoint *tp)
|
||||
{
|
||||
if(tp == top) {
|
||||
top = top->pp;
|
||||
}
|
||||
if(tp == bottom) {
|
||||
bottom = bottom->pn;
|
||||
}
|
||||
}
|
||||
|
||||
Slice :: ~Slice()
|
||||
{
|
||||
for(TrackPoint *tp = bottom;
|
||||
tp;
|
||||
tp = tp->pn) {
|
||||
tp->slice = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,46 +1,77 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef TRACKPOINT_H
|
||||
#define TRACKPOINT_H
|
||||
|
||||
#include "grain.h"
|
||||
#include "sbsms.h"
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
class track;
|
||||
enum { TrackPointNoCont = 65535 };
|
||||
|
||||
class tpoint {
|
||||
public:
|
||||
tpoint() {}
|
||||
virtual ~tpoint() {}
|
||||
real f;
|
||||
real y;
|
||||
real ph;
|
||||
short h;
|
||||
short M;
|
||||
real y0;
|
||||
class Track;
|
||||
class Slice;
|
||||
|
||||
class TrackPoint : public SBSMSTrackPoint {
|
||||
public:
|
||||
TrackPoint(Slice *slice, float *peak, audio *gx, float *mag, float *mag2, int k, int N, int band);
|
||||
~TrackPoint();
|
||||
void destroy();
|
||||
float getF();
|
||||
float getM();
|
||||
float getPhase();
|
||||
protected:
|
||||
TrackPoint *pp;
|
||||
TrackPoint *pn;
|
||||
TrackPoint *dupcont;
|
||||
TrackPoint *dupStereo;
|
||||
TrackPoint *cont;
|
||||
TrackPoint *dup[3];
|
||||
Track *owner;
|
||||
Slice *slice;
|
||||
float *peak;
|
||||
float x01;
|
||||
float y01;
|
||||
float phSynth;
|
||||
union {
|
||||
float fSynth0;
|
||||
float xtp2;
|
||||
};
|
||||
union {
|
||||
float fSynth1;
|
||||
float xtn2;
|
||||
};
|
||||
int refCount;
|
||||
float f;
|
||||
float x;
|
||||
float y;
|
||||
float ph;
|
||||
float contF;
|
||||
float m;
|
||||
float m2;
|
||||
bool bJump;
|
||||
bool bSyncStereo;
|
||||
bool bConnected;
|
||||
bool bConnect;
|
||||
bool bDelete;
|
||||
bool bOwned;
|
||||
bool bMarked;
|
||||
bool bSplit;
|
||||
bool bMerge;
|
||||
|
||||
friend class Slice;
|
||||
friend class SMS;
|
||||
friend class Track;
|
||||
};
|
||||
|
||||
class trackpoint : public tpoint {
|
||||
public:
|
||||
trackpoint();
|
||||
trackpoint(trackpoint *tp);
|
||||
trackpoint(grain *g, real x, real y, int N, short M, short h, long time);
|
||||
~trackpoint();
|
||||
|
||||
track *owner;
|
||||
long time;
|
||||
|
||||
real contF;
|
||||
bool bConnect;
|
||||
bool bConnected;
|
||||
bool bDelete;
|
||||
|
||||
trackpoint *dupcont;
|
||||
trackpoint *cont;
|
||||
trackpoint *dup[3];
|
||||
|
||||
protected:
|
||||
void init();
|
||||
class Slice {
|
||||
public:
|
||||
Slice(int band, const TimeType &time);
|
||||
~Slice();
|
||||
void remove(TrackPoint *tp);
|
||||
TrackPoint *bottom;
|
||||
TrackPoint *top;
|
||||
int band;
|
||||
TimeType time;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
#include <math.h>
|
||||
#include "utils.h"
|
||||
#include "real.h"
|
||||
|
||||
namespace _sbsms_ {
|
||||
int COSSIZE;
|
||||
real *COSTABLE = NULL;
|
||||
real COSFACTOR;
|
||||
|
||||
int *factor(int n)
|
||||
{
|
||||
int *f = (int*)calloc(ilog2(n)+1,sizeof(int));
|
||||
factor(n,f,0);
|
||||
return f;
|
||||
}
|
||||
|
||||
void factor(int n, int *f, int m)
|
||||
{
|
||||
for(int k=2;k<=n;k++) {
|
||||
if(n%k==0) {
|
||||
f[m++] = k;
|
||||
n /= k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(n>1)
|
||||
factor(n,f,m);
|
||||
}
|
||||
|
||||
void _evenodd2c(audio *eo, audio *even, audio *odd, int N)
|
||||
{
|
||||
for(int k=0;k<N;k++) {
|
||||
eo[k][0] = (even[k][0] - odd[k][1]);
|
||||
eo[k][1] = (even[k][1] + odd[k][0]);
|
||||
}
|
||||
}
|
||||
|
||||
void _c2evenodd(audio *eo, audio *even, audio *odd, int N)
|
||||
{
|
||||
int Nover2 = N/2;
|
||||
for(int k=0;k<=Nover2;k++) {
|
||||
int fk = (k==0)?0:N-k;
|
||||
|
||||
real eok0 = eo[k][0];
|
||||
real eok1 = eo[k][1];
|
||||
real eofk0 = eo[fk][0];
|
||||
real eofk1 = eo[fk][1];
|
||||
|
||||
even[k][0] = 0.5f*(eok0 + eofk0);
|
||||
even[k][1] = 0.5f*(eok1 - eofk1);
|
||||
|
||||
odd[k][0] = 0.5f*(eok1 + eofk1);
|
||||
odd[k][1] = 0.5f*(-eok0 + eofk0);
|
||||
}
|
||||
}
|
||||
|
||||
void cosinit(int size) {
|
||||
COSSIZE = size;
|
||||
COSFACTOR = (real)(COSSIZE-1)/PI;
|
||||
if(COSTABLE) free(COSTABLE);
|
||||
COSTABLE = (real*)malloc(size*sizeof(real));
|
||||
for(int k=0;k<size;k++)
|
||||
COSTABLE[k] = cos((real)k/(real)(COSSIZE-1)*PI);
|
||||
}
|
||||
|
||||
void _c2magphase(audio *g, int N)
|
||||
{
|
||||
for(int k=0;k<N;k++) {
|
||||
real mag = norm(g[k]);
|
||||
real phase = atan2(g[k][1],g[k][0]);
|
||||
g[k][0] = mag;
|
||||
g[k][1] = phase;
|
||||
}
|
||||
}
|
||||
|
||||
void _magphase2c(audio *g, int N)
|
||||
{
|
||||
for(int k=0;k<N;k++) {
|
||||
real mag = g[k][0];
|
||||
real phi = g[k][1];
|
||||
real re = mag * cos(phi);
|
||||
real im = mag * sin(phi);
|
||||
|
||||
g[k][0] = re;
|
||||
g[k][1] = im;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
#ifndef FFTUTILS_H
|
||||
#define FFTUTILS_H
|
||||
// -*- mode: c++ -*-
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include "real.h"
|
||||
#include "config.h"
|
||||
#include "sbsms.h"
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace _sbsms_ {
|
||||
|
||||
|
@ -13,67 +12,56 @@ namespace _sbsms_ {
|
|||
#define PI 3.1415926535897932384626433832795f
|
||||
#define TWOPI 6.28318530717958647692528676655900576f
|
||||
|
||||
extern int COSSIZE;
|
||||
extern real COSFACTOR;
|
||||
extern real *COSTABLE;
|
||||
|
||||
void cosinit(int size);
|
||||
void _evenodd2c(audio *eo, audio *even, audio *odd, int N);
|
||||
void _c2evenodd(audio *eo, audio *even, audio *odd, int N);
|
||||
inline real COS(real x);
|
||||
inline real square(real x);
|
||||
void _c2magphase(audio *g, int N);
|
||||
void _magphase2c(audio *g, int N);
|
||||
inline real canon(real ph);
|
||||
inline real norm(audio x);
|
||||
inline real norm2(audio x);
|
||||
inline real sign(real x);
|
||||
inline real dBApprox(real x);
|
||||
int *factor(int n);
|
||||
void factor(int n, int *f, int m);
|
||||
|
||||
inline int ilog2(int x)
|
||||
inline void c2even(audio *eo, audio *even, int N)
|
||||
{
|
||||
int n = 0;
|
||||
while(x>1) {
|
||||
x>>=1;
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
int Nover2 = N/2;
|
||||
even[0][0] = eo[0][0];
|
||||
even[0][1] = 0.0f;
|
||||
for(int k=1;k<=Nover2;k++) {
|
||||
int Nk = N-k;
|
||||
even[k][0] = 0.5f*(eo[k][0] + eo[Nk][0]);
|
||||
even[k][1] = 0.5f*(eo[k][1] - eo[Nk][1]);
|
||||
}
|
||||
}
|
||||
|
||||
inline real dBApprox(real x)
|
||||
inline void c2odd(audio *eo, audio *odd, int N)
|
||||
{
|
||||
real u = (x-1.0f)/(x+1.0f);
|
||||
real u2 = u*u;
|
||||
return 17.37177927613007f*u*(1.0f + u2*(0.333333333333333f + u2*(0.2f + u2*0.14285714285714f)));
|
||||
int Nover2 = N/2;
|
||||
odd[0][0] = eo[0][1];
|
||||
odd[0][1] = 0.0f;
|
||||
for(int k=1;k<=Nover2;k++) {
|
||||
int Nk = N-k;
|
||||
odd[k][0] = 0.5f*(eo[k][1] + eo[Nk][1]);
|
||||
odd[k][1] = 0.5f*(eo[Nk][0] - eo[k][0]);
|
||||
}
|
||||
}
|
||||
|
||||
inline real canon(real ph)
|
||||
inline float canonPI(float ph)
|
||||
{
|
||||
return ph - TWOPI*(real)round2int(ph*ONEOVERTWOPI);
|
||||
ph -= TWOPI * lrintf(ph * ONEOVERTWOPI);
|
||||
if(ph < -PI) ph += TWOPI;
|
||||
else if(ph >= PI) ph -= TWOPI;
|
||||
return ph;
|
||||
}
|
||||
|
||||
inline real norm2(audio x)
|
||||
inline float canon2PI(float ph)
|
||||
{
|
||||
return square(x[0]) + square(x[1]);
|
||||
ph -= TWOPI * lrintf(ph * ONEOVERTWOPI);
|
||||
if(ph < 0.0f) ph += TWOPI;
|
||||
if(ph >= TWOPI) ph -= TWOPI;
|
||||
return ph;
|
||||
}
|
||||
|
||||
inline real norm(audio x)
|
||||
{
|
||||
return sqrt(norm2(x));
|
||||
}
|
||||
|
||||
inline real COS(real x)
|
||||
{
|
||||
return COSTABLE[round2int(COSFACTOR*fabsf(x))];
|
||||
}
|
||||
|
||||
inline real square(real x)
|
||||
inline float square(float x)
|
||||
{
|
||||
return x*x;
|
||||
}
|
||||
|
||||
inline float norm2(t_fft x)
|
||||
{
|
||||
return square(x[0]) + square(x[1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,7 +6,7 @@ SBSMSEffect.cpp
|
|||
|
||||
Clayton Otey
|
||||
|
||||
This abstract class contains all of the common code for an
|
||||
This class contains all of the common code for an
|
||||
effect that uses SBSMS to do its processing (TimeScale)
|
||||
|
||||
**********************************************************************/
|
||||
|
@ -22,79 +22,90 @@ effect that uses SBSMS to do its processing (TimeScale)
|
|||
#include "../Project.h"
|
||||
#include "TimeWarper.h"
|
||||
|
||||
class resampleBuf
|
||||
enum {
|
||||
SBSMSOutBlockSize = 512
|
||||
};
|
||||
|
||||
class ResampleBuf
|
||||
{
|
||||
public:
|
||||
resampleBuf()
|
||||
ResampleBuf()
|
||||
{
|
||||
processed = 0;
|
||||
buf = NULL;
|
||||
leftBuffer = NULL;
|
||||
rightBuffer = NULL;
|
||||
quality = NULL;
|
||||
iface = NULL;
|
||||
sbsms = NULL;
|
||||
|
||||
sbsmser = NULL;
|
||||
outBuf = NULL;
|
||||
outputLeftBuffer = NULL;
|
||||
outputRightBuffer = NULL;
|
||||
resampler = NULL;
|
||||
SBSMSBuf = NULL;
|
||||
outputLeftTrack = NULL;
|
||||
outputRightTrack = NULL;
|
||||
resampler = NULL;
|
||||
}
|
||||
|
||||
~resampleBuf()
|
||||
~ResampleBuf()
|
||||
{
|
||||
if(buf) free(buf);
|
||||
if(leftBuffer) free(leftBuffer);
|
||||
if(rightBuffer) free(rightBuffer);
|
||||
if(sbsmser) sbsms_destroy(sbsmser);
|
||||
if(outBuf) free(outBuf);
|
||||
if(outputLeftBuffer) free(outputLeftBuffer);
|
||||
if(outputRightBuffer) free(outputRightBuffer);
|
||||
if(SBSMSBuf) free(SBSMSBuf);
|
||||
if(outputLeftTrack) delete outputLeftTrack;
|
||||
if(outputRightTrack) delete outputRightTrack;
|
||||
if(quality) delete quality;
|
||||
if(sbsms) delete sbsms;
|
||||
if(iface) delete iface;
|
||||
if(resampler) delete resampler;
|
||||
}
|
||||
|
||||
bool bPitch;
|
||||
audio *buf;
|
||||
double ratio;
|
||||
sampleCount block;
|
||||
sampleCount processed;
|
||||
sampleCount blockSize;
|
||||
sampleCount SBSMSBlockSize;
|
||||
sampleCount offset;
|
||||
sampleCount end;
|
||||
float *leftBuffer;
|
||||
float *rightBuffer;
|
||||
WaveTrack *leftTrack;
|
||||
WaveTrack *rightTrack;
|
||||
SBSMS *sbsms;
|
||||
SBSMSInterface *iface;
|
||||
audio *SBSMSBuf;
|
||||
|
||||
// Not required by callbacks, but makes for easier cleanup
|
||||
sbsms *sbsmser;
|
||||
audio *outBuf;
|
||||
float *outputLeftBuffer;
|
||||
float *outputRightBuffer;
|
||||
Resampler *resampler;
|
||||
SBSMSQuality *quality;
|
||||
WaveTrack *outputLeftTrack;
|
||||
WaveTrack *outputRightTrack;
|
||||
};
|
||||
|
||||
class SBSMSEffectInterface : public SBSMSInterfaceSliding {
|
||||
public:
|
||||
SBSMSEffectInterface(Resampler *resampler,
|
||||
Slide *rateSlide, Slide *pitchSlide,
|
||||
bool bReferenceInput,
|
||||
long samples, long preSamples,
|
||||
SBSMSQuality *quality)
|
||||
: SBSMSInterfaceSliding(rateSlide,pitchSlide,bReferenceInput,samples,preSamples,quality)
|
||||
{
|
||||
this->resampler = resampler;
|
||||
}
|
||||
virtual ~SBSMSEffectInterface() {}
|
||||
|
||||
long samples(audio *buf, long n) {
|
||||
return resampler->read(buf, n);
|
||||
}
|
||||
|
||||
protected:
|
||||
Resampler *resampler;
|
||||
};
|
||||
|
||||
long samplesCB(audio *chdata, long numFrames, void *userData)
|
||||
{
|
||||
sbsmsInfo *si = (sbsmsInfo*) userData;
|
||||
long n_read = si->rs->read(chdata, numFrames);
|
||||
return n_read;
|
||||
}
|
||||
|
||||
void EffectSBSMS :: setParameters(double rateStart, double rateEnd, double pitchStart, double pitchEnd, bool bPreAnalyze)
|
||||
long resampleCB(void *cb_data, SBSMSFrame *data)
|
||||
{
|
||||
this->rateStart = rateStart;
|
||||
this->rateEnd = rateEnd;
|
||||
this->pitchStart = pitchStart;
|
||||
this->pitchEnd = pitchEnd;
|
||||
this->bPreAnalyze = bPreAnalyze;
|
||||
}
|
||||
|
||||
bool EffectSBSMS :: bInit = FALSE;
|
||||
|
||||
long resampleCB(void *cb_data, sbsms_resample_frame *data)
|
||||
{
|
||||
resampleBuf *r = (resampleBuf*) cb_data;
|
||||
ResampleBuf *r = (ResampleBuf*) cb_data;
|
||||
|
||||
long blockSize = r->leftTrack->GetBestBlockSize(r->offset);
|
||||
|
||||
|
@ -112,29 +123,75 @@ long resampleCB(void *cb_data, sbsms_resample_frame *data)
|
|||
r->buf[i][1] = r->rightBuffer[i];
|
||||
}
|
||||
|
||||
r->offset += blockSize;
|
||||
data->in = r->buf;
|
||||
data->buf = r->buf;
|
||||
data->size = blockSize;
|
||||
data->ratio0 = r->ratio;
|
||||
data->ratio1 = r->ratio;
|
||||
|
||||
if(r->bPitch) {
|
||||
float t0 = (float)(r->processed) / r->iface->getSamplesToInput();
|
||||
float t1 = (float)(r->processed + blockSize) / r->iface->getSamplesToInput();
|
||||
data->ratio0 = r->iface->getStretch(t0);
|
||||
data->ratio1 = r->iface->getStretch(t1);
|
||||
} else {
|
||||
data->ratio0 = r->ratio;
|
||||
data->ratio1 = r->ratio;
|
||||
}
|
||||
r->processed += blockSize;
|
||||
r->offset += blockSize;
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
long postResampleCB(void *cb_data, SBSMSFrame *data)
|
||||
{
|
||||
ResampleBuf *r = (ResampleBuf*) cb_data;
|
||||
long sampleCount = r->sbsms->read(r->iface, r->SBSMSBuf, r->SBSMSBlockSize);
|
||||
data->buf = r->SBSMSBuf;
|
||||
data->size = sampleCount;
|
||||
data->ratio0 = 1.0 / r->ratio;
|
||||
data->ratio1 = 1.0 / r->ratio;
|
||||
return sampleCount;
|
||||
}
|
||||
|
||||
void EffectSBSMS :: setParameters(double rateStart, double rateEnd, double pitchStart, double pitchEnd,
|
||||
SlideType rateSlideType, SlideType pitchSlideType,
|
||||
bool bLinkRatePitch, bool bRateReferenceInput, bool bPitchReferenceInput)
|
||||
{
|
||||
this->rateStart = rateStart;
|
||||
this->rateEnd = rateEnd;
|
||||
this->pitchStart = pitchStart;
|
||||
this->pitchEnd = pitchEnd;
|
||||
this->bLinkRatePitch = bLinkRatePitch;
|
||||
this->rateSlideType = rateSlideType;
|
||||
this->pitchSlideType = pitchSlideType;
|
||||
this->bRateReferenceInput = bRateReferenceInput;
|
||||
this->bPitchReferenceInput = bPitchReferenceInput;
|
||||
}
|
||||
|
||||
TimeWarper *createTimeWarper(double t0, double t1, double duration,
|
||||
double rateStart, double rateEnd, SlideType rateSlideType)
|
||||
{
|
||||
TimeWarper *warper = NULL;
|
||||
if (rateStart == rateEnd || rateSlideType == SlideConstant) {
|
||||
warper = new LinearTimeWarper(t0, t0, t1, t0+duration);
|
||||
} else if(rateSlideType == SlideLinearInputRate) {
|
||||
warper = new LinearInputRateTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
} else if(rateSlideType == SlideLinearOutputRate) {
|
||||
warper = new LinearOutputRateTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
} else if(rateSlideType == SlideLinearInputStretch) {
|
||||
warper = new LinearInputStretchTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
} else if(rateSlideType == SlideLinearOutputStretch) {
|
||||
warper = new LinearOutputStretchTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
} else if(rateSlideType == SlideGeometricInput) {
|
||||
warper = new GeometricInputTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
} else if(rateSlideType == SlideGeometricOutput) {
|
||||
warper = new GeometricOutputTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
}
|
||||
return warper;
|
||||
}
|
||||
|
||||
// Labels inside the affected region are moved to match the audio; labels after
|
||||
// it are shifted along appropriately.
|
||||
bool EffectSBSMS::ProcessLabelTrack(Track *t)
|
||||
{
|
||||
TimeWarper *warper = NULL;
|
||||
if (rateStart == rateEnd)
|
||||
{
|
||||
warper = new LinearTimeWarper(mT0, mT0,
|
||||
mT1, mT0+(mT1-mT0)*mTotalStretch);
|
||||
} else
|
||||
{
|
||||
warper = new LogarithmicTimeWarper(mT0, mT1,
|
||||
rateStart, rateEnd);
|
||||
}
|
||||
TimeWarper *warper = createTimeWarper(mT0,mT1,(mT1-mT0)*mTotalStretch,rateStart,rateEnd,rateSlideType);
|
||||
SetTimeWarper(new RegionTimeWarper(mT0, mT1, warper));
|
||||
LabelTrack *lt = (LabelTrack*)t;
|
||||
if (lt == NULL) return false;
|
||||
|
@ -144,16 +201,10 @@ bool EffectSBSMS::ProcessLabelTrack(Track *t)
|
|||
|
||||
bool EffectSBSMS::Process()
|
||||
{
|
||||
if(!bInit) {
|
||||
sbsms_init(8192);
|
||||
bInit = TRUE;
|
||||
}
|
||||
|
||||
bool bGoodResult = true;
|
||||
|
||||
//Iterate over each track
|
||||
// Track::All is needed because this effect needs to introduce
|
||||
// silence in the group tracks to keep sync-lock.
|
||||
//Track::All is needed because this effect needs to introduce silence in the group tracks to keep sync
|
||||
this->CopyInputTracks(Track::All); // Set up mOutputTracks.
|
||||
TrackListIterator iter(mOutputTracks);
|
||||
Track* t;
|
||||
|
@ -161,13 +212,11 @@ bool EffectSBSMS::Process()
|
|||
|
||||
double maxDuration = 0.0;
|
||||
|
||||
if(rateStart == rateEnd)
|
||||
mTotalStretch = 1.0/rateStart;
|
||||
else
|
||||
mTotalStretch = 1.0/(rateEnd-rateStart)*log(rateEnd/rateStart);
|
||||
|
||||
// Must sync if selection length will change
|
||||
bool mustSync = (mTotalStretch != 1.0);
|
||||
bool mustSync = (rateStart != rateEnd);
|
||||
Slide rateSlide(rateSlideType,rateStart,rateEnd);
|
||||
Slide pitchSlide(pitchSlideType,pitchStart,pitchEnd);
|
||||
mTotalStretch = rateSlide.getTotalStretch();
|
||||
|
||||
t = iter.First();
|
||||
while (t != NULL) {
|
||||
|
@ -218,131 +267,116 @@ bool EffectSBSMS::Process()
|
|||
|
||||
mCurTrackNum++; // Increment for rightTrack, too.
|
||||
}
|
||||
|
||||
sampleCount trackStart = leftTrack->TimeToLongSamples(leftTrack->GetStartTime());
|
||||
sampleCount trackEnd = leftTrack->TimeToLongSamples(leftTrack->GetEndTime());
|
||||
|
||||
// SBSMS has a fixed sample rate - we just convert to its sample rate and then convert back
|
||||
float srIn = leftTrack->GetRate();
|
||||
// mchinen: srSBMS doesn't do the right thing when it was set to fixed 44100. This seems to fix it.
|
||||
float srSBSMS = leftTrack->GetRate();
|
||||
|
||||
float srTrack = leftTrack->GetRate();
|
||||
float srProcess = bLinkRatePitch?srTrack:44100.0;
|
||||
|
||||
// the resampler needs a callback to supply its samples
|
||||
resampleBuf rb;
|
||||
ResampleBuf rb;
|
||||
sampleCount maxBlockSize = leftTrack->GetMaxBlockSize();
|
||||
rb.block = maxBlockSize;
|
||||
rb.buf = (audio*)calloc(rb.block,sizeof(audio));
|
||||
rb.blockSize = maxBlockSize;
|
||||
rb.buf = (audio*)calloc(rb.blockSize,sizeof(audio));
|
||||
rb.leftTrack = leftTrack;
|
||||
rb.rightTrack = rightTrack?rightTrack:leftTrack;
|
||||
rb.leftBuffer = (float*)calloc(maxBlockSize,sizeof(float));
|
||||
rb.rightBuffer = (float*)calloc(maxBlockSize,sizeof(float));
|
||||
rb.offset = start;
|
||||
rb.end = trackEnd;
|
||||
rb.ratio = srSBSMS/srIn;
|
||||
rb.resampler = new Resampler(resampleCB, &rb);
|
||||
|
||||
// Samples in selection
|
||||
sampleCount samplesIn = end-start;
|
||||
|
||||
// Samples for SBSMS to process after resampling
|
||||
sampleCount samplesToProcess = (sampleCount) ((real)samplesIn*(srSBSMS/srIn));
|
||||
sampleCount samplesToProcess = (sampleCount) ((float)samplesIn*(srProcess/srTrack));
|
||||
|
||||
SlideType outSlideType;
|
||||
SBSMSResampleCB outResampleCB;
|
||||
|
||||
sampleCount processPresamples = 0;
|
||||
sampleCount trackPresamples = 0;
|
||||
|
||||
if(bLinkRatePitch) {
|
||||
rb.bPitch = true;
|
||||
outSlideType = rateSlideType;
|
||||
outResampleCB = resampleCB;
|
||||
rb.offset = start;
|
||||
rb.end = end;
|
||||
rb.iface = new SBSMSInterfaceSliding(&rateSlide,&pitchSlide,
|
||||
bPitchReferenceInput,
|
||||
samplesToProcess,0,
|
||||
NULL);
|
||||
} else {
|
||||
rb.bPitch = false;
|
||||
outSlideType = (srProcess==srTrack?SlideIdentity:SlideConstant);
|
||||
outResampleCB = postResampleCB;
|
||||
rb.ratio = srProcess/srTrack;
|
||||
rb.quality = new SBSMSQuality(&SBSMSQualityStandard);
|
||||
rb.resampler = new Resampler(resampleCB, &rb, srProcess==srTrack?SlideIdentity:SlideConstant);
|
||||
rb.sbsms = new SBSMS(rightTrack?2:1,rb.quality,true);
|
||||
rb.SBSMSBlockSize = rb.sbsms->getInputFrameSize();
|
||||
rb.SBSMSBuf = (audio*)calloc(rb.SBSMSBlockSize,sizeof(audio));
|
||||
|
||||
processPresamples = wxMin(rb.quality->getMaxPresamples(),
|
||||
(long)((float)(start-trackStart)*(srProcess/srTrack)));
|
||||
trackPresamples = wxMin(start-trackStart,
|
||||
(long)((float)(processPresamples)*(srTrack/srProcess)));
|
||||
rb.offset = start - trackPresamples;
|
||||
rb.end = trackEnd;
|
||||
rb.iface = new SBSMSEffectInterface(rb.resampler,
|
||||
&rateSlide,&pitchSlide,
|
||||
bPitchReferenceInput,
|
||||
samplesToProcess,processPresamples,
|
||||
rb.quality);
|
||||
}
|
||||
|
||||
Resampler resampler(outResampleCB,&rb,outSlideType);
|
||||
|
||||
audio outBuf[SBSMSOutBlockSize];
|
||||
float outBufLeft[2*SBSMSOutBlockSize];
|
||||
float outBufRight[2*SBSMSOutBlockSize];
|
||||
|
||||
// Samples in output after SBSMS
|
||||
sampleCount samplesToOutput = rb.iface->getSamplesToOutput();
|
||||
|
||||
// Samples in output after resampling back
|
||||
sampleCount samplesToGenerate = (sampleCount) ((real)samplesToProcess * mTotalStretch);
|
||||
sampleCount samplesOut = (sampleCount) ((real)samplesIn * mTotalStretch);
|
||||
sampleCount samplesOut = (sampleCount) ((float)samplesToOutput * (srTrack/srProcess));
|
||||
|
||||
// Duration in track time
|
||||
double duration = (mCurT1-mCurT0) * mTotalStretch;
|
||||
|
||||
if(duration > maxDuration)
|
||||
maxDuration = duration;
|
||||
|
||||
TimeWarper *warper = NULL;
|
||||
if (rateStart == rateEnd)
|
||||
{
|
||||
warper = new LinearTimeWarper(mCurT0, mCurT0,
|
||||
mCurT1, mCurT0+maxDuration);
|
||||
} else
|
||||
{
|
||||
warper = new LogarithmicTimeWarper(mCurT0, mCurT1,
|
||||
rateStart, rateEnd);
|
||||
}
|
||||
TimeWarper *warper = createTimeWarper(mCurT0,mCurT1,maxDuration,rateStart,rateEnd,rateSlideType);
|
||||
SetTimeWarper(warper);
|
||||
|
||||
sbsmsInfo si;
|
||||
si.rs = rb.resampler;
|
||||
si.samplesToProcess = samplesToProcess;
|
||||
si.samplesToGenerate = samplesToGenerate;
|
||||
si.rate0 = rateStart;
|
||||
si.rate1 = rateEnd;
|
||||
si.pitch0 = pitchStart;
|
||||
si.pitch1 = pitchEnd;
|
||||
|
||||
sbsms_quality quality = sbsms_quality_fast;
|
||||
rb.sbsmser = sbsms_create(&samplesCB,&rateCBLinear,&pitchCBLinear,rightTrack?2:1,&quality,bPreAnalyze,true);
|
||||
|
||||
|
||||
rb.outputLeftTrack = mFactory->NewWaveTrack(leftTrack->GetSampleFormat(),
|
||||
leftTrack->GetRate());
|
||||
if(rightTrack)
|
||||
rb.outputRightTrack = mFactory->NewWaveTrack(rightTrack->GetSampleFormat(),
|
||||
rightTrack->GetRate());
|
||||
|
||||
|
||||
sampleCount blockSize = quality.maxoutframesize;
|
||||
rb.outBuf = (audio*)calloc(blockSize,sizeof(audio));
|
||||
rb.outputLeftBuffer = (float*)calloc(blockSize*2,sizeof(float));
|
||||
if(rightTrack)
|
||||
rb.outputRightBuffer = (float*)calloc(blockSize*2,sizeof(float));
|
||||
|
||||
long pos = 0;
|
||||
long outputCount = -1;
|
||||
|
||||
// pre analysis
|
||||
real fracPre = 0.0f;
|
||||
if(bPreAnalyze) {
|
||||
fracPre = 0.05f;
|
||||
resampleBuf rbPre;
|
||||
rbPre.block = maxBlockSize;
|
||||
rbPre.buf = (audio*)calloc(rb.block,sizeof(audio));
|
||||
rbPre.leftTrack = leftTrack;
|
||||
rbPre.rightTrack = rightTrack?rightTrack:leftTrack;
|
||||
rbPre.leftBuffer = (float*)calloc(maxBlockSize,sizeof(float));
|
||||
rbPre.rightBuffer = (float*)calloc(maxBlockSize,sizeof(float));
|
||||
rbPre.offset = start;
|
||||
rbPre.end = end;
|
||||
rbPre.ratio = srSBSMS/srIn;
|
||||
rbPre.resampler = new Resampler(resampleCB, &rbPre);
|
||||
si.rs = rbPre.resampler;
|
||||
|
||||
long pos = 0;
|
||||
long lastPos = 0;
|
||||
long ret = 0;
|
||||
while(lastPos<samplesToProcess) {
|
||||
ret = sbsms_pre_analyze(&samplesCB,&si,rb.sbsmser);
|
||||
lastPos = pos;
|
||||
pos += ret;
|
||||
real completion = (real)lastPos/(real)samplesToProcess;
|
||||
if (TrackProgress(0,fracPre*completion))
|
||||
return false;
|
||||
}
|
||||
sbsms_pre_analyze_complete(rb.sbsmser);
|
||||
sbsms_reset(rb.sbsmser);
|
||||
si.rs = rb.resampler;
|
||||
}
|
||||
|
||||
|
||||
// process
|
||||
while(pos<samplesOut && outputCount) {
|
||||
outputCount = sbsms_read_frame(rb.outBuf, &si, rb.sbsmser, NULL, NULL);
|
||||
if(pos+outputCount>samplesOut) {
|
||||
outputCount = samplesOut - pos;
|
||||
long frames;
|
||||
if(pos+SBSMSOutBlockSize>samplesOut) {
|
||||
frames = samplesOut - pos;
|
||||
} else {
|
||||
frames = SBSMSOutBlockSize;
|
||||
}
|
||||
|
||||
outputCount = resampler.read(outBuf,frames);
|
||||
for(int i = 0; i < outputCount; i++) {
|
||||
rb.outputLeftBuffer[i] = rb.outBuf[i][0];
|
||||
outBufLeft[i] = outBuf[i][0];
|
||||
if(rightTrack)
|
||||
rb.outputRightBuffer[i] = rb.outBuf[i][1];
|
||||
outBufRight[i] = outBuf[i][1];
|
||||
}
|
||||
pos += outputCount;
|
||||
rb.outputLeftTrack->Append((samplePtr)rb.outputLeftBuffer, floatSample, outputCount);
|
||||
rb.outputLeftTrack->Append((samplePtr)outBufLeft, floatSample, outputCount);
|
||||
if(rightTrack)
|
||||
rb.outputRightTrack->Append((samplePtr)rb.outputRightBuffer, floatSample, outputCount);
|
||||
rb.outputRightTrack->Append((samplePtr)outBufRight, floatSample, outputCount);
|
||||
|
||||
double frac = (double)pos/(double)samplesOut;
|
||||
int nWhichTrack = mCurTrackNum;
|
||||
|
@ -356,7 +390,7 @@ bool EffectSBSMS::Process()
|
|||
frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once.
|
||||
}
|
||||
}
|
||||
if (TrackProgress(nWhichTrack, fracPre + (1.0-fracPre)*frac))
|
||||
if (TrackProgress(nWhichTrack, frac))
|
||||
return false;
|
||||
}
|
||||
rb.outputLeftTrack->Flush();
|
||||
|
|
|
@ -21,22 +21,23 @@
|
|||
#include "sbsms.h"
|
||||
using namespace _sbsms_;
|
||||
|
||||
class WaveTrack;
|
||||
|
||||
class EffectSBSMS : public Effect {
|
||||
public:
|
||||
static bool bInit;
|
||||
virtual bool Process();
|
||||
void setParameters(double rateStart, double rateEnd, double pitchStart, double pitchEnd, bool bPreAnalyze);
|
||||
void setParameters(double rateStart, double rateEnd, double pitchStart, double pitchEnd,
|
||||
SlideType rateSlideType, SlideType pitchSlideType,
|
||||
bool bLinkRatePitch, bool bRateReferenceInput, bool bPitchReferenceInput);
|
||||
|
||||
private:
|
||||
bool ProcessLabelTrack(Track *track);
|
||||
double rateStart, rateEnd, pitchStart, pitchEnd;
|
||||
bool bPreAnalyze;
|
||||
bool bLinkRatePitch, bRateReferenceInput, bPitchReferenceInput;
|
||||
SlideType rateSlideType;
|
||||
SlideType pitchSlideType;
|
||||
int mCurTrackNum;
|
||||
double mCurT0;
|
||||
double mCurT1;
|
||||
real mTotalStretch;
|
||||
float mTotalStretch;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include "../ShuttleGui.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
|
@ -38,7 +40,7 @@
|
|||
// EffectTimeScale
|
||||
//
|
||||
|
||||
EffectTimeScale::EffectTimeScale()
|
||||
EffectTimeScale::EffectTimeScale()
|
||||
{
|
||||
m_RatePercentChangeStart = 0;
|
||||
m_RatePercentChangeEnd = 0;
|
||||
|
@ -46,7 +48,13 @@ EffectTimeScale::EffectTimeScale()
|
|||
m_PitchHalfStepsEnd = 0;
|
||||
m_PitchPercentChangeStart = 0;
|
||||
m_PitchPercentChangeEnd = 0;
|
||||
m_PreAnalyze = false;
|
||||
m_RateSlideType = 0;
|
||||
m_PitchSlideType = 0;
|
||||
m_RateSlideReference = 0;
|
||||
m_PitchSlideReference = 0;
|
||||
m_RateLinkInitialFinal = false;
|
||||
m_PitchLinkInitialFinal = false;
|
||||
m_LinkRatePitch = false;
|
||||
}
|
||||
|
||||
wxString EffectTimeScale::GetEffectDescription() {
|
||||
|
@ -68,7 +76,13 @@ bool EffectTimeScale::PromptUser()
|
|||
dlog.m_PitchHalfStepsEnd = m_PitchHalfStepsEnd;
|
||||
dlog.m_PitchPercentChangeStart = m_PitchPercentChangeStart;
|
||||
dlog.m_PitchPercentChangeEnd = m_PitchPercentChangeEnd;
|
||||
dlog.m_PreAnalyze = m_PreAnalyze;
|
||||
dlog.m_LinkRatePitch = m_LinkRatePitch;
|
||||
dlog.m_RateSlideType = m_RateSlideType;
|
||||
dlog.m_PitchSlideType = m_PitchSlideType;
|
||||
dlog.m_RateSlideReference = m_RateSlideReference;
|
||||
dlog.m_PitchSlideReference = m_PitchSlideReference;
|
||||
dlog.m_RateLinkInitialFinal = m_RateLinkInitialFinal;
|
||||
dlog.m_PitchLinkInitialFinal = m_PitchLinkInitialFinal;
|
||||
|
||||
// Don't need to call TransferDataToWindow, although other
|
||||
// Audacity dialogs (from which I derived this one) do it, because
|
||||
|
@ -86,7 +100,13 @@ bool EffectTimeScale::PromptUser()
|
|||
m_PitchHalfStepsEnd = dlog.m_PitchHalfStepsEnd;
|
||||
m_PitchPercentChangeStart = dlog.m_PitchPercentChangeStart;
|
||||
m_PitchPercentChangeEnd = dlog.m_PitchPercentChangeEnd;
|
||||
m_PreAnalyze = dlog.m_PreAnalyze;
|
||||
m_LinkRatePitch = dlog.m_LinkRatePitch;
|
||||
m_RateSlideType = dlog.m_RateSlideType;
|
||||
m_PitchSlideType = dlog.m_PitchSlideType;
|
||||
m_RateSlideReference = dlog.m_RateSlideReference;
|
||||
m_PitchSlideReference = dlog.m_PitchSlideReference;
|
||||
m_RateLinkInitialFinal = dlog.m_RateLinkInitialFinal;
|
||||
m_PitchLinkInitialFinal = dlog.m_PitchLinkInitialFinal;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -99,14 +119,15 @@ bool EffectTimeScale::TransferParameters( Shuttle & shuttle )
|
|||
shuttle.TransferDouble(wxT("PitchHalfStepsEnd"),m_PitchHalfStepsEnd,0.0);
|
||||
shuttle.TransferDouble(wxT("PitchPercentChangeStart"),m_PitchPercentChangeStart,0.0);
|
||||
shuttle.TransferDouble(wxT("PitchPercentChangeEnd"),m_PitchPercentChangeEnd,0.0);
|
||||
shuttle.TransferBool(wxT("PreAnalyze"),m_PreAnalyze,false);
|
||||
return true;
|
||||
}
|
||||
shuttle.TransferBool(wxT("LinkRatePitch"),m_LinkRatePitch,false);
|
||||
shuttle.TransferInt(wxT("RateSlideType"),m_RateSlideType,0);
|
||||
shuttle.TransferInt(wxT("PitchSlideType"),m_PitchSlideType,0);
|
||||
shuttle.TransferInt(wxT("RateSlideReference"),m_RateSlideReference,0);
|
||||
shuttle.TransferInt(wxT("PitchSlideReference"),m_PitchSlideReference,0);
|
||||
shuttle.TransferBool(wxT("RateLinkInitialFinal"),m_RateLinkInitialFinal,false);
|
||||
shuttle.TransferBool(wxT("PitchLinkInitialFinal"),m_PitchLinkInitialFinal,false);
|
||||
|
||||
inline double InvertedPercentChangeToRatio(double percentChange)
|
||||
{
|
||||
//mchinen hack: invert the ratio so it works with the sbsms bug which requires the reciprocal number.
|
||||
return 1.0/(1.0 + percentChange / 100.0);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline double PercentChangeToRatio(double percentChange)
|
||||
|
@ -121,19 +142,50 @@ inline double HalfStepsToPercentChange(double halfSteps)
|
|||
|
||||
inline double PercentChangeToHalfSteps(double percentChange)
|
||||
{
|
||||
// mchinen: hack: take the negative of this so the correct value is displayed
|
||||
// (see the InvertedPercentChangeToRatio hack for why this is needed)
|
||||
return 17.312340490667560888319096172023 * log(PercentChangeToRatio(percentChange));
|
||||
}
|
||||
|
||||
bool EffectTimeScale::Process()
|
||||
{
|
||||
// The pitch part of sbsms is backwards, so use an inverted function
|
||||
double pitchStart = InvertedPercentChangeToRatio(m_PitchPercentChangeStart);
|
||||
double pitchEnd = InvertedPercentChangeToRatio(m_PitchPercentChangeEnd);
|
||||
double pitchStart = PercentChangeToRatio(m_PitchPercentChangeStart);
|
||||
double pitchEnd = PercentChangeToRatio(m_PitchPercentChangeEnd);
|
||||
double rateStart = PercentChangeToRatio(m_RatePercentChangeStart);
|
||||
double rateEnd = PercentChangeToRatio(m_RatePercentChangeEnd);
|
||||
this->EffectSBSMS::setParameters(rateStart,rateEnd,pitchStart,pitchEnd,m_PreAnalyze);
|
||||
SlideType rateSlideType;
|
||||
SlideType pitchSlideType;
|
||||
if(rateStart == rateEnd || m_RateLinkInitialFinal) {
|
||||
rateSlideType = SlideConstant;
|
||||
} else if(m_RateSlideType == 0) {
|
||||
if(m_RateSlideReference == 1) {
|
||||
rateSlideType = SlideLinearInputRate;
|
||||
} else {
|
||||
rateSlideType = SlideLinearOutputRate;
|
||||
}
|
||||
} else if(m_RateSlideType == 1) {
|
||||
if(m_RateSlideReference == 1) {
|
||||
rateSlideType = SlideLinearInputStretch;
|
||||
} else {
|
||||
rateSlideType = SlideLinearOutputStretch;
|
||||
}
|
||||
} else if(m_RateSlideType == 2) {
|
||||
if(m_RateSlideReference == 1) {
|
||||
rateSlideType = SlideGeometricInput;
|
||||
} else {
|
||||
rateSlideType = SlideGeometricOutput;
|
||||
}
|
||||
}
|
||||
if(pitchStart == pitchEnd || m_PitchLinkInitialFinal) {
|
||||
pitchSlideType = SlideConstant;
|
||||
} else if(m_PitchSlideType == 0) {
|
||||
pitchSlideType = SlideLinearInputRate;
|
||||
} else if(m_PitchSlideType == 1) {
|
||||
pitchSlideType = SlideLinearInputStretch;
|
||||
} else if(m_PitchSlideType == 2) {
|
||||
pitchSlideType = SlideGeometricInput;
|
||||
}
|
||||
bool rateReferenceInput = (m_RateSlideReference == 1);
|
||||
bool pitchReferenceInput = (m_PitchSlideReference == 1);
|
||||
this->EffectSBSMS::setParameters(rateStart,rateEnd,pitchStart,pitchEnd,rateSlideType,pitchSlideType,m_LinkRatePitch,rateReferenceInput,pitchReferenceInput);
|
||||
return this->EffectSBSMS::Process();
|
||||
}
|
||||
|
||||
|
@ -141,16 +193,15 @@ bool EffectTimeScale::Process()
|
|||
// TimeScaleDialog
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define RATE_PERCENTCHANGE_MAX_SLIDER 150
|
||||
#define RATE_PERCENTCHANGE_MIN_SLIDER -75
|
||||
#define RATE_PERCENTCHANGE_MAX_TEXT 500
|
||||
#define RATE_PERCENTCHANGE_MAX_SLIDER 150
|
||||
#define RATE_PERCENTCHANGE_MIN_TEXT -90
|
||||
#define RATE_PERCENTCHANGE_MAX_TEXT 500
|
||||
#define RATE_PERCENTCHANGE_DEFAULT 0
|
||||
#define PITCH_HALFSTEPS_MIN_TEXT -12
|
||||
#define PITCH_HALFSTEPS_MAX_TEXT 12
|
||||
#define PITCH_PERCENTCHANGE_MIN_TEXT -50
|
||||
#define PITCH_PERCENTCHANGE_MAX_TEXT 100
|
||||
|
||||
#define PITCH_HALFSTEPS_MIN_TEXT -24
|
||||
#define PITCH_HALFSTEPS_MAX_TEXT 24
|
||||
#define PITCH_PERCENTCHANGE_MIN_TEXT -75
|
||||
#define PITCH_PERCENTCHANGE_MAX_TEXT 300
|
||||
|
||||
#define ID_TEXT_RATE_PERCENTCHANGE_START 10001
|
||||
#define ID_TEXT_RATE_PERCENTCHANGE_END 10002
|
||||
|
@ -160,7 +211,13 @@ bool EffectTimeScale::Process()
|
|||
#define ID_TEXT_PITCH_PERCENTCHANGE_END 10006
|
||||
#define ID_SLIDER_RATE_PERCENTCHANGE_START 10007
|
||||
#define ID_SLIDER_RATE_PERCENTCHANGE_END 10008
|
||||
#define ID_CHECKBOX_PREANALYZE 10009
|
||||
#define ID_CHECKBOX_LINKRATEPITCH 10010
|
||||
#define ID_CHOICE_RATE_SLIDETYPE 10011
|
||||
#define ID_CHOICE_PITCH_SLIDETYPE 10012
|
||||
#define ID_CHOICE_RATE_SLIDEREFERENCE 10013
|
||||
#define ID_CHOICE_PITCH_SLIDEREFERENCE 10014
|
||||
#define ID_CHECKBOX_RATE_LINKINITIALFINAL 10015
|
||||
#define ID_CHECKBOX_PITCH_LINKINITIALFINAL 10016
|
||||
|
||||
// event table for TimeScaleDialog
|
||||
|
||||
|
@ -173,13 +230,31 @@ BEGIN_EVENT_TABLE(TimeScaleDialog, EffectDialog)
|
|||
EVT_TEXT(ID_TEXT_PITCH_PERCENTCHANGE_END, TimeScaleDialog::OnText_PitchPercentChangeEnd)
|
||||
EVT_SLIDER(ID_SLIDER_RATE_PERCENTCHANGE_START, TimeScaleDialog::OnSlider_RatePercentChangeStart)
|
||||
EVT_SLIDER(ID_SLIDER_RATE_PERCENTCHANGE_END, TimeScaleDialog::OnSlider_RatePercentChangeEnd)
|
||||
EVT_CHECKBOX(ID_CHECKBOX_PREANALYZE, TimeScaleDialog::OnCheckBox_PreAnalyze)
|
||||
EVT_CHECKBOX(ID_CHECKBOX_LINKRATEPITCH, TimeScaleDialog::OnCheckBox_LinkRatePitch)
|
||||
EVT_CHOICE(ID_CHOICE_RATE_SLIDETYPE, TimeScaleDialog::OnChoice_RateSlideType)
|
||||
EVT_CHOICE(ID_CHOICE_PITCH_SLIDETYPE, TimeScaleDialog::OnChoice_PitchSlideType)
|
||||
EVT_CHOICE(ID_CHOICE_RATE_SLIDEREFERENCE, TimeScaleDialog::OnChoice_RateSlideReference)
|
||||
EVT_CHOICE(ID_CHOICE_PITCH_SLIDEREFERENCE, TimeScaleDialog::OnChoice_PitchSlideReference)
|
||||
EVT_CHECKBOX(ID_CHECKBOX_RATE_LINKINITIALFINAL, TimeScaleDialog::OnCheckBox_RateLinkInitialFinal)
|
||||
EVT_CHECKBOX(ID_CHECKBOX_PITCH_LINKINITIALFINAL, TimeScaleDialog::OnCheckBox_PitchLinkInitialFinal)
|
||||
EVT_BUTTON(ID_EFFECT_PREVIEW, TimeScaleDialog::OnPreview)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
TimeScaleDialog::TimeScaleDialog(EffectTimeScale *effect, wxWindow *parent)
|
||||
: EffectDialog(parent, _("Time Scale"), INSERT_EFFECT),
|
||||
: EffectDialog(parent, _("Time Scale"), PROCESS_EFFECT),
|
||||
mEffect(effect)
|
||||
{
|
||||
rateSlideTypes.Add(_("Linear Rate"));
|
||||
rateSlideTypes.Add(_("Linear Stretch"));
|
||||
rateSlideTypes.Add(_("Geometric"));
|
||||
pitchSlideTypes.Add(_("Linear Rate"));
|
||||
pitchSlideTypes.Add(_("Linear Stretch"));
|
||||
pitchSlideTypes.Add(_("Geometric"));
|
||||
rateSlideReferences.Add(_("Output"));
|
||||
rateSlideReferences.Add(_("Input"));
|
||||
pitchSlideReferences.Add(_("Output"));
|
||||
pitchSlideReferences.Add(_("Input"));
|
||||
|
||||
m_bLoopDetect = false;
|
||||
|
||||
// NULL out these control members because there are some cases where the
|
||||
|
@ -194,7 +269,13 @@ TimeScaleDialog::TimeScaleDialog(EffectTimeScale *effect, wxWindow *parent)
|
|||
m_pTextCtrl_PitchPercentChangeEnd = NULL;
|
||||
m_pTextCtrl_PitchHalfStepsStart = NULL;
|
||||
m_pTextCtrl_PitchHalfStepsEnd = NULL;
|
||||
m_pCheckBox_PreAnalyze = NULL;
|
||||
m_pCheckBox_LinkRatePitch = NULL;
|
||||
m_pChoice_RateSlideType = NULL;
|
||||
m_pChoice_PitchSlideType = NULL;
|
||||
m_pChoice_RateSlideReference = NULL;
|
||||
m_pChoice_PitchSlideReference = NULL;
|
||||
m_pCheckBox_RateLinkInitialFinal = NULL;
|
||||
m_pCheckBox_PitchLinkInitialFinal = NULL;
|
||||
|
||||
// effect parameters
|
||||
m_RatePercentChangeStart = 0;
|
||||
|
@ -203,17 +284,27 @@ TimeScaleDialog::TimeScaleDialog(EffectTimeScale *effect, wxWindow *parent)
|
|||
m_PitchPercentChangeEnd = 0;
|
||||
m_PitchHalfStepsStart = 0;
|
||||
m_PitchHalfStepsEnd = 0;
|
||||
m_PreAnalyze = false;
|
||||
m_LinkRatePitch = false;
|
||||
m_RateSlideType = 0;
|
||||
m_PitchSlideType = 0;
|
||||
m_RateSlideReference = 0;
|
||||
m_PitchSlideReference = 0;
|
||||
m_RateLinkInitialFinal = false;
|
||||
m_PitchLinkInitialFinal = false;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnPreview(wxCommandEvent & event)
|
||||
{
|
||||
mEffect->Preview();
|
||||
}
|
||||
|
||||
void TimeScaleDialog::PopulateOrExchange(ShuttleGui & S)
|
||||
{
|
||||
|
||||
wxTextValidator nullvld(wxFILTER_INCLUDE_CHAR_LIST);
|
||||
wxTextValidator numvld(wxFILTER_NUMERIC);
|
||||
|
||||
|
||||
S.SetBorder(10);
|
||||
S.StartHorizontalLay(wxCENTER, false);
|
||||
{
|
||||
|
@ -223,94 +314,130 @@ void TimeScaleDialog::PopulateOrExchange(ShuttleGui & S)
|
|||
}
|
||||
S.EndHorizontalLay();
|
||||
S.SetBorder(5);
|
||||
|
||||
S.StartMultiColumn(2, 0);
|
||||
// Rate Start
|
||||
S.StartStatic(_("Initial Tempo Change (%)"));
|
||||
|
||||
S.StartStatic(_("Tempo Change"));
|
||||
{
|
||||
S.StartMultiColumn(1, wxCENTER);
|
||||
S.StartHorizontalLay(wxEXPAND);
|
||||
{
|
||||
m_pTextCtrl_RatePercentChangeStart = S.Id(ID_TEXT_RATE_PERCENTCHANGE_START)
|
||||
.AddTextBox(wxT(""), wxT(""), 12);
|
||||
m_pTextCtrl_RatePercentChangeStart->SetValidator(numvld);
|
||||
S.StartVerticalLay(wxCENTER);
|
||||
{
|
||||
S.StartHorizontalLay(wxCENTER,0);
|
||||
{
|
||||
m_pTextCtrl_RatePercentChangeStart = S.Id(ID_TEXT_RATE_PERCENTCHANGE_START)
|
||||
.AddTextBox(_("Initial (%)"), wxT(""), 12);
|
||||
m_pTextCtrl_RatePercentChangeStart->SetValidator(numvld);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(wxEXPAND,0);
|
||||
{
|
||||
S.SetStyle(wxSL_HORIZONTAL);
|
||||
m_pSlider_RatePercentChangeStart = S.Id(ID_SLIDER_RATE_PERCENTCHANGE_START)
|
||||
.AddSlider(wxT(""), (int)RATE_PERCENTCHANGE_DEFAULT, (int)RATE_PERCENTCHANGE_MAX_SLIDER, (int)RATE_PERCENTCHANGE_MIN_SLIDER);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndVerticalLay();
|
||||
|
||||
S.StartVerticalLay(wxCENTER);
|
||||
{
|
||||
S.StartHorizontalLay(wxCENTER,0);
|
||||
{
|
||||
m_pTextCtrl_RatePercentChangeEnd = S.Id(ID_TEXT_RATE_PERCENTCHANGE_END)
|
||||
.AddTextBox(_("Final (%)"), wxT(""), 12);
|
||||
m_pTextCtrl_RatePercentChangeEnd->SetValidator(numvld);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(wxEXPAND,0);
|
||||
{
|
||||
S.SetStyle(wxSL_HORIZONTAL);
|
||||
m_pSlider_RatePercentChangeEnd = S.Id(ID_SLIDER_RATE_PERCENTCHANGE_END)
|
||||
.AddSlider(wxT(""), (int)RATE_PERCENTCHANGE_DEFAULT, (int)RATE_PERCENTCHANGE_MAX_SLIDER, (int)RATE_PERCENTCHANGE_MIN_SLIDER);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndVerticalLay();
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
S.StartHorizontalLay(wxEXPAND,0);
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(0,0);
|
||||
{
|
||||
S.SetStyle(wxSL_HORIZONTAL);
|
||||
m_pSlider_RatePercentChangeStart = S.Id(ID_SLIDER_RATE_PERCENTCHANGE_START)
|
||||
.AddSlider(wxT(""), (int)RATE_PERCENTCHANGE_DEFAULT, (int)RATE_PERCENTCHANGE_MAX_SLIDER, (int)RATE_PERCENTCHANGE_MIN_SLIDER);
|
||||
m_pChoice_RateSlideType = S.Id(ID_CHOICE_RATE_SLIDETYPE)
|
||||
.AddChoice(_("Slide Type"),_("Linear Rate"),&rateSlideTypes);
|
||||
m_pChoice_RateSlideType->SetSelection(0);
|
||||
m_pChoice_RateSlideType->SetSizeHints(-1,-1);
|
||||
m_pChoice_RateSlideReference = S.Id(ID_CHOICE_RATE_SLIDEREFERENCE)
|
||||
.AddChoice(_("Reference"),_("Output"),&rateSlideReferences);
|
||||
m_pChoice_RateSlideReference->SetSelection(0);
|
||||
m_pChoice_RateSlideReference->SetSizeHints(-1,-1);
|
||||
m_pCheckBox_RateLinkInitialFinal = S.Id(ID_CHECKBOX_RATE_LINKINITIALFINAL)
|
||||
.AddCheckBox(_("Link Initial/Final"), wxT("false"));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndStatic();
|
||||
|
||||
S.StartStatic(_("Final Tempo Change (%)"));
|
||||
// Pitch Change
|
||||
S.StartStatic(_("Pitch Shift"));
|
||||
{
|
||||
S.StartMultiColumn(1, wxCENTER);
|
||||
S.StartMultiColumn(2, wxCENTER);
|
||||
{
|
||||
m_pTextCtrl_RatePercentChangeEnd = S.Id(ID_TEXT_RATE_PERCENTCHANGE_END)
|
||||
.AddTextBox(wxT(""), wxT(""), 12);
|
||||
m_pTextCtrl_RatePercentChangeEnd->SetValidator(numvld);
|
||||
S.StartMultiColumn(2, wxCENTER);
|
||||
{
|
||||
m_pTextCtrl_PitchHalfStepsStart = S.Id(ID_TEXT_PITCH_HALFSTEPS_START)
|
||||
.AddTextBox(_("Initial (semitones) [-24 to 24]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchHalfStepsStart->SetValidator(numvld);
|
||||
m_pTextCtrl_PitchPercentChangeStart = S.Id(ID_TEXT_PITCH_PERCENTCHANGE_START)
|
||||
.AddTextBox(_("Initial (%) [-75 to 300]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchPercentChangeStart->SetValidator(numvld);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
|
||||
S.StartMultiColumn(2, wxCENTER);
|
||||
{
|
||||
m_pTextCtrl_PitchHalfStepsEnd = S.Id(ID_TEXT_PITCH_HALFSTEPS_END)
|
||||
.AddTextBox(_("Final (semitones) [-24 to 24]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchHalfStepsEnd->SetValidator(numvld);
|
||||
|
||||
m_pTextCtrl_PitchPercentChangeEnd = S.Id(ID_TEXT_PITCH_PERCENTCHANGE_END)
|
||||
.AddTextBox(_("Final (%) [-75 to 300]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchPercentChangeEnd->SetValidator(numvld);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
S.StartHorizontalLay(wxEXPAND,0);
|
||||
{
|
||||
S.SetStyle(wxSL_HORIZONTAL);
|
||||
m_pSlider_RatePercentChangeEnd = S.Id(ID_SLIDER_RATE_PERCENTCHANGE_END)
|
||||
.AddSlider(wxT(""), (int)RATE_PERCENTCHANGE_DEFAULT, (int)RATE_PERCENTCHANGE_MAX_SLIDER, (int)RATE_PERCENTCHANGE_MIN_SLIDER);
|
||||
|
||||
S.StartHorizontalLay(0,0);
|
||||
{
|
||||
m_pChoice_PitchSlideType = S.Id(ID_CHOICE_PITCH_SLIDETYPE)
|
||||
.AddChoice(_("Slide Type"),_("Linear"),&pitchSlideTypes);
|
||||
m_pChoice_PitchSlideType->SetSelection(0);
|
||||
m_pChoice_PitchSlideType->SetSizeHints(-1,-1);
|
||||
m_pChoice_PitchSlideReference = S.Id(ID_CHOICE_PITCH_SLIDEREFERENCE)
|
||||
.AddChoice(_("Reference"),_("Output"),&pitchSlideReferences);
|
||||
m_pChoice_PitchSlideReference->SetSelection(0);
|
||||
m_pChoice_PitchSlideReference->SetSizeHints(-1,-1);
|
||||
m_pCheckBox_PitchLinkInitialFinal = S.Id(ID_CHECKBOX_PITCH_LINKINITIALFINAL)
|
||||
.AddCheckBox(_("Link Initial/Final"), wxT("false"));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndStatic();
|
||||
|
||||
// Pitch Start
|
||||
S.StartStatic(_("Initial Pitch Shift"));
|
||||
{
|
||||
S.StartMultiColumn(2, wxCENTER);
|
||||
{
|
||||
m_pTextCtrl_PitchHalfStepsStart = S.Id(ID_TEXT_PITCH_HALFSTEPS_START)
|
||||
.AddTextBox(_("(semitones) [-12 to 12]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchHalfStepsStart->SetValidator(numvld);
|
||||
|
||||
m_pTextCtrl_PitchPercentChangeStart = S.Id(ID_TEXT_PITCH_PERCENTCHANGE_START)
|
||||
.AddTextBox(_("(%) [-50 to 100]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchPercentChangeStart->SetValidator(numvld);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
S.EndStatic();
|
||||
|
||||
// Pitch End
|
||||
S.StartStatic(_("Final Pitch Shift"));
|
||||
{
|
||||
S.StartMultiColumn(2, wxCENTER);
|
||||
{
|
||||
m_pTextCtrl_PitchHalfStepsEnd = S.Id(ID_TEXT_PITCH_HALFSTEPS_END)
|
||||
.AddTextBox(_("(semitones) [-12 to 12]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchHalfStepsEnd->SetValidator(numvld);
|
||||
|
||||
m_pTextCtrl_PitchPercentChangeEnd = S.Id(ID_TEXT_PITCH_PERCENTCHANGE_END)
|
||||
.AddTextBox(_("(%) [-50 to 100]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchPercentChangeEnd->SetValidator(numvld);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
S.EndStatic();
|
||||
S.EndMultiColumn();
|
||||
|
||||
S.StartStatic(_("Options"));
|
||||
{
|
||||
S.StartHorizontalLay(wxEXPAND);
|
||||
{
|
||||
S.SetStyle(wxSL_HORIZONTAL);
|
||||
m_pCheckBox_PreAnalyze = S.Id(ID_CHECKBOX_PREANALYZE)
|
||||
.AddCheckBox(wxT("Dynamic Transient Sharpening"), wxT("Dynamic Transient Sharpening"));
|
||||
m_pCheckBox_LinkRatePitch = S.Id(ID_CHECKBOX_LINKRATEPITCH)
|
||||
.AddCheckBox(_("Link Rate/Pitch (Resample)"), wxT("false"));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndStatic();
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -326,7 +453,13 @@ bool TimeScaleDialog::TransferDataToWindow()
|
|||
this->Update_Text_PitchHalfStepsEnd();
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_CheckBox_PreAnalyze();
|
||||
this->Update_CheckBox_LinkRatePitch();
|
||||
this->Update_Choice_RateSlideType();
|
||||
this->Update_Choice_PitchSlideType();
|
||||
this->Update_Choice_RateSlideReference();
|
||||
this->Update_Choice_PitchSlideReference();
|
||||
this->Update_CheckBox_RateLinkInitialFinal();
|
||||
this->Update_CheckBox_PitchLinkInitialFinal();
|
||||
|
||||
m_bLoopDetect = false;
|
||||
|
||||
|
@ -379,8 +512,32 @@ bool TimeScaleDialog::TransferDataFromWindow()
|
|||
m_PitchPercentChangeEnd = newValue;
|
||||
}
|
||||
|
||||
if(m_pCheckBox_PreAnalyze) {
|
||||
m_PreAnalyze = m_pCheckBox_PreAnalyze->GetValue();
|
||||
if(m_pCheckBox_LinkRatePitch) {
|
||||
m_LinkRatePitch = m_pCheckBox_LinkRatePitch->GetValue();
|
||||
}
|
||||
|
||||
if(m_pChoice_RateSlideType) {
|
||||
m_RateSlideType = m_pChoice_RateSlideType->GetSelection();
|
||||
}
|
||||
|
||||
if(m_pChoice_PitchSlideType) {
|
||||
m_PitchSlideType = m_pChoice_PitchSlideType->GetSelection();
|
||||
}
|
||||
|
||||
if(m_pChoice_RateSlideReference) {
|
||||
m_RateSlideReference = m_pChoice_RateSlideReference->GetSelection();
|
||||
}
|
||||
|
||||
if(m_pChoice_PitchSlideReference) {
|
||||
m_PitchSlideReference = m_pChoice_PitchSlideReference->GetSelection();
|
||||
}
|
||||
|
||||
if(m_pCheckBox_RateLinkInitialFinal) {
|
||||
m_RateLinkInitialFinal = m_pCheckBox_RateLinkInitialFinal->GetValue();
|
||||
}
|
||||
|
||||
if(m_pCheckBox_PitchLinkInitialFinal) {
|
||||
m_PitchLinkInitialFinal = m_pCheckBox_PitchLinkInitialFinal->GetValue();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -395,17 +552,18 @@ bool TimeScaleDialog::CheckParameters()
|
|||
(m_RatePercentChangeEnd >= RATE_PERCENTCHANGE_MIN_TEXT &&
|
||||
m_RatePercentChangeEnd <= RATE_PERCENTCHANGE_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchHalfStepsStart >= PITCH_HALFSTEPS_MIN_TEXT &&
|
||||
m_PitchHalfStepsStart <= PITCH_HALFSTEPS_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchHalfStepsEnd >= PITCH_HALFSTEPS_MIN_TEXT &&
|
||||
m_PitchHalfStepsEnd <= PITCH_HALFSTEPS_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchPercentChangeStart >= PITCH_PERCENTCHANGE_MIN_TEXT &&
|
||||
m_PitchPercentChangeStart <= PITCH_PERCENTCHANGE_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchPercentChangeEnd >= PITCH_PERCENTCHANGE_MIN_TEXT &&
|
||||
m_PitchPercentChangeEnd <= PITCH_PERCENTCHANGE_MAX_TEXT);
|
||||
(m_LinkRatePitch ||
|
||||
((m_PitchHalfStepsStart >= PITCH_HALFSTEPS_MIN_TEXT &&
|
||||
m_PitchHalfStepsStart <= PITCH_HALFSTEPS_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchHalfStepsEnd >= PITCH_HALFSTEPS_MIN_TEXT &&
|
||||
m_PitchHalfStepsEnd <= PITCH_HALFSTEPS_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchPercentChangeStart >= PITCH_PERCENTCHANGE_MIN_TEXT &&
|
||||
m_PitchPercentChangeStart <= PITCH_PERCENTCHANGE_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchPercentChangeEnd >= PITCH_PERCENTCHANGE_MIN_TEXT &&
|
||||
m_PitchPercentChangeEnd <= PITCH_PERCENTCHANGE_MAX_TEXT)));
|
||||
}
|
||||
|
||||
// handler implementations for TimeScaleDialog
|
||||
|
@ -423,6 +581,23 @@ void TimeScaleDialog::OnText_RatePercentChangeStart(wxCommandEvent & event)
|
|||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchPercentChangeStart = m_RatePercentChangeStart;
|
||||
m_PitchHalfStepsStart = PercentChangeToHalfSteps(m_PitchPercentChangeStart);
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeEnd = m_RatePercentChangeStart;
|
||||
m_PitchHalfStepsEnd = m_PitchHalfStepsStart;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
}
|
||||
}
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeEnd = m_RatePercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
|
@ -442,6 +617,23 @@ void TimeScaleDialog::OnText_RatePercentChangeEnd(wxCommandEvent & event)
|
|||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchPercentChangeEnd = m_RatePercentChangeEnd;
|
||||
m_PitchHalfStepsEnd = PercentChangeToHalfSteps(m_PitchPercentChangeEnd);
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeStart = m_RatePercentChangeEnd;
|
||||
m_PitchHalfStepsStart = m_PitchHalfStepsEnd;
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
}
|
||||
}
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeStart = m_RatePercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
|
@ -458,7 +650,26 @@ void TimeScaleDialog::OnSlider_RatePercentChangeStart(wxCommandEvent & event)
|
|||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchPercentChangeStart = m_RatePercentChangeStart;
|
||||
m_PitchHalfStepsStart = PercentChangeToHalfSteps(m_PitchPercentChangeStart);
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeEnd = m_RatePercentChangeStart;
|
||||
m_PitchHalfStepsEnd = m_PitchHalfStepsStart;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
}
|
||||
}
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeEnd = m_RatePercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -472,7 +683,26 @@ void TimeScaleDialog::OnSlider_RatePercentChangeEnd(wxCommandEvent & event)
|
|||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchPercentChangeEnd = m_RatePercentChangeEnd;
|
||||
m_PitchHalfStepsEnd = PercentChangeToHalfSteps(m_PitchPercentChangeEnd);
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeStart = m_RatePercentChangeEnd;
|
||||
m_PitchHalfStepsStart = m_PitchHalfStepsEnd;
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
}
|
||||
}
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeStart = m_RatePercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,6 +720,22 @@ void TimeScaleDialog::OnText_PitchHalfStepsStart(wxCommandEvent & event)
|
|||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RatePercentChangeStart = m_PitchPercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeEnd = m_PitchPercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
}
|
||||
}
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeEnd = m_PitchPercentChangeStart;
|
||||
m_PitchHalfStepsEnd = m_PitchHalfStepsStart;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
|
@ -510,6 +756,22 @@ void TimeScaleDialog::OnText_PitchHalfStepsEnd(wxCommandEvent & event)
|
|||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RatePercentChangeEnd = m_PitchPercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeStart = m_PitchPercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
}
|
||||
}
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeStart = m_PitchPercentChangeEnd;
|
||||
m_PitchHalfStepsStart = m_PitchHalfStepsEnd;
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
|
@ -527,11 +789,27 @@ void TimeScaleDialog::OnText_PitchPercentChangeStart(wxCommandEvent & event)
|
|||
str.ToDouble(&newValue);
|
||||
m_PitchPercentChangeStart = newValue;
|
||||
m_PitchHalfStepsStart = PercentChangeToHalfSteps(newValue);
|
||||
|
||||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RatePercentChangeStart = m_PitchPercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_RatePercentChangeEnd = m_PitchPercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
}
|
||||
}
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeEnd = m_PitchPercentChangeStart;
|
||||
m_PitchHalfStepsEnd = m_PitchHalfStepsStart;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
}
|
||||
}
|
||||
|
@ -550,16 +828,156 @@ void TimeScaleDialog::OnText_PitchPercentChangeEnd(wxCommandEvent & event)
|
|||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RatePercentChangeEnd = m_PitchPercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_RatePercentChangeStart = m_PitchPercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
}
|
||||
}
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeStart = m_PitchPercentChangeEnd;
|
||||
m_PitchHalfStepsStart = m_PitchHalfStepsEnd;
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnCheckBox_PreAnalyze(wxCommandEvent & event)
|
||||
void TimeScaleDialog::OnCheckBox_LinkRatePitch(wxCommandEvent & event)
|
||||
{
|
||||
if (m_pCheckBox_PreAnalyze) {
|
||||
m_PreAnalyze = m_pCheckBox_PreAnalyze->GetValue();
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pCheckBox_LinkRatePitch) {
|
||||
m_LinkRatePitch = m_pCheckBox_LinkRatePitch->GetValue();
|
||||
|
||||
if(m_LinkRatePitch) {
|
||||
m_bLoopDetect = true;
|
||||
m_RatePercentChangeStart = m_PitchPercentChangeStart;
|
||||
m_RatePercentChangeEnd = m_PitchPercentChangeEnd;
|
||||
m_RateSlideType = m_PitchSlideType;
|
||||
m_RateSlideReference = m_PitchSlideReference;
|
||||
m_RateLinkInitialFinal = m_PitchLinkInitialFinal;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
this->Update_Choice_RateSlideType();
|
||||
this->Update_Choice_RateSlideReference();
|
||||
this->Update_CheckBox_RateLinkInitialFinal();
|
||||
m_bLoopDetect = false;
|
||||
} else {
|
||||
}
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnCheckBox_RateLinkInitialFinal(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pCheckBox_RateLinkInitialFinal) {
|
||||
m_RateLinkInitialFinal = m_pCheckBox_RateLinkInitialFinal->GetValue();
|
||||
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_bLoopDetect = true;
|
||||
m_RatePercentChangeEnd = m_RatePercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnCheckBox_PitchLinkInitialFinal(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pCheckBox_PitchLinkInitialFinal) {
|
||||
m_PitchLinkInitialFinal = m_pCheckBox_PitchLinkInitialFinal->GetValue();
|
||||
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_bLoopDetect = true;
|
||||
m_PitchPercentChangeEnd = m_PitchPercentChangeStart;
|
||||
m_PitchHalfStepsEnd = m_PitchHalfStepsStart;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnChoice_RateSlideType(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pChoice_RateSlideType) {
|
||||
m_RateSlideType = m_pChoice_RateSlideType->GetSelection();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchSlideType = m_RateSlideType;
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Choice_PitchSlideType();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnChoice_PitchSlideType(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pChoice_PitchSlideType) {
|
||||
m_PitchSlideType = m_pChoice_PitchSlideType->GetSelection();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RateSlideType = m_PitchSlideType;
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Choice_RateSlideType();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnChoice_RateSlideReference(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pChoice_RateSlideReference) {
|
||||
m_RateSlideReference = m_pChoice_RateSlideReference->GetSelection();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchSlideReference = m_RateSlideReference;
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Choice_PitchSlideReference();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnChoice_PitchSlideReference(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pChoice_PitchSlideReference) {
|
||||
m_PitchSlideReference = m_pChoice_PitchSlideReference->GetSelection();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RateSlideReference = m_PitchSlideReference;
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Choice_RateSlideReference();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -631,10 +1049,52 @@ void TimeScaleDialog::Update_Text_PitchPercentChangeEnd()
|
|||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_CheckBox_PreAnalyze()
|
||||
void TimeScaleDialog::Update_CheckBox_LinkRatePitch()
|
||||
{
|
||||
if (m_pCheckBox_PreAnalyze) {
|
||||
m_pCheckBox_PreAnalyze->SetValue(m_PreAnalyze);
|
||||
if (m_pCheckBox_LinkRatePitch) {
|
||||
m_pCheckBox_LinkRatePitch->SetValue(m_LinkRatePitch);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_CheckBox_RateLinkInitialFinal()
|
||||
{
|
||||
if (m_pCheckBox_RateLinkInitialFinal) {
|
||||
m_pCheckBox_RateLinkInitialFinal->SetValue(m_RateLinkInitialFinal);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_CheckBox_PitchLinkInitialFinal()
|
||||
{
|
||||
if (m_pCheckBox_PitchLinkInitialFinal) {
|
||||
m_pCheckBox_PitchLinkInitialFinal->SetValue(m_PitchLinkInitialFinal);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_Choice_RateSlideType()
|
||||
{
|
||||
if (m_pChoice_RateSlideType) {
|
||||
m_pChoice_RateSlideType->SetSelection(m_RateSlideType);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_Choice_PitchSlideType()
|
||||
{
|
||||
if (m_pChoice_PitchSlideType) {
|
||||
m_pChoice_PitchSlideType->SetSelection(m_PitchSlideType);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_Choice_RateSlideReference()
|
||||
{
|
||||
if (m_pChoice_RateSlideReference) {
|
||||
m_pChoice_RateSlideReference->SetSelection(m_RateSlideReference);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_Choice_PitchSlideReference()
|
||||
{
|
||||
if (m_pChoice_PitchSlideReference) {
|
||||
m_pChoice_PitchSlideReference->SetSelection(m_PitchSlideReference);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,13 @@
|
|||
#include <wx/intl.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/choice.h>
|
||||
|
||||
class wxString;
|
||||
class wxArrayString;
|
||||
class wxTextCtrl;
|
||||
class wxCheckBox;
|
||||
class wxChoice;
|
||||
|
||||
class EffectTimeScale : public EffectSBSMS {
|
||||
|
||||
|
@ -63,7 +67,13 @@ class EffectTimeScale : public EffectSBSMS {
|
|||
double m_PitchHalfStepsEnd;
|
||||
double m_PitchPercentChangeStart;
|
||||
double m_PitchPercentChangeEnd;
|
||||
bool m_PreAnalyze;
|
||||
int m_RateSlideType;
|
||||
int m_PitchSlideType;
|
||||
int m_RateSlideReference;
|
||||
int m_PitchSlideReference;
|
||||
bool m_LinkRatePitch;
|
||||
bool m_RateLinkInitialFinal;
|
||||
bool m_PitchLinkInitialFinal;
|
||||
|
||||
friend class TimeScaleDialog;
|
||||
};
|
||||
|
@ -74,61 +84,92 @@ class EffectTimeScale : public EffectSBSMS {
|
|||
|
||||
class TimeScaleDialog:public EffectDialog {
|
||||
public:
|
||||
TimeScaleDialog(EffectTimeScale * effect,
|
||||
wxWindow * parent);
|
||||
|
||||
void PopulateOrExchange(ShuttleGui & S);
|
||||
bool TransferDataToWindow();
|
||||
bool TransferDataFromWindow();
|
||||
|
||||
TimeScaleDialog(EffectTimeScale * effect,
|
||||
wxWindow * parent);
|
||||
|
||||
void PopulateOrExchange(ShuttleGui & S);
|
||||
bool TransferDataToWindow();
|
||||
bool TransferDataFromWindow();
|
||||
|
||||
private:
|
||||
// handlers
|
||||
void OnText_RatePercentChangeStart(wxCommandEvent & event);
|
||||
void OnText_RatePercentChangeEnd(wxCommandEvent & event);
|
||||
void OnText_PitchPercentChangeStart(wxCommandEvent & event);
|
||||
void OnText_PitchPercentChangeEnd(wxCommandEvent & event);
|
||||
void OnText_PitchHalfStepsStart(wxCommandEvent & event);
|
||||
void OnText_PitchHalfStepsEnd(wxCommandEvent & event);
|
||||
void OnSlider_RatePercentChangeStart(wxCommandEvent & event);
|
||||
void OnSlider_RatePercentChangeEnd(wxCommandEvent & event);
|
||||
void OnCheckBox_PreAnalyze(wxCommandEvent & event);
|
||||
|
||||
// helper fns
|
||||
bool CheckParameters();
|
||||
void Update_Text_RatePercentChangeStart();
|
||||
void Update_Text_RatePercentChangeEnd();
|
||||
void Update_Text_PitchPercentChangeStart();
|
||||
void Update_Text_PitchPercentChangeEnd();
|
||||
void Update_Text_PitchHalfStepsStart();
|
||||
void Update_Text_PitchHalfStepsEnd();
|
||||
void Update_Slider_RatePercentChangeStart();
|
||||
void Update_Slider_RatePercentChangeEnd();
|
||||
void Update_CheckBox_PreAnalyze();
|
||||
|
||||
// handlers
|
||||
void OnText_RatePercentChangeStart(wxCommandEvent & event);
|
||||
void OnText_RatePercentChangeEnd(wxCommandEvent & event);
|
||||
void OnText_PitchPercentChangeStart(wxCommandEvent & event);
|
||||
void OnText_PitchPercentChangeEnd(wxCommandEvent & event);
|
||||
void OnText_PitchHalfStepsStart(wxCommandEvent & event);
|
||||
void OnText_PitchHalfStepsEnd(wxCommandEvent & event);
|
||||
void OnSlider_RatePercentChangeStart(wxCommandEvent & event);
|
||||
void OnSlider_RatePercentChangeEnd(wxCommandEvent & event);
|
||||
void OnCheckBox_LinkRatePitch(wxCommandEvent & event);
|
||||
void OnChoice_RateSlideType(wxCommandEvent & event);
|
||||
void OnChoice_PitchSlideType(wxCommandEvent & event);
|
||||
void OnChoice_RateSlideReference(wxCommandEvent & event);
|
||||
void OnChoice_PitchSlideReference(wxCommandEvent & event);
|
||||
void OnCheckBox_RateLinkInitialFinal(wxCommandEvent & event);
|
||||
void OnCheckBox_PitchLinkInitialFinal(wxCommandEvent & event);
|
||||
void OnPreview(wxCommandEvent & event);
|
||||
|
||||
// helper fns
|
||||
bool CheckParameters();
|
||||
void Update_Text_RatePercentChangeStart();
|
||||
void Update_Text_RatePercentChangeEnd();
|
||||
void Update_Text_PitchPercentChangeStart();
|
||||
void Update_Text_PitchPercentChangeEnd();
|
||||
void Update_Text_PitchHalfStepsStart();
|
||||
void Update_Text_PitchHalfStepsEnd();
|
||||
void Update_Slider_RatePercentChangeStart();
|
||||
void Update_Slider_RatePercentChangeEnd();
|
||||
void Update_CheckBox_LinkRatePitch();
|
||||
void Update_Choice_RateSlideType();
|
||||
void Update_Choice_PitchSlideType();
|
||||
void Update_Choice_RateSlideReference();
|
||||
void Update_Choice_PitchSlideReference();
|
||||
void Update_CheckBox_RateLinkInitialFinal();
|
||||
void Update_CheckBox_PitchLinkInitialFinal();
|
||||
|
||||
private:
|
||||
EffectTimeScale *mEffect;
|
||||
bool m_bLoopDetect;
|
||||
|
||||
// controls
|
||||
wxTextCtrl *m_pTextCtrl_RatePercentChangeStart;
|
||||
wxTextCtrl *m_pTextCtrl_RatePercentChangeEnd;
|
||||
wxSlider *m_pSlider_RatePercentChangeStart;
|
||||
wxSlider *m_pSlider_RatePercentChangeEnd;
|
||||
wxTextCtrl *m_pTextCtrl_PitchHalfStepsStart;
|
||||
wxTextCtrl *m_pTextCtrl_PitchHalfStepsEnd;
|
||||
wxTextCtrl *m_pTextCtrl_PitchPercentChangeStart;
|
||||
wxTextCtrl *m_pTextCtrl_PitchPercentChangeEnd;
|
||||
wxCheckBox *m_pCheckBox_PreAnalyze;
|
||||
|
||||
public:
|
||||
EffectTimeScale *mEffect;
|
||||
bool m_bLoopDetect;
|
||||
|
||||
wxArrayString rateSlideTypes;
|
||||
wxArrayString pitchSlideTypes;
|
||||
wxArrayString rateSlideReferences;
|
||||
wxArrayString pitchSlideReferences;
|
||||
|
||||
// controls
|
||||
wxTextCtrl *m_pTextCtrl_RatePercentChangeStart;
|
||||
wxTextCtrl *m_pTextCtrl_RatePercentChangeEnd;
|
||||
wxSlider *m_pSlider_RatePercentChangeStart;
|
||||
wxSlider *m_pSlider_RatePercentChangeEnd;
|
||||
wxTextCtrl *m_pTextCtrl_PitchHalfStepsStart;
|
||||
wxTextCtrl *m_pTextCtrl_PitchHalfStepsEnd;
|
||||
wxTextCtrl *m_pTextCtrl_PitchPercentChangeStart;
|
||||
wxTextCtrl *m_pTextCtrl_PitchPercentChangeEnd;
|
||||
wxCheckBox *m_pCheckBox_LinkRatePitch;
|
||||
wxChoice *m_pChoice_RateSlideType;
|
||||
wxChoice *m_pChoice_PitchSlideType;
|
||||
wxChoice *m_pChoice_RateSlideReference;
|
||||
wxChoice *m_pChoice_PitchSlideReference;
|
||||
wxCheckBox *m_pCheckBox_RateLinkInitialFinal;
|
||||
wxCheckBox *m_pCheckBox_PitchLinkInitialFinal;
|
||||
|
||||
double m_RatePercentChangeStart;
|
||||
double m_RatePercentChangeEnd;
|
||||
double m_PitchHalfStepsStart;
|
||||
double m_PitchHalfStepsEnd;
|
||||
double m_PitchPercentChangeStart;
|
||||
double m_PitchPercentChangeEnd;
|
||||
bool m_PreAnalyze;
|
||||
bool m_LinkRatePitch;
|
||||
int m_RateSlideType;
|
||||
int m_PitchSlideType;
|
||||
int m_RateSlideReference;
|
||||
int m_PitchSlideReference;
|
||||
bool m_RateLinkInitialFinal;
|
||||
bool m_PitchLinkInitialFinal;
|
||||
|
||||
friend class EffectTimeScale;
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
\file TimeWarper.cpp
|
||||
\brief Contains definitions for IdentityTimeWarper, ShiftTimeWarper,
|
||||
LinearTimeWarper, LogarithmicTimeWarper classes
|
||||
LinearTimeWarper, LogarithmicTimeWarper, QuadraticTimeWarper,
|
||||
Geometric TimeWarper classes
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
|
@ -33,14 +34,14 @@ double LinearTimeWarper::Warp(double originalTime) const
|
|||
return originalTime*mScale + mShift;
|
||||
}
|
||||
|
||||
double LogarithmicTimeWarper::Warp(double originalTime) const
|
||||
double LinearInputRateTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double rate = mRateWarper.Warp(originalTime);
|
||||
return mTStart + mScale*log(rate/mRStart);
|
||||
}
|
||||
|
||||
LogarithmicTimeWarper::LogarithmicTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
LinearInputRateTimeWarper::LinearInputRateTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mRateWarper(tStart, rStart, tEnd, rEnd), mRStart(rStart),
|
||||
mTStart(tStart), mScale((tEnd-tStart)/(rEnd-rStart))
|
||||
{
|
||||
|
@ -48,6 +49,91 @@ LogarithmicTimeWarper::LogarithmicTimeWarper(double tStart, double tEnd,
|
|||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
double LinearOutputRateTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double scaledTime = mTimeWarper.Warp(originalTime);
|
||||
return mTStart + mScale*(sqrt(mC1 + scaledTime * mC2) - mRStart);
|
||||
}
|
||||
|
||||
LinearOutputRateTimeWarper::LinearOutputRateTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mTimeWarper(tStart, 0.0, tEnd, 1.0),
|
||||
mRStart(rStart), mTStart(tStart),
|
||||
mScale(2.0*(tEnd-tStart)/(rEnd*rEnd-rStart*rStart)),
|
||||
mC1(rStart*rStart), mC2(rEnd*rEnd-rStart*rStart)
|
||||
{
|
||||
wxASSERT(rStart != rEnd);
|
||||
wxASSERT(rStart > 0.0);
|
||||
wxASSERT(rEnd > 0.0);
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
double LinearInputStretchTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double scaledTime = mTimeWarper.Warp(originalTime);
|
||||
return mTStart + mC1 * scaledTime * (1.0 + mC2 * scaledTime);
|
||||
}
|
||||
|
||||
LinearInputStretchTimeWarper::LinearInputStretchTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mTimeWarper(tStart, 0.0, tEnd, 1.0), mTStart(tStart),
|
||||
mC1((tEnd-tStart)/rStart), mC2(0.5*(rStart/rEnd - 1.0))
|
||||
{
|
||||
wxASSERT(rStart > 0.0);
|
||||
wxASSERT(rEnd > 0.0);
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
double LinearOutputStretchTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double scaledTime = mTimeWarper.Warp(originalTime);
|
||||
return mTStart + mC1 * (pow(mC2, scaledTime) - 1.0);
|
||||
}
|
||||
|
||||
LinearOutputStretchTimeWarper::LinearOutputStretchTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mTimeWarper(tStart, 0.0, tEnd, 1.0), mTStart(tStart),
|
||||
mC1((tEnd-tStart)/(rStart*log(rStart/rEnd))), mC2(rStart/rEnd)
|
||||
{
|
||||
wxASSERT(rStart != rEnd);
|
||||
wxASSERT(rStart > 0.0);
|
||||
wxASSERT(rEnd > 0.0);
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
double GeometricInputTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double scaledTime = mTimeWarper.Warp(originalTime);
|
||||
return mTStart + mScale*(pow(mRatio,scaledTime) - 1.0);
|
||||
}
|
||||
|
||||
GeometricInputTimeWarper::GeometricInputTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mTimeWarper(tStart, 0.0, tEnd, 1.0), mTStart(tStart),
|
||||
mScale((tEnd-tStart)/(log(rStart/rEnd)*rStart)), mRatio(rStart/rEnd)
|
||||
{
|
||||
wxASSERT(rStart != rEnd);
|
||||
wxASSERT(rStart > 0.0);
|
||||
wxASSERT(rEnd > 0.0);
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
double GeometricOutputTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double scaledTime = mTimeWarper.Warp(originalTime);
|
||||
return mTStart + mScale*log(mC0 * scaledTime + 1.0);
|
||||
}
|
||||
|
||||
GeometricOutputTimeWarper::GeometricOutputTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mTimeWarper(tStart, 0.0, tEnd, 1.0), mTStart(tStart),
|
||||
mScale((tEnd-tStart)/(rEnd-rStart)), mC0((rEnd-rStart)/rStart)
|
||||
{
|
||||
wxASSERT(rStart > 0.0);
|
||||
wxASSERT(rEnd > 0.0);
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
StepTimeWarper::StepTimeWarper(double tStep, double offset)
|
||||
: mTStep(tStep), mOffset(offset)
|
||||
{ }
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
|
||||
\file TimeWarper.h
|
||||
\brief Contains declarations for TimeWarper, IdentityTimeWarper,
|
||||
ShiftTimeWarper, LinearTimeWarper, LogarithmicTimeWarper classes
|
||||
ShiftTimeWarper, LinearTimeWarper, LinearInputRateSlideTimeWarper,
|
||||
LinearOutputRateSlideTimeWarper, LinearInputInverseRateTimeWarper,
|
||||
GeometricInputRateTimeWarper, GeometricOutputRateTimeWarper classes
|
||||
|
||||
\class TimeWarper
|
||||
\brief Transforms one point in time to another point. For example, a time
|
||||
|
@ -26,8 +28,20 @@ split points in the input.
|
|||
\class LinearTimeWarper
|
||||
\brief Linear scaling, initialised by giving two points on the line
|
||||
|
||||
\class LogarithmicTimeWarper
|
||||
\brief TimeScale - rate varies linearly, so time changes logarithmically.
|
||||
\class LinearInputRateTimeWarper
|
||||
\brief TimeScale - rate varies linearly with input
|
||||
|
||||
\class LinearOutputRateTimeWarper
|
||||
\brief TimeScale - rate varies linearly with output
|
||||
|
||||
\class LinearInputInverseRateTimeWarper
|
||||
\brief TimeScale - inverse rate varies linearly with input
|
||||
|
||||
\class GeometricInputRateTimeWarper
|
||||
\brief TimeScale - rate varies geometrically with input
|
||||
|
||||
\class GeometricOutputRateTimeWarper
|
||||
\brief TimeScale - rate varies geometrically with output
|
||||
|
||||
\class StepTimeWarper
|
||||
\brief Like identity but with a jump
|
||||
|
@ -82,7 +96,7 @@ public:
|
|||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class LogarithmicTimeWarper : public TimeWarper
|
||||
class LinearInputRateTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mRateWarper;
|
||||
|
@ -90,8 +104,75 @@ private:
|
|||
double mTStart;
|
||||
double mScale;
|
||||
public:
|
||||
LogarithmicTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
LinearInputRateTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class LinearOutputRateTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mTimeWarper;
|
||||
double mRStart;
|
||||
double mTStart;
|
||||
double mScale;
|
||||
double mC1;
|
||||
double mC2;
|
||||
public:
|
||||
LinearOutputRateTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class LinearInputStretchTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mTimeWarper;
|
||||
double mTStart;
|
||||
double mC1;
|
||||
double mC2;
|
||||
public:
|
||||
LinearInputStretchTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class LinearOutputStretchTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mTimeWarper;
|
||||
double mTStart;
|
||||
double mC1;
|
||||
double mC2;
|
||||
public:
|
||||
LinearOutputStretchTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class GeometricInputTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mTimeWarper;
|
||||
double mTStart;
|
||||
double mScale;
|
||||
double mRatio;
|
||||
public:
|
||||
GeometricInputTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class GeometricOutputTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mTimeWarper;
|
||||
double mTStart;
|
||||
double mScale;
|
||||
double mC0;
|
||||
public:
|
||||
GeometricOutputTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -285,11 +285,11 @@
|
|||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\audio.cpp"
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\buffer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\buffer.cpp"
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\dBTable.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
|
@ -300,10 +300,6 @@
|
|||
RelativePath="..\..\..\lib-src\sbsms\src\grain.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\peak.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\resample.cpp"
|
||||
>
|
||||
|
@ -312,6 +308,10 @@
|
|||
RelativePath="..\..\..\lib-src\sbsms\src\sbsms.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\slide.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\sms.cpp"
|
||||
>
|
||||
|
@ -328,10 +328,6 @@
|
|||
RelativePath="..\..\..\lib-src\sbsms\src\trackpoint.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\utils.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
|
@ -339,11 +335,11 @@
|
|||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\audio.h"
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\buffer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\buffer.h"
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\dBTable.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
|
@ -354,10 +350,6 @@
|
|||
RelativePath="..\..\..\lib-src\sbsms\src\grain.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\peak.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\real.h"
|
||||
>
|
||||
|
@ -370,10 +362,18 @@
|
|||
RelativePath="..\..\..\lib-src\sbsms\src\sms.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\sse.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\subband.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\synthTable.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\lib-src\sbsms\src\track.h"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue