Compare commits

...

141 Commits

Author SHA1 Message Date
Olli
9ef8458d85 cmake minimum version to 3.5 to avoid deprecation warning 2025-02-23 13:03:03 +02:00
Olli
16956b94b9 Replace '-Ofast', being deprecated in some compilers, with '-O3 -ffast-math' 2025-02-23 13:00:17 +02:00
Olli
5dede763ff Refactor pow() usage
Refactor pow() usage:
- use base of 0.5^k instead of 1/(2^k)
- skip pow if using INTEGER_SAMPLES
2025-02-23 12:54:41 +02:00
Olli Parviainen
e31e1715fb Merge pull request 'build: add install components for CMake targets' (#42) from aminya/soundtouch:component-names into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/42
2024-10-04 11:38:47 +00:00
Amin Yahyaabadi
bc2a2f73ff build: add install components for CMake targets 2024-10-03 21:47:17 -07:00
Olli
d3f7e2530b SoundStretch: parse command-line argument values with double precision 2024-09-21 09:41:37 +03:00
Olli
ddf28667c9 Increase max nr. of channels from 16 to 32 2024-09-17 19:26:14 +03:00
Olli Parviainen
7f35604eda Merge pull request 'Fix typo in README.html' (#39) from LeonC/soundtouch:fix-typo into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/39
2024-06-18 15:40:15 +00:00
Tianxiao Cao
4ae091f54f Fix typo in README.html 2024-06-18 11:36:56 +08:00
Olli
e83424d592 Update latest stable version to 2.3.3 2024-03-29 20:49:53 +02:00
Olli Parviainen
0095a3d933 soundstretch: Print hello text even if no switches were given 2024-03-29 20:33:00 +02:00
Olli Parviainen
077e73422f Win/VisualStudio: Change Win32 debug settings to avoid build warning 2024-03-29 20:25:20 +02:00
Olli
f0ef4cd853 automake: Build SoundTouchDLL only if FLOAT samples used 2024-03-29 20:03:34 +02:00
Olli
7dce7268cd Linux soundstretch: Fix unhandled exception error 2024-03-29 19:42:55 +02:00
Olli
63002027de dos2unix:ify line endings, source code formatter 2024-03-29 19:42:23 +02:00
Olli Parviainen
290b0b13e2 Merge pull request 'source/SoundTouchDLL: don't clobber CXXFLAGS, LDFLAGS' (#35) from thesamesam/soundtouch:no-clobber-flags into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/35
2024-03-24 13:58:14 +00:00
Olli Parviainen
2a24e3b454 Merge pull request 'configure.ac: fix bashism in CXXFLAGS assignment' (#34) from thesamesam/soundtouch:bashism into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/34
2024-03-24 13:52:31 +00:00
Sam James
02c22eceea
source/SoundTouchDLL: don't clobber CXXFLAGS, LDFLAGS
automake warns about this, telling us to set AM_CXXFLAGS and AM_LDFLAGS instead.

This fixes respecting LDFLAGS in particular (the CXXFLAGS one was harmless).

Signed-off-by: Sam James <sam@gentoo.org>
2024-03-24 07:41:49 +00:00
Sam James
ba1cb7727e configure.ac: fix bashism in CXXFLAGS assignment
configure scripts need to be runnable with a POSIX-compliant /bin/sh.

On many (but not all!) systems, /bin/sh is provided by Bash, so errors
like this aren't spotted. Notably Debian defaults to /bin/sh provided
by dash which doesn't tolerate such bashisms as '=='.

This retains compatibility with bash.

Fixes configure warnings/errors like:
```
checking whether make supports nested variables... (cached) yes
configure: 3698: CXXFLAGS+= -Ofast: not found
```

Signed-off-by: Sam James <sam@gentoo.org>
2024-03-24 07:34:48 +00:00
Olli Parviainen
17b63eeb3e Merge pull request 'Use -O3 instead of -Ofast when targeting Emscripten (WebAssembly)' (#29) from fwcd/soundtouch:fix-cmake-emscripten into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/29
2024-03-03 18:00:19 +00:00
Olli Parviainen
2e83c770b0 Merge pull request 'Set CMAKE_CXX_STANDARD to 17 in CMakeLists' (#30) from fwcd/soundtouch:cmake-cxx-standard-17 into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/30
2024-03-03 17:56:28 +00:00
fwcd
5e624fff73 Set CMAKE_CXX_STANDARD to 17 2024-03-02 23:21:39 +01:00
fwcd
1c6a90804b Use -O3 instead of -Ofast when targeting Emscripten (WASM) 2024-03-02 23:02:06 +01:00
Olli Parviainen
f921e5b586 Fix DLL function import clause for gnu platform 2024-03-02 19:11:43 +02:00
Olli Parviainen
6872a2b6d0 Add SS_CharTypes.h 2024-03-02 18:52:42 +02:00
Olli Parviainen
d90844f67d Add class="current" to latest entry in change history 2024-02-12 17:48:11 +02:00
Olli Parviainen
375e6ccfe9 Windows: SoundStretch to accept wide-character command line attributes to support asian/non-latin files names. 2024-02-11 17:52:48 +02:00
Olli Parviainen
74514f5597 C# example: Update to NET toolit v4.8.1, x64 by default, update SoundTouch.dll binary 2023-12-03 17:28:15 +02:00
Olli Parviainen
3781ff5d55 Merge pull request 'fix: fix the CMake config for SoundTouchDLL' (#24) from aminya/soundtouch:dll-cmake into master
Thanks for the MR.

Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/24
2023-12-03 11:24:27 +00:00
Amin Yahyaabadi
e56457728c fix: fix the CMake config for SoundTouchDLL 2023-12-03 11:24:27 +00:00
Olli Parviainen
c4c922c7b9 Merge pull request 'fix: fix uint conversion for number of samples' (#25) from aminya/soundtouch:conversions into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/25
2023-12-03 11:23:25 +00:00
Amin Yahyaabadi
28df544c48
fix: fix uint conversion for number of samples 2023-12-02 21:22:48 -08:00
Olli Parviainen
dd2252e9af Merge pull request 'Do not add -mfpu=neon flag under aarch64' (#15) from fundawang/soundtouch:master into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/15
2023-04-24 15:42:50 +00:00
fundawang
55bd933dba Do not add -mfpu=neon flag under aarch64 2023-04-23 22:26:37 +00:00
Olli Parviainen
8726394399 Merge pull request 'Fixed MSVC build errors' (#14) from oviano/soundtouch:fixed-msvc-build-error into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/14
2023-04-12 16:15:56 +00:00
Oliver Collyer
170349af69 Fixed MSVC build errors 2023-04-12 14:55:46 +01:00
Olli Parviainen
b477936716 Resolve gcc compiler warnings in ARM environment 2023-04-02 18:48:28 +03:00
Olli Parviainen
cc24adfc6d Merge pull request 'Expose BPM detector beat position and strength retrieval API via SoundTouchDLL.' (#11) from sagamusix/soundtouch:master into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/11
2023-03-26 17:03:37 +00:00
Johannes Schultz
808bf021e6 Expose BPM detector beat position and strength retrieval API via SoundTouchDLL. 2023-03-26 18:54:04 +02:00
Olli
63db6bf344 Add -Wextra -Wzero-as-null-pointer-constant to configure.ac
Signed-off-by: Olli <oparviai'at'iki.fi>
2023-03-25 11:49:10 +02:00
Olli Parviainen
05d2835f65 Merge pull request 'Increase warning settings' (#10) from Minty-Meeo/soundtouch:master into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/10
2023-03-25 09:44:23 +00:00
Minty-Meeo
1eda9c0b01 Resolve [-Wzero-as-null-pointer-constant] 2023-03-24 12:32:50 -05:00
Minty-Meeo
230ae2f9a9 Resolve [-Wextra]
[-Winconsistent-missing-override]
[-Wunused-const-variable]
[-Wunused-private-field]
[-Wunused-parameter]
2023-03-24 12:32:24 -05:00
Olli
a88c82d0ab Enable -Wall -Wno-unknown-pragmas compiler setting
Enable `-Wall -Wno-unknown-pragmas` compiler setting to show warnings
during build.

Supress "unknown-pragmas" warning though because it's legitimely used
for openmp support.

Signed-off-by: Olli <oparviai'at'iki.fi>
2023-03-19 17:06:47 +02:00
serge-sans-paille
82cb3f99bb Remove unused dScaler variable in FIRFilter.cpp
Code is guarded by SOUNDTOUCH_FLOAT_SAMPLES but never actually used. Get
rid of it as it triggers a warning under -Werror=unused-variable.
--
Cherry-picked from
https://gitlab.com/serge-sans-paille/soundtouch/-/tree/fix/remove-unused-float-scaler
2023-03-19 16:52:18 +02:00
serge-sans-paille
4070166f4a Avoid signed/unsigned comparison when possible
As reported by -Wall
--
Cherry-picked from
https://gitlab.com/serge-sans-paille/soundtouch/-/tree/fix/sign-issue
2023-03-19 16:50:59 +02:00
serge-sans-paille
4bcbb3556f Remove trivially unused variables, as pointed out by -Wunused-variable
cherry-picked from
https://gitlab.com/serge-sans-paille/soundtouch/-/tree/fix/remove-unused-variables
2023-03-19 16:50:56 +02:00
Olli
29fba832a7 Update version to 2.3.2
Signed-off-by: Olli <oparviai'at'iki.fi>
2022-11-08 18:02:17 +02:00
Olli Parviainen
9e798c0f7f Fix compiler flags in SoundTouchDLL/Makefile.am
Fix compiler flags in SoundTouchDLL/Makefile.am so that flags inherited
from master makefile get included.

Signed-off-by: Olli Parviainen <oparviai'at'iki.fi>
2022-11-02 19:55:10 +02:00
Olli Parviainen
ddc351bfb6 Merge remote-tracking branch 'origin/config-updates' 2022-11-02 19:43:23 +02:00
Olli
774257ab5f Small updates to dynamic-link libary build script & pascal example
Signed-off-by: Olli <oparviai'at'iki.fi>
2022-10-31 18:51:35 +02:00
Olli Parviainen
eaa9090f65 Merge pull request 'Migrate configuration file, add building of dynamic-link version to the master makefile' (#9) from config-updates into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/9
2022-10-30 17:19:16 +01:00
Olli
17925302ae Migrate configuration file, add building of dynamic-link version to the master makefile
- Migrate configuration.ac file to new autotools
- add building of also the dynamic-link version within
  'source/SoundTouchDLL' directory from the main-level makefile
- add a simple lazarus/pascal example project that uses the dynamic-link
  version of the SoundTouch library

Signed-off-by: Olli <oparviai'at'iki.fi>
2022-10-30 18:15:10 +02:00
Olli Parviainen
8562287944 Merge pull request 'Comment out _init_threading call in processFile function' (#1) from shwixel/soundtouch:master into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/1
2022-01-23 16:10:34 +01:00
Olli Parviainen
9f14bd8b6e Merge pull request 'Fix exception throwing across DLL boundary' (#2) from sagamusix/soundtouch:master into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/2
2022-01-23 16:08:35 +01:00
Olli Parviainen
64760eb34e Merge pull request 'Add 'override' keyword' (#3) from vestral/soundtouch:override into master
Reviewed-on: https://codeberg.org/soundtouch/soundtouch/pulls/3
2022-01-23 16:01:34 +01:00
Vestral
bb0434dd6e Add 'override' keyword 2022-01-22 09:22:02 +09:00
Johannes Schultz
1a07a649e4 C functions mustn't throw. Catch exceptions in SoundTouch DLL interface because the user cannot catch them. 2021-12-04 22:09:51 +01:00
Johannes Schultz
bdafd3b08c Ignore .vs folders created by Visual Studio 2021-12-04 22:02:06 +01:00
Daniil Zakharov
ab2b8ca91f Comment out _init_threading call in processFile function 2021-12-03 02:42:45 +03:00
Olli
9fedba866e synced gitlab+codeberg masters 2021-10-31 17:20:56 +02:00
Olli
0afe414a18 Merge remote-tracking branch 'gitlab/master' 2021-10-31 17:20:19 +02:00
Olli
b9092339f5 add links to stable tarballs 2021-10-31 17:16:13 +02:00
Olli
85c03d6063 update readme.md 2021-10-31 17:11:53 +02:00
Olli
7ede48e436 update repository location 2021-10-31 16:57:52 +02:00
Olli Parviainen
8a9d4acb12 Add links to source code release tarballs
Signed-off-by: Olli Parviainen <oparviai at iki fi>
2021-10-14 19:16:15 +03:00
Olli
d063c0d9f9 Changed gitlab.com references to codeberg.org 2021-10-14 18:29:15 +03:00
Olli Parviainen
b9afe0ac11 Merge branch 'cmake-openmp' into 'master'
CMake: Add option for OpenMP

See merge request soundtouch/soundtouch!24
2021-10-04 16:24:22 +00:00
Daniel E
572d12c3e9 CMake: Add option for OpenMP
Make support for OpenMP optional (disabled by default)
2021-10-03 23:45:00 +00:00
Olli Parviainen
e016ebfcd5 Merge branch 'diizzyy-master-patch-90177' into 'master'
CMake: Add aarch64 as identifier for ARM 64-bit

See merge request soundtouch/soundtouch!21
2021-10-03 15:49:51 +00:00
Daniel E
4fd8e1acb9 CMake: Add aarch64 as identifier for ARM 64-bit
On FreeBSD ARM 64-bit is called aarch64
2021-09-26 17:09:05 +00:00
Olli Parviainen
afb0e4a73f Merge branch 'diizzyy-master-patch-80799' into 'master'
CMake: Fix build with INTEGER_SAMPLES enabled

See merge request soundtouch/soundtouch!20
2021-09-19 17:45:35 +00:00
Daniel E
77cbbb2227 CMake: Fix build with INTEGER_SAMPLES enabled 2021-09-18 16:21:41 +00:00
Olli Parviainen
e1f315f535 Merge branch 'dll_exports' into 'master'
CMake: fix SoundTouchDLL build with MSVC

See merge request soundtouch/soundtouch!18
2021-09-07 15:26:53 +00:00
Olli Parviainen
82e9ebd075 Merge branch 'fpic' into 'master'
CMake: fix compiler warning about unknown option -fPIC with MSVC

See merge request soundtouch/soundtouch!19
2021-09-07 15:11:30 +00:00
Be
fd8e4c6835
CMake: fix compiler warning about unknown option -fPIC with MSVC 2021-09-07 08:42:45 -05:00
Be
d7b7a2f3a1
CMake: fix SoundTouchDLL build with MSVC 2021-09-07 08:35:18 -05:00
Olli
7df5617a4b cmake: remove "CMAKE" compiler definition and instead add mock "soundtouch_config.h"
Add a empty mock "soundtouch_config.h" file and remove "CMAKE" compiler
definition that was used in #ifdef that skipped including
"soundtouch_config.h" in cmake build.

This is to avoid errors about missing include file when not using
autotools build.

Also update version to 2.3.1

Signed-off-by: Olli <oparviai'at'iki.fi>
2021-09-06 20:13:01 +03:00
Olli Parviainen
2e606befef Merge branch 'shared-lib-version' into 'master'
Set VERSION and SOVERSION for shared libraries

See merge request soundtouch/soundtouch!15
2021-09-01 14:58:22 +00:00
Olli Parviainen
268a91494b Merge branch 'configure.ac' into 'master'
Fix for commit 3d7bf376

See merge request soundtouch/soundtouch!17
2021-09-01 14:57:50 +00:00
Olli Parviainen
2adf2ae71d Merge branch 'incorrect-fsf-address' into 'master'
Correct fsf address

See merge request soundtouch/soundtouch!16
2021-09-01 14:57:18 +00:00
Sérgio M. Basto
9f72a8aa6b Fix for commit 3d7bf376
we need use += and a space CXXFLAGS+=" -O3 -ffast-math" , if not += you override all system settings for CXXFLAGS and none for LDFLAGS, which ends with "/usr/bin/ld: /tmp/ccARck2g.o: relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE`"

https://stackoverflow.com/a/38579792/778517
2021-08-31 22:11:27 +01:00
Sérgio M. Basto
d11a3adb2d Correct fsf address
https://fedoraproject.org/wiki/Common_Rpmlint_issues#incorrect-fsf-address
2021-08-30 19:07:29 +01:00
Uwe Klotz
847edf4548 Set VERSION and SOVERSION for shared libraries
Required by the RPM builds for Fedora:

b7c49ac115
2021-08-30 10:01:38 +02:00
Be
3148382fa8 CMake: make building soundstretch optional 2021-08-29 18:19:28 +03:00
Olli
c65afe49f6 cmake: add -mfpu=neon if neon build 2021-08-21 13:25:24 +03:00
Olli
28b32c0fbb Update readme, version info for release v2.3.0
Signed-off-by: Olli <oparviai'at'iki.fi>
2021-08-21 13:00:35 +03:00
Olli
bd2149daf6 Fix cmake NEON condition
Signed-off-by: Olli <oparviai'at'iki.fi>
2021-08-21 12:59:59 +03:00
Olli
776443f914 Disable OpenMP init_threading workaround in Android build
Signed-off-by: Olli <oparviai'at'iki.fi>
2021-08-21 11:38:17 +03:00
Olli
65caafdc5f cmake: add 'soundstretch' utility, regroup CMakeList.txt by targets
- add 'soundstretch' utility as cmake build target
- group CMakeList.txt contents per target for better readability
2021-08-20 21:56:12 +03:00
Olli Parviainen
6dce1068d9 Merge branch 'optimizations' into 'master'
CMake: set optimization options for MSVC as well as GCC & Clang

See merge request soundtouch/soundtouch!13
2021-08-20 17:57:09 +00:00
Be
eb6d970970
CMake: set optimization options for MSVC as well as GCC & Clang 2021-08-18 12:24:18 -05:00
Olli
f974b28682 Further cmake changes for SoundTouchDLL compilation
- enable "-Ofast" compilation flags for cmake build
- adjust compiler flags for the SoundTouchDLL compilation
- add cmake-generated "SoundTouchDLL_EXPORTS" as alias for "DLL_EXPORT"
- hide cmake temporary files in gitignore

Signed-off-by: Olli <oparviai'at'iki.fi>
2021-08-17 19:50:29 +03:00
Olli Parviainen
220eb7857c Merge branch 'cmake' into 'master'
CMake fixes for SoundTouchDLL

See merge request soundtouch/soundtouch!12
2021-08-17 16:49:07 +00:00
Be
dae91683bc
CMake fixes for SoundTouchDLL 2021-08-16 11:23:01 -05:00
Olli Parviainen
fa223609d2 Merge branch 'cmake' into 'master'
add CMake build system

See merge request soundtouch/soundtouch!11
2021-08-16 16:03:43 +00:00
Be
3617bd166b
add build directory to .gitignore 2021-08-16 10:09:32 -05:00
Be
d8d86e1a92
add CMake build system 2021-08-16 10:09:32 -05:00
Olli
e0e00878fc Remove surplus semicolon
Remove surplus semicolon that caused warning if compiling with
'-pedantic' compiler switch.

Signed-off-by: Olli <oparviai 'at' iki.fi>
2021-07-30 14:53:04 +03:00
Olli
17a63e99d5 Fix bug with too small initial skipFract value
Fix bug with too small initial skipFract value with certain processing
parameter set: replaces assert with assignment that corrects the
situation.
2021-03-03 18:11:45 +02:00
Olli
6533514372 Improve soundtouch.clear() so that it really clears TDStretch & RateTransposer states
Improve soundtouch.clear() so that it really clears all TDStretch &
RateTransposer state variables. Before this clear() left last processed
sample or fractional position state uncleared, which caused slightly
different result if same stream was processed again after clear().
2021-01-30 19:02:08 +02:00
Olli
81b0d74727 Correct initial skip value
... so that with nominal tempo the expected best sequence overlapping
location lays in middle of the correlation window. This will ensure that
with output should be similar to input when tempo adjustment is zero.
2021-01-28 21:32:35 +02:00
Olli
5e76cf2f6d Disable skipping of unaligned SIMD memory offset by default
Change default setting so that SIMD does not skip of unaligned memory
offsets, as that likely is not a necessary compromise with concurrent
CPUs any more.
2021-01-28 21:26:38 +02:00
Olli
f38cfa6850 Call "clear()" after changing anti-alias filter on/off
Call "clear()" after changing anti-alias filter on/off to prefill
buffers appropriately.
2021-01-28 20:19:06 +02:00
Olli Parviainen
762f56024b Updated versions and documents for release 2.2 2020-10-15 18:23:34 +03:00
Olli Parviainen
1d42d899ab Merge branch 'improve-autovectorization' into 'master'
Improvements to help compiler autovectorization

See merge request soundtouch/soundtouch!10
2020-10-13 18:19:08 +00:00
Olli Parviainen
bf3cec0244 Improvements to help compiler autovectorization
Refactored FIRfilter and TDStretch hot-spot routines to help compiler
perform more efficient autovectorization.

Benchmarked:
- 2x/3x improvement in gcc-generated x86 SIMD code execution
  times for SSE2/AVX instruction extensions accordingly, when
  hand-tuned SSE intrinsics were disabled. Hand-tuned SSE code
  still is slightly faster than gcc-produced AVX.
- 2.4x improvement for cumulative ARM NEON tunings when compared to
  previous SoundTouch release.

Signed-off-by: Olli Parviainen <oparviai'at'iki.fi>
2020-10-13 20:46:23 +03:00
Olli Parviainen
a911a1e986 Bugfix in integer version of calcCrossCorrAccumulate()
Using "unsigned long" for "lnorm" variable that was yet made negative in very first step caused incorrect calculation result. Corrected the type to "long".

Signed-off-by: Olli Parviainen <oparviai@iki.fi>
2020-10-03 16:58:00 +03:00
Olli Parviainen
3e74d1d18f Fixed characters in source code comments that ought to be ± 2020-07-08 19:13:30 +03:00
Olli Parviainen
f382149086 Compensate initial buffering of anti-alias filter and intepolator.
This avoids losing first few dozen of samples from beginning of the stream.

Signed-off-by: Olli Parviainen <oparviai at iki.fi>
2020-06-30 14:16:03 +03:00
Olli Parviainen
308c3484f6 Merge branch 'feature/neon-tuning' into 'master'
Tuning for ARM NEON

See merge request soundtouch/soundtouch!8
2020-06-21 17:43:36 +00:00
Olli Parviainen
3d7bf376fd Tuning for ARM NEON
Tuning to enable ARM NEON SIMD performance improvements:
- NEON detection in configure file
- Remove manual loop unrolling, gcc autovectorization does better job
without manually unrolled loops.
- Avoid unaligned pointer accesses when using NEON
2020-06-21 20:38:00 +03:00
Olli Parviainen
1e56c65ea5 Merge branch 'bpmdetect-warning-size_t-int' into 'master'
BPMDetect: Make conversion from size_t to int explicit

See merge request soundtouch/soundtouch!7
2020-05-10 14:39:52 +00:00
Rémi Verschelde
fe15975a21 BPMDetect: Make conversion from size_t to int explicit
Fixes warning C4267 on MSVC.

This assumes that `beats.size()` should never overflow `int` - if that
could happen, the API should likely be changed to handle it gracefully.
2020-04-28 10:48:47 +02:00
Olli Parviainen
a046b6971d Windows build: Retargeted to Visual Studio 2019 and Windows 10. Removed obsolete /Gm build option.
Signed-off-by: Olli Parviainen <oparviai at iki.fi>
2020-02-02 18:58:46 +02:00
Olli Parviainen
c4f1602474 Added section about building the software in Mac 2019-10-28 19:04:28 +02:00
Olli Parviainen
244fbeac24 BPM PeakFinder: Fix possible reading past end of array.
Increase minor version accordingly.
2019-01-07 18:55:36 +02:00
Olli Parviainen
12cb25ed7b Updated README.html 2019-01-01 16:55:23 +02:00
Olli
fb3ea4d9f0 Update readme.md 2018-12-08 19:01:57 +00:00
Olli Parviainen
2b2585bc74 Enable using multiple CPUs in Visual Studio build for faster build 2018-12-04 21:11:17 +02:00
Olli
eef1220d72 BPMDetect: Change correlation loop 'sum' variable type from double to float, because double causes big performance penalty for autovectorized code. 2018-12-02 22:33:55 +02:00
olli
9205fc971e Bump version to 2.1.2 to correct incorrect version info in configure.ac 2018-12-02 10:43:00 +02:00
Olli
b9659b64c6 Updated readme & version info to 2.1.1 2018-11-14 19:25:34 +02:00
Olli
7f594f8b7d New take on CVE-2018-17097 i.e. avoiding writing beyond end of buffer in case of 24-bit samples 2018-10-31 18:36:05 +02:00
olli
6d700259b9 Touched version number 2018-10-28 16:27:48 +02:00
olli
dad1d566c4 Added unset ACLOCAL to bootstrap to avoid issue that ACLOCAL has been previously set to incompatible value. 2018-10-28 16:25:23 +02:00
Olli
41a2cd3e6b Merge branch 'master' of gitlab.com:soundtouch/soundtouch 2018-10-28 16:05:26 +02:00
Olli
09e04252dd Fix CVE-2018-17097 by rounding working buffer size up to nearest 4-byte boundary. Replaced also tab characters with spaces in indentation. 2018-10-28 16:04:15 +02:00
Olli
59129fa33d Eliminate assert condition by reading # sample elements that are multiple of num-of-channels 2018-10-28 15:49:50 +02:00
Olli
a1c400eb2c Fix issue CVE-2018-17096: Replace assert with runtime exception 2018-10-28 15:32:58 +02:00
Olli
12eaa21e14 Merge branch 'android-build-update' into 'master'
Adding gradle build for Android example

See merge request soundtouch/soundtouch!6
2018-09-22 16:14:52 +00:00
ggfan
bdbe1bf551 Adding gradle build for Android example 2018-09-20 07:35:02 -07:00
Olli
1d63bbf8e1 Update readme.md 2018-09-10 06:22:36 +00:00
olli
79cbdb1140 Reformat README.html eol characters 2018-09-08 19:15:39 +03:00
Olli
3ea4f5c7b3 Merge branch 'master' of https://gitlab.com/soundtouch/soundtouch 2018-09-08 19:04:37 +03:00
Olli
68df82bd5b Merge branch 'master' of https://gitlab.com/soundtouch/soundtouch 2018-09-08 19:04:21 +03:00
Olli
00241ebba1 Merge branch 'master' of https://gitlab.com/soundtouch/soundtouch 2018-09-08 18:54:04 +03:00
Olli
1e9ec6f54b Merge branch 'master' of https://gitlab.com/soundtouch/soundtouch 2018-09-08 18:53:37 +03:00
Olli
50348640f7 Merge branch 'master' of https://gitlab.com/soundtouch/soundtouch 2018-09-08 18:52:44 +03:00
Olli
1e9c3bce2d Bump version to 2.1 2018-09-08 18:52:10 +03:00
Olli
5e3ca30225 Bump version to 2.1 2018-09-08 18:34:10 +03:00
87 changed files with 13021 additions and 11718 deletions

15
.gitignore vendored
View File

@ -38,3 +38,18 @@ source/SoundTouchDll/Win32/
source/SoundTouchDll/x64/
source/SoundTouchDll/DllTest/Win32/
source/SoundTouchDll/DllTest/x64/
.vs
# Files generated by Android Studio
source/android-lib/.gradle
source/android-lib/.idea
**/*.iml
source/android-lib/local.properties
source/android-lib/build
source/android-lib/.externalNativeBuild
# CMake build directory
build*
CMakeFiles
CMakeCache.txt
*.cmake

191
CMakeLists.txt Normal file
View File

@ -0,0 +1,191 @@
cmake_minimum_required(VERSION 3.5)
project(SoundTouch VERSION 2.3.3 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
include(GNUInstallDirs)
set(COMPILE_OPTIONS)
if(MSVC)
set(COMPILE_DEFINITIONS /O2 /fp:fast)
else()
list(APPEND COMPILE_OPTIONS -Wall -Wextra -Wzero-as-null-pointer-constant -Wno-unknown-pragmas)
if(EMSCRIPTEN)
list(APPEND COMPILE_OPTIONS -O3)
else()
# Apply -ffast-math to allow compiler autovectorization generate effective SIMD code for arm compilation
list(APPEND COMPILE_OPTIONS -O3 -ffast-math)
endif()
endif()
#####################
# SoundTouch library
add_library(SoundTouch
source/SoundTouch/AAFilter.cpp
source/SoundTouch/BPMDetect.cpp
source/SoundTouch/cpu_detect_x86.cpp
source/SoundTouch/FIFOSampleBuffer.cpp
source/SoundTouch/FIRFilter.cpp
source/SoundTouch/InterpolateCubic.cpp
source/SoundTouch/InterpolateLinear.cpp
source/SoundTouch/InterpolateShannon.cpp
source/SoundTouch/mmx_optimized.cpp
source/SoundTouch/PeakFinder.cpp
source/SoundTouch/RateTransposer.cpp
source/SoundTouch/SoundTouch.cpp
source/SoundTouch/sse_optimized.cpp
source/SoundTouch/TDStretch.cpp
)
target_include_directories(SoundTouch PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_definitions(SoundTouch PRIVATE ${COMPILE_DEFINITIONS})
target_compile_options(SoundTouch PRIVATE ${COMPILE_OPTIONS})
if(BUILD_SHARED_LIBS)
set_target_properties(SoundTouch PROPERTIES
VERSION ${CMAKE_PROJECT_VERSION}
)
if(WIN32)
set_target_properties(SoundTouch PROPERTIES
WINDOWS_EXPORT_ALL_SYMBOLS TRUE
)
else()
set_target_properties(SoundTouch PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}
)
endif()
endif()
option(INTEGER_SAMPLES "Use integers instead of floats for samples" OFF)
if(INTEGER_SAMPLES)
target_compile_definitions(SoundTouch PRIVATE SOUNDTOUCH_INTEGER_SAMPLES)
else()
target_compile_definitions(SoundTouch PRIVATE SOUNDTOUCH_FLOAT_SAMPLES)
endif()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7.*|armv8.*|aarch64.*)$")
set(NEON_CPU ON)
else()
set(NEON_CPU OFF)
endif()
option(NEON "Use ARM Neon SIMD instructions if in ARM CPU" ON)
if(${NEON} AND ${NEON_CPU})
target_compile_definitions(SoundTouch PRIVATE SOUNDTOUCH_USE_NEON)
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64.*$")
target_compile_options(SoundTouch PRIVATE -mfpu=neon)
endif()
endif()
find_package(OpenMP)
option(OPENMP "Use parallel multicore calculation through OpenMP" OFF)
if(OPENMP AND OPENMP_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
install(
FILES
include/BPMDetect.h
include/FIFOSampleBuffer.h
include/FIFOSamplePipe.h
include/STTypes.h
include/SoundTouch.h
include/soundtouch_config.h
DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}/soundtouch"
COMPONENT SoundTouch
)
install(TARGETS SoundTouch
EXPORT SoundTouchTargets
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
COMPONENT SoundTouch
)
#######################
# soundstretch utility
option(SOUNDSTRETCH "Build soundstretch command line utility." ON)
if(SOUNDSTRETCH)
add_executable(soundstretch
source/SoundStretch/main.cpp
source/SoundStretch/RunParameters.cpp
source/SoundStretch/WavFile.cpp
)
target_include_directories(soundstretch PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_compile_definitions(soundstretch PRIVATE ${COMPILE_DEFINITIONS})
target_compile_options(soundstretch PRIVATE ${COMPILE_OPTIONS})
target_link_libraries(soundstretch PRIVATE SoundTouch)
if(INTEGER_SAMPLES)
target_compile_definitions(soundstretch PRIVATE SOUNDTOUCH_INTEGER_SAMPLES)
endif()
install(TARGETS soundstretch
DESTINATION bin
COMPONENT soundstretch
)
endif()
########################
# SoundTouchDll library
option(SOUNDTOUCH_DLL "Build SoundTouchDLL C wrapper library" OFF)
if(SOUNDTOUCH_DLL)
add_library(SoundTouchDLL SHARED
source/SoundTouchDLL/SoundTouchDLL.cpp
source/SoundTouchDLL/SoundTouchDLL.rc
)
set_target_properties(SoundTouch PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
target_compile_options(SoundTouchDLL PRIVATE ${COMPILE_OPTIONS})
set_target_properties(SoundTouchDLL PROPERTIES CXX_VISIBILITY_PRESET hidden)
target_compile_definitions(SoundTouchDLL PRIVATE DLL_EXPORTS)
target_include_directories(SoundTouchDLL PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries(SoundTouchDLL PRIVATE SoundTouch)
install(FILES source/SoundTouchDLL/SoundTouchDLL.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/soundtouch" COMPONENT SoundTouchDLL)
install(TARGETS SoundTouchDLL EXPORT SoundTouchTargets COMPONENT SoundTouchDLL)
endif()
########################
# pkgconfig
set(prefix "${CMAKE_INSTALL_PREFIX}")
set(execprefix "\${prefix}")
set(libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
set(VERSION "${CMAKE_PROJECT_VERSION}")
configure_file(soundtouch.pc.in "${CMAKE_CURRENT_BINARY_DIR}/soundtouch.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/soundtouch.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" COMPONENT SoundTouch)
# CMake config
include(CMakePackageConfigHelpers)
set(SOUNDTOUCH_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/SoundTouch")
install(
EXPORT SoundTouchTargets
FILE SoundTouchTargets.cmake
NAMESPACE SoundTouch::
DESTINATION "${SOUNDTOUCH_INSTALL_CMAKEDIR}"
COMPONENT SoundTouch
)
configure_package_config_file(SoundTouchConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfig.cmake"
INSTALL_DESTINATION "${SOUNDTOUCH_INSTALL_CMAKEDIR}"
)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfigVersion.cmake"
VERSION "${CMAKE_PROJECT_VERSION}"
COMPATIBILITY SameMajorVersion
)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfigVersion.cmake"
DESTINATION "${SOUNDTOUCH_INSTALL_CMAKEDIR}"
COMPONENT SoundTouch
)

View File

@ -2,7 +2,7 @@
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -117,7 +117,7 @@ be combined with the library in order to run.
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authoried party saying it may be distributed under the terms of
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".

View File

@ -1,20 +1,22 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>SoundTouch library README</title>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1252">
<meta http-equiv="Content-Language" content="en-us">
<meta name="author" content="Olli Parviainen">
<meta name="description"
content="Readme file for SoundTouch audio processing library">
<style> <!-- .normal { font-family: Arial }
--></style>
<meta name="description" content="Readme file for SoundTouch audio processing library">
<style>
body {
font-family: Arial, Helvetica;
}
</style>
</head>
<body class="normal">
<hr>
<h1>SoundTouch audio processing library v2.1pre</h1>
<p class="normal">SoundTouch library Copyright <EFBFBD> Olli Parviainen 2001-2018</p>
<h1>SoundTouch audio processing library v2.3.3</h1>
<p class="normal">SoundTouch library Copyright &copy; Olli Parviainen 2001-2024</p>
<hr>
<h2>1. Introduction </h2>
<p>SoundTouch is an open-source audio processing library that allows
@ -32,10 +34,12 @@ same time</li>
<h3>1.1 Contact information </h3>
<p>Author email: oparviai 'at' iki.fi </p>
<p>SoundTouch WWW page: <a href="http://soundtouch.surina.net">http://soundtouch.surina.net</a></p>
<p>SoundTouch git repository: <a
href="https://codeberg.org/soundtouch/soundtouch.git">https://codeberg.org/soundtouch/soundtouch.git</a></p>
<hr>
<h2>2. Compiling SoundTouch</h2>
<p>Before compiling, notice that you can choose the sample data format if it's
desirable to use floating point sample data instead of 16bit integers. See
desirable to use 16bit integer sample data instead of floating point samples. See
section &quot;sample data format&quot; for more information.</p>
<p>Also notice that SoundTouch can use OpenMP instructions for parallel
computation to accelerate the runtime processing speed in multi-core systems,
@ -68,15 +72,17 @@ folders.</p>
<li>x64 64bit: C:\Program Files (x86)\Microsoft Visual Studio
9.0\VC\redist\amd64\Microsoft.VC90.OPENMP\vcomp90.dll</li>
</ul>
<p>In Visual Studio 2008, a SP1 version may be required for these libraries. In
other VC++ versions the required library will be expectedly found in similar
<p>In other VC++ versions the required library will be expectedly found in similar
&quot;redist&quot; location.</p>
<p>Notice that as minor demonstration of a &quot;dll hell&quot; phenomenon both the 32-bit
and 64-bit version of vcomp90.dll have the same filename but different contents,
thus choose the proper version to allow the program start.</p>
thus choose the proper version to allow the program to start.</p>
<h3>2.2. Building in Gnu platforms</h3>
<p>The SoundTouch library compiles in practically any platform
supporting GNU compiler (GCC) tools. SoundTouch requires GCC version 4.3 or later.</p>
supporting GNU compiler (GCC) tools.
<h4>2.2.1 Compiling with autotools</h4>
<p>To install build prerequisites for 'autotools' tool chain:</p>
<pre> sudo apt-get install automake autoconf libtool build-essential</pre>
<p>To build and install the binaries, run the following commands in
/soundtouch directory:</p>
<table border="0" cellpadding="0" cellspacing="4">
@ -123,41 +129,32 @@ destination locations.</p>
</tr>
</tbody>
</table>
<h4><b>2.2.1 Required GNU tools</b></h4>
<p> <span style="font-weight: bold;">Bash shell</span>, <span
style="font-weight: bold;">GNU C++ compiler</span>, <span
style="font-weight: bold;">libtool</span>, <span
style="font-weight: bold;">autoconf</span> and <span
style="font-weight: bold;">automake</span> tools
are required for compiling the SoundTouch library. These are usually
included with the GNU/Linux distribution, but if not, install these
packages first. For example, Ubuntu Linux can acquire and install
these with the following command:</p>
<pre><b>sudo apt-get install automake autoconf libtool build-essential</b></pre>
<h4><b>2.2.2 Problems with GCC compiler compatibility</b></h4>
<p>At the release time the SoundTouch package has been tested to
compile in GNU/Linux platform. However, If you have problems getting the
SoundTouch library compiled, try disabling optimizations that are specific for
x86 processors by running <b>./configure</b> script with switch
<blockquote>
<pre>--enable-x86-optimizations=no</pre>
</blockquote>
Alternatively, if you don't use GNU Configure system, edit file "include/STTypes.h"
directly and remove the following definition:<blockquote>
<pre>#define SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS 1</pre>
</blockquote>
<b>Compiling portable Shared Library / DLL version</b>
<p> The GNU autotools compilation automatically builds an additional dynamic-link version
of SoundTouch library that features position-independent code and "C"-style API that is
more suitable for calling the SoundTouch routines from other programming languages.</p>
<p>This dynamic-link library is built under source/SoundTouchDLL directory, whose
subdirectories also comtain simple example apps that use the dynamic-link library.
</p>
<h4><b>2.2.3 Compiling Shared Library / DLL version in Cygwin</b></h4>
<p>
The GNU compilation does not automatically create a shared-library version of
SoundTouch (.so or .dll). If such is desired, then you can create it as follows
after running the usual compilation:</p>
<blockquote>
<pre>g++ -shared -static -DDLL_EXPORTS -I../../include -o SoundTouch.dll \
SoundTouchDLL.cpp ../SoundTouch/.libs/libSoundTouch.a
sstrip SoundTouch.dll</pre>
</blockquote>
<h4><b>2.2.2 Compiling with cmake</b></h4>
<p>'cmake' build scripts are provided as an alternative to the autotools toolchain.</p>
<p>To install cmake build prerequisites:</p>
<pre> sudo apt-get install libtool build-essential cmake</pre>
<p>To build:</p>
<pre>
cmake .
make -j
make install</pre>
<p>To list available build options:</p>
<pre>
cmake -LH</pre>
<p>To compile the additional portable Shared Library / DLL version with the native C-language API:</p>
<pre>
cmake . -DSOUNDTOUCH_DLL=ON
make -j
make install</pre>
<h3>2.3. Building in Android</h3>
<p>Android compilation instructions are within the
@ -172,18 +169,26 @@ library binary version to use.</p>
example application that processes WAV audio files using SoundTouch library in
Android devices.</p>
<h3>2.4. Building in Mac</h3>
<p>Install autoconf tool as instructed in <a
href="http://macappstore.org/autoconf/">http://macappstore.org/autoconf/</a>, or alternatively the 'cmake' toolchain.</p>
<p>Then, build as described above in section "Building in Gnu platforms".</p>
<hr>
<h2>3. About implementation &amp; Usage tips <h3>3.1. Supported sample data formats</h3>
<p>The sample data format can be chosen between 16bit signed integer
and 32bit floating point values. The default is 32bit floating point format,
which will also provide slightly better sound quality over the integer format. </p>
and 32bit floating point values.</p>
</p> The default sample type is 32bit floating point format,
which also provides better sound quality than integer format because
integer algorithms need to scale already intermediate calculation results to
avoid integer overflows. These early integer scalings can slightly degrade
output quality.</p>
<p> In Windows environment, the sample data format is chosen in file
"STTypes.h" by choosing one of the following defines:</p>
<ul>
<li> <span style="font-weight: bold;">#define
SOUNDTOUCH_INTEGER_SAMPLES</span> for 16bit signed integer</li>
<li> <span style="font-weight: bold;">#define </span><span
style="font-weight: bold;">SOUNDTOUCH_</span><span
<li> <span style="font-weight: bold;">#define </span><span style="font-weight: bold;">SOUNDTOUCH_</span><span
style="font-weight: bold;">FLOAT_SAMPLES</span> for 32bit floating
point</li>
</ul>
@ -200,7 +205,7 @@ that while it'd be possible in theory to process stereo sound as two
separate mono channels, this isn't recommended because processing the
channels separately would result in losing the phase coherency between
the channels, which consequently would ruin the stereo effect.</p>
<p>Sample rates between 8000-48000H are supported.</p>
<p>Sample rates between 8000-48000Hz are supported.</p>
<h3>3.2. Processing latency</h3>
<p>The processing and latency constraints of the SoundTouch library are:</p>
<ul>
@ -299,7 +304,8 @@ ends of the consecutive sequences will overlap with each other.<br>
<br>
This shouldn't be that critical parameter. If you reduce the
DEFAULT_SEQUENCE_MS setting by a large amount, you might wish to try a
smaller value on this.</li>
smaller value on this.
</li>
</ul>
<p>Notice that these parameters can also be set during execution time
with functions "<strong>TDStretch::setParameters()</strong>" and "<strong>SoundTouch::setSetting()</strong>".</p>
@ -357,6 +363,29 @@ computation burden</td>
</tbody>
</table>
<h3>3.5 Performance Optimizations </h3>
<p><strong>Integer vs floating point:</strong></p>
<p>Floating point sample type is generally recommended because it provides
better sound quality.</p>
<p>However, execution speed difference between integer and floating point processing
depends on the CPU architecture. As rule of thumb,
<ul>
<li>in 32-bit x86 floating point and integer are roughly equally fast</li>
<li>in 64-bit x86/x64 floating point can be significantly faster than integer
version, because MMX integer optimizations are not available in the x64 architecture.
That depends on the compiler however, so that gcc can autovectorize integer routines
to work equally fast as floating point, where as Visual C++ (2017) does not
perform equally well and produces integer code that runs some 3x slower than
SSE-optimized floating poing code.
</li>
<li>in ARMv7 integer routines are twice as fast as floating point. Their
relative difference is roughly the same both with and without NEON; NEON
vfpu can however bring 2.4x speed improvement.
</li>
<li>in other platforms: try out if the execution time performance makes a
big difference</li>
</ul>
</p>
<p><strong>General optimizations:</strong></p>
<p>The time-stretch routine has a 'quick' mode that substantially
speeds up the algorithm but may slightly compromise the sound quality.
@ -371,11 +400,15 @@ function with parameter id of SETTING_USE_QUICKSEEK and value
intrinsics, providing about a 3x processing speedup for x86 compatible
processors vs. non-SIMD implementation:</p>
<ul>
<li> Intel MMX optimized routines are used with x86 CPUs when 16bit integer
<li> MMX optimized routines are used in 32-bit x86 build when 16bit integer
sample type is used</li>
<li> Intel SSE optimized routines are used with x86 CPUs when 32bit floating
point sample type is used</li>
<li> SSE optimized routines are used in 32- and 64-bit x86 CPUs when 32bit
floating point sample type is used</li>
</ul>
<p>The algorithms are tuned to utilize autovectorization efficiently
also in other CPU architectures, for example ARM cpus see approx 2.4x processing
speedup when NEON SIMD support is present.
</p>
<h3>3.5 OpenMP parallel computation</h3>
<p>SoundTouch 1.9 onwards support running the algorithms parallel in several CPU
cores. Based on benchmark the experienced multi-core processing speed-up gain
@ -383,7 +416,8 @@ ranges between +30% (on a high-spec dual-core x86 Windows PC) to 215% (on a mode
quad-core ARM of Raspberry Pi2). </p>
<p>See an external blog article with more detailed discussion about the
<a href="http://www.softwarecoven.com/parallel-computing-in-embedded-mobile-devices/">
SoundTouch OpenMP optimization</a>.</p>
SoundTouch OpenMP optimization</a>.
</p>
<p>The parallel computing support is implemented using OpenMP spec 3.0
instructions. These instructions are supported by Visual C++ 2008 and later, and
GCC v4.2 and later. Compilers that do not supporting OpenMP will ignore these
@ -407,7 +441,8 @@ library as follows:</p>
</strong>settings. Set
there &quot;<strong>OpenMP support</strong>&quot; to &quot;<strong>Yes</strong>&quot;. Alternatively add
<strong>/openmp</strong> switch to command-line
parameters</li>
parameters
</li>
<li><strong>GNU</strong>: Run the configure script with &quot;<strong>./configure
--enable-openmp</strong>&quot; switch, then run make as usually</li>
<li><strong>Android</strong>: Add &quot;<strong>-fopenmp</strong>&quot; switches to compiler &amp; linker
@ -418,7 +453,7 @@ library as follows:</p>
<h2><a name="SoundStretch"></a>4. SoundStretch audio processing utility
</h2>
<p>SoundStretch audio processing utility<br>
Copyright (c) Olli Parviainen 2002-2015</p>
Copyright (c) Olli Parviainen 2002-2024</p>
<p>SoundStretch is a simple command-line application that can change
tempo, pitch and playback rates of WAV sound files. This program is
intended primarily to demonstrate how the "SoundTouch" library can be
@ -573,7 +608,66 @@ this corresponds to lowering the pitch by -0.318 semitones:</p>
<hr>
<h2>5. Change History</h2>
<h3>5.1. SoundTouch library Change History </h3>
<p><b>2.1pre:</b></p>
<p><b>2.3.3:</b></p>
<ul class="current">
<li>Fixing compiler warnings, maintenance fixes to make/build files for various systems
</li>
</ul>
<p><b>2.3.2:</b></p>
<ul>
<li>Improve autotools makefiles to build the `SoundTouchDLL` dynamic-link link library with
C-style API. This library variation is easier to import and use from other programming
languages than the default C++ library.
</li>
</ul>
<p><b>2.3.1:</b></p>
<ul>
<li>Adjusted cmake build settings and header files that cmake installs</li>
</ul>
<p><b>2.3.0:</b></p>
<ul>
<li>Disable setting "SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION" by default. The original
purpose of this setting was to avoid performance penalty due to unaligned SIMD memory
accesses in old CPUs, but that is not any more issue in concurrent CPU SIMD implementations
and having this setting enabled can cause slight compromise in result quality.
</li>
<li>Bugfix: soundtouch.clear() to really clear whole processing pipeline state. Earlier
individual variables were left uncleared, which caused slightly different result if
the same audio stream were processed again after calling clear().
</li>
<li>Bugfix: TDstretch to align initial offset position to be in middle of correlation search
window. This ensures that with zero tempo change the output will be same as input.
</li>
<li>Bugfix: Fix a bug in TDstrectch with too small initial skipFract value that occurred
with certain processing parameter settings: Replace assert with assignment that
corrects the situation.
</li>
<li>Remove OpenMP "_init_threading" workaround from Android build as it's not needed with concurrent
Android SDKs any more.</li>
</ul>
<p><b>2.2:</b></p>
<ul>
<li>Improved source codes so that compiler can autovectorize them more effectively.
This brings remarkable improvement e.g. ARM cpus equipped with NEON vfpu: Bencmarked
2.4x improvement in execution speed in ARMv7l vs the previous SoundTouch version
for both integer and floating point sample types.
</li>
<li>Bugfix: Resolved bad sound quality when using integer sample types in non-x86 CPU</li>
<li>Bugfix: Fixed possible reading past end of array in BPM peak detection algorithm</li>
</ul>
<p><b>2.1.2:</b></p>
<ul>
<li>Bump version to 2.1.2 also in configure.ac. The earlier release had old version info for GNU autotools.</li>
</ul>
<p><b>2.1.1:</b></p>
<ul>
<li>Bugfixes: Fixed potential buffer overwrite bugs in WavFile routines. Replaced asserts with runtime exceptions.
</li>
<li>Android: Migrated the SoundTouch Android example to new Android Studio</li>
<li>Automake: unset ACLOCAL in bootstrap script in case earlier build script has set it</li>
</ul>
<p><b>2.1:</b></p>
<ul>
<li>Refactored C# interface example</li>
<li>Disable anti-alias filter when switch
@ -589,11 +683,13 @@ this corresponds to lowering the pitch by -0.318 semitones:</p>
</ul>
<p><b>2.0:</b></p>
<ul>
<li>Added functions to get initial processing latency, duration ratio between the original input and processed output tracks, and clarified reporting of input/output batch sizes</li>
<li>Added functions to get initial processing latency, duration ratio between the original input and processed
output tracks, and clarified reporting of input/output batch sizes</li>
<li>Fixed issue that added brief sequence of silence to beginning of output audio</li>
<li>Adjusted algorithm parameters to reduce reverberating effect at tempo slowdown</li>
<li>Bugfix: Fixed a glitch that could cause negative array indexing in quick seek algorithm</li>
<li>Bugfix: flush() didn't properly flush final samples from the pipeline on 2nd time in case that soundtouch object instance was recycled and used for processing a second audio stream.</li>
<li>Bugfix: flush() didn't properly flush final samples from the pipeline on 2nd time in case that soundtouch
object instance was recycled and used for processing a second audio stream.</li>
<li>Bugfix: Pi value had incorrect 9th/10th decimals</li>
<li>Added C# example application that uses SoundTouch dll library for processing MP3 files</li>
</ul>
@ -603,8 +699,10 @@ this corresponds to lowering the pitch by -0.318 semitones:</p>
</ul>
<p><b>1.9.1:</b></p>
<ul>
<li>Improved SoundTouch::flush() function so that it returns precisely the desired amount of samples for exact output duration control</li>
<li>Redesigned quickseek algorithm for improved sound quality when using the quickseek mode. The new quickseek algorithm can find 99% as good results as the
<li>Improved SoundTouch::flush() function so that it returns precisely the desired amount of samples for exact
output duration control</li>
<li>Redesigned quickseek algorithm for improved sound quality when using the quickseek mode. The new quickseek
algorithm can find 99% as good results as the
default full-scan mode, while the quickseek algorithm is remarkable less
CPU intensive.</li>
<li>Added adaptive integer divider scaling for improved sound quality when using integer processing algorithm
@ -612,7 +710,8 @@ this corresponds to lowering the pitch by -0.318 semitones:</p>
</ul>
<p><b>1.9:</b></p>
<ul>
<li>Added support for parallel computation support via OpenMP primitives for better performance in multicore systems.
<li>Added support for parallel computation support via OpenMP primitives for better performance in multicore
systems.
Benchmarks show that achieved parallel processing speedup improvement
typically range from +30% (x86 dual-core) to +180% (ARM quad-core). The
OpenMP optimizations are disabled by default, see OpenMP notes above in this
@ -783,11 +882,14 @@ accessing the FIFOSampleBuffer class from external files.</li>
<li> Initial release</li>
</ul>
<h3>5.2. SoundStretch application Change History </h3>
<p><b>2.3.3:</b></p>
<ul class="current_soundstretch">
<li>Added support for Asian / non-latin filenames in Windows. Gnu platform has supported them already earlier.</li>
</ul>
<p><b>1.9:</b></p>
<ul>
<li>Added support for WAV file 'fact' information chunk.</li>
</ul>
<p><b>1.7.0:</b></p>
<ul>
<li>Bugfixes in Wavfile: exception string formatting, avoid getLengthMs() integer
@ -856,13 +958,16 @@ submitted bugfixes:</p>
<li> Jamie Bullock</li>
<li> Chris Bryan</li>
<li> Jacek Caban</li>
<li> Marketa Calabkova</li>
<li> Brian Cameron</li>
<li> Jason Champion</li>
<li> Giuseppe Cigala</li>
<li> David Clark</li>
<li> Patrick Colis</li>
<li> Miquel Colon</li>
<li> Jim Credland</li>
<li> Sandro Cumerlato</li>
<li> Gerry Fan</li>
<li> Justin Frankel</li>
<li> Masa H.</li>
<li> Jason Garland</li>
@ -881,12 +986,14 @@ submitted bugfixes:</p>
<li> Michael Pruett</li>
<li> Rajeev Puran</li>
<li> RJ Ryan</li>
<li> Serge Sans Paille</li>
<li> John Sheehy</li>
<li> Tim Shuttleworth</li>
<li> Albert Sirvent</li>
<li> Tyson Smith</li>
<li> John Stumpo</li>
<li> Mario di Vece</li>
<li> Rémi Verschelde</li>
<li> Katja Vetter</li>
<li> Wu Q.</li>
</ul>
@ -908,6 +1015,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</p>
<p>---</p>
<p>commercial license alternative also available, contact author for details.</p>
<hr>
<p><i>README.html file updated in May-2018</i></p>
</body>
</html>

14
SoundTouchConfig.cmake.in Normal file
View File

@ -0,0 +1,14 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/SoundTouchTargets.cmake")
check_required_components(SoundTouch)
get_target_property(SoundTouch_LOCATION SoundTouch::SoundTouch LOCATION)
message(STATUS "Found SoundTouch: ${SoundTouch_LOCATION}")
if(@SOUNDTOUCH_DLL@)
check_required_components(SoundTouchDLL)
get_target_property(SoundTouchDLL_LOCATION SoundTouch::SoundTouchDLL LOCATION)
message(STATUS "Found SoundTouchDLL: ${SoundTouchDLL_LOCATION}")
endif()

View File

@ -1,8 +1,8 @@
set SOUND_DIR=d:\dev\test_sounds
set SOUND_DIR=c:\dev\test_sounds
set OUT_DIR=.
set TEST_NAME=semmari
set OUT_NAME=out
set SS=soundstretch
set SS=soundstretch_x64
set TEST_PARAM=-pitch=-3 -bpm
call %SS% %SOUND_DIR%\%TEST_NAME%-8b1.wav %OUT_DIR%\%OUT_NAME%-8b1.wav %TEST_PARAM%

View File

@ -1,5 +1,7 @@
#!/bin/sh
unset ACLOCAL
if [ "$1" = "--clean" ]
then
if [ -a Makefile ]
@ -14,9 +16,6 @@ then
rm -rf configure libtool aclocal.m4 `find . -name Makefile.in` autom4te*.cache config/config.guess config/config.h.in config/config.sub config/depcomp config/install-sh config/ltmain.sh config/missing config/mkinstalldirs config/stamp-h config/stamp-h.in
#gettextie files
#rm -f ABOUT-NLS config/config.rpath config/m4/codeset.m4 config/m4/gettext.m4 config/m4/glibc21.m4 config/m4/iconv.m4 config/m4/intdiv0.m4 config/m4/inttypes-pri.m4 config/m4/inttypes.m4 config/m4/inttypes_h.m4 config/m4/isc-posix.m4 config/m4/lcmessage.m4 config/m4/lib-ld.m4 config/m4/lib-link.m4 config/m4/lib-prefix.m4 config/m4/progtest.m4 config/m4/stdint_h.m4 config/m4/uintmax_t.m4 config/m4/ulonglong.m4 po/Makefile.in.in po/Rules-quot po/boldquot.sed po/en@boldquot.header po/en@quot.header po/insert-header.sin po/quot.sed po/remove-potcdate.sin
else
export AUTOMAKE="automake --add-missing --foreign --copy"
autoreconf -fisv && rm -f `find . -name "*~"` && rm -f ChangeLog

View File

@ -15,22 +15,25 @@ dnl this program; if not, write to the Free Software Foundation, Inc., 59 Temple
dnl Place - Suite 330, Boston, MA 02111-1307, USA
# Process this file with autoconf to produce a configure script.
AC_INIT([SoundTouch], [2.0.0], [http://www.surina.net/soundtouch])
AC_INIT([SoundTouch],[2.3.2],[http://www.surina.net/soundtouch])
dnl Default to libSoundTouch.so.$LIB_SONAME.0.0
LIB_SONAME=1
AC_SUBST(LIB_SONAME)
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_MACRO_DIR([config/m4])
AM_CONFIG_HEADER([config.h include/soundtouch_config.h])
AC_CONFIG_HEADERS([config.h include/soundtouch_config.h])
AM_INIT_AUTOMAKE
AM_SILENT_RULES([yes])
#AC_DISABLE_SHARED dnl This makes libtool only build static libs
AC_DISABLE_STATIC dnl This makes libtool only build shared libs
#AC_GNU_SOURCE dnl enable posix extensions in glibc
#AC_USE_SYSTEM_EXTENSIONS dnl enable posix extensions in glibc
AC_LANG(C++)
# Compiler flags. Apply -ffast-math to allow compiler autovectorization generate effective SIMD code for arm compilation
CXXFLAGS="${CXXFLAGS} -O3 -ffast-math -Wall -Wextra -Wzero-as-null-pointer-constant -Wno-unknown-pragmas"
# Set AR_FLAGS to avoid build warning "ar: `u' modifier ignored since `D' is the default (see `U')"
AR_FLAGS='cr'
@ -47,7 +50,7 @@ AC_PROG_INSTALL
#AC_PROG_LN_S
AC_PROG_MAKE_SET
AM_PROG_LIBTOOL dnl turn on using libtool
LT_INIT dnl turn on using libtool
@ -55,10 +58,11 @@ AM_PROG_LIBTOOL dnl turn on using libtool
dnl ############################################################################
dnl # Checks for header files #
dnl ############################################################################
AC_HEADER_STDC
#AC_HEADER_SYS_WAIT
# add any others you want to check for here
AC_CHECK_HEADERS([cpuid.h])
AC_CHECK_HEADERS([arm_neon.h])
if test "x$ac_cv_header_cpuid_h" = "xno"; then
AC_MSG_WARN([The cpuid.h file was not found therefore the x86 optimizations will be disabled.])
@ -77,31 +81,34 @@ AC_C_INLINE
AC_ARG_ENABLE(integer-samples,
[AC_HELP_STRING([--enable-integer-samples],
[use integer samples instead of floats
[default=no]])],,
[AS_HELP_STRING([--enable-integer-samples],[use integer samples instead of floats [default=no]])],,
[enable_integer_samples=no])
AC_ARG_ENABLE(openmp,
[AC_HELP_STRING([--enable-openmp],
[use parallel multicore calculation through OpenMP [default=no]])],,
[AS_HELP_STRING([--enable-openmp],[use parallel multicore calculation through OpenMP [default=no]])],,
[enable_openmp=no])
# Let the user enable/disable the x86 optimizations.
# Useful when compiling on non-x86 architectures.
AC_ARG_ENABLE([x86-optimizations],
[AS_HELP_STRING([--enable-x86-optimizations],
[use MMX or SSE optimization
[default=yes]])],[enable_x86_optimizations="${enableval}"],
[use MMX or SSE optimization [default=yes]])],[enable_x86_optimizations="${enableval}"],
[enable_x86_optimizations=yes])
# Let the user enable/disable the x86 optimizations.
# Useful when compiling on non-x86 architectures.
AC_ARG_ENABLE([neon-optimizations],
[AS_HELP_STRING([--enable-neon-optimizations],
[use ARM NEON optimization [default=yes]])],[enable_neon_optimizations="${enableval}"],
[enable_neon_optimizations=yes])
# Tell the Makefile.am if the user wants to disable optimizations.
# Makefile.am will enable them by default if support is available.
# Note: We check if optimizations are supported a few lines down.
AM_CONDITIONAL([X86_OPTIMIZATIONS], [test "x$enable_x86_optimizations" = "xyes"])
if test "x$enable_integer_samples" = "xyes"; then
echo "****** Integer sample type enabled ******"
AC_DEFINE(SOUNDTOUCH_INTEGER_SAMPLES,1,[Use Integer as Sample type])
@ -109,7 +116,7 @@ else
echo "****** Float sample type enabled ******"
AC_DEFINE(SOUNDTOUCH_FLOAT_SAMPLES,1,[Use Float as Sample type])
fi
AM_CONDITIONAL([SOUNDTOUCH_FLOAT_SAMPLES], [test "x$enable_integer_samples" != "xyes"])
if test "x$enable_openmp" = "xyes"; then
echo "****** openmp optimizations enabled ******"
@ -195,6 +202,52 @@ else
CPPFLAGS="-DSOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS $CPPFLAGS"
fi
if test "x$enable_neon_optimizations" = "xyes" -a "x$ac_cv_header_arm_neon_h" = "xyes"; then
# Check for ARM NEON support
original_saved_CXXFLAGS=$CXXFLAGS
have_neon=no
CXXFLAGS="-mfpu=neon -march=native $CXXFLAGS"
# Check if can compile neon code using intrinsics, require GCC >= 4.3 for autovectorization.
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3))
#error "Need GCC >= 4.3 for neon autovectorization"
#endif
#include <arm_neon.h>
int main () {
int32x4_t t = {1};
return vaddq_s32(t,t)[0] == 2;
}]])],[have_neon=yes])
CXXFLAGS=$original_saved_CXXFLAGS
if test "x$have_neon" = "xyes" ; then
echo "****** NEON support enabled ******"
CPPFLAGS="-mfpu=neon -march=native -mtune=native $CPPFLAGS"
AC_DEFINE(SOUNDTOUCH_USE_NEON,1,[Use ARM NEON extension])
fi
fi
AC_CANONICAL_HOST
HOST_OS=""
AS_CASE([$host_cpu],
[x86_64],
[
x86_64=true
x86=true
],
[i?86],
[
x86=true
])
AM_CONDITIONAL([X86], [test "$x86" = true])
AM_CONDITIONAL([X86_64], [test "$x86_64" = true])
AC_SUBST([HOST_OS])
# Set AM_CXXFLAGS
AC_SUBST([AM_CXXFLAGS], [$AM_CXXFLAGS])
@ -217,8 +270,6 @@ AM_CONDITIONAL([HAVE_SSE], [test "x$have_sse_intrinsics" = "xyes"])
dnl ############################################################################
dnl # Checks for library functions/classes #
dnl ############################################################################
AC_FUNC_MALLOC
AC_TYPE_SIGNAL
dnl make -lm get added to the LIBS
AC_CHECK_LIB(m, sqrt,,AC_MSG_ERROR([compatible libc math library not found]))
@ -251,11 +302,12 @@ AC_CONFIG_FILES([
source/Makefile
source/SoundTouch/Makefile
source/SoundStretch/Makefile
source/SoundTouchDLL/Makefile
include/Makefile
])
AC_OUTPUT(
soundtouch.pc
)
AC_CONFIG_FILES([soundtouch.pc
])
AC_OUTPUT
dnl use 'echo' to put stuff here if you want a message to the builder

View File

@ -196,7 +196,7 @@ namespace soundtouch
/// - "values" receive array of beat detection strengths
/// - max_num indicates max.size of "pos" and "values" array.
///
/// You can query a suitable array sized by calling this with NULL in "pos" & "values".
/// You can query a suitable array sized by calling this with nullptr in "pos" & "values".
///
/// \return number of beats in the arrays.
int getBeats(float *pos, float *strength, int max_num);

View File

@ -91,7 +91,7 @@ public:
);
/// destructor
~FIFOSampleBuffer();
~FIFOSampleBuffer() override;
/// Returns a pointer to the beginning of the output samples.
/// This function is provided for accessing the output samples directly.
@ -100,7 +100,7 @@ public:
/// When using this function to output samples, also remember to 'remove' the
/// output samples from the buffer by calling the
/// 'receiveSamples(numSamples)' function
virtual SAMPLETYPE *ptrBegin();
virtual SAMPLETYPE *ptrBegin() override;
/// Returns a pointer to the end of the used part of the sample buffer (i.e.
/// where the new samples are to be inserted). This function may be used for
@ -121,7 +121,7 @@ public:
/// the sample buffer.
virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
uint numSamples ///< Number of samples to insert.
);
) override;
/// Adjusts the book-keeping to increase number of samples in the buffer without
/// copying any actual samples.
@ -139,7 +139,7 @@ public:
/// \return Number of samples returned.
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
uint maxSamples ///< How many samples to receive at max.
);
) override;
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere.
@ -147,10 +147,10 @@ public:
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
);
) override;
/// Returns number of samples currently available.
virtual uint numSamples() const;
virtual uint numSamples() const override;
/// Sets number of channels, 1 = mono, 2 = stereo.
void setChannels(int numChannels);
@ -162,14 +162,17 @@ public:
}
/// Returns nonzero if there aren't any samples available for outputting.
virtual int isEmpty() const;
virtual int isEmpty() const override;
/// Clears all the samples.
virtual void clear();
virtual void clear() override;
/// allow trimming (downwards) amount of samples in pipeline.
/// Returns adjusted amount of samples
uint adjustAmountOfSamples(uint numSamples);
uint adjustAmountOfSamples(uint numSamples) override;
/// Add silence to end of buffer
void addSilent(uint nSamples);
};
}

View File

@ -88,11 +88,11 @@ public:
void moveSamples(FIFOSamplePipe &other ///< Other pipe instance where from the receive the data.
)
{
int oNumSamples = other.numSamples();
const uint oNumSamples = other.numSamples();
putSamples(other.ptrBegin(), oNumSamples);
other.receiveSamples(oNumSamples);
};
}
/// Output samples from beginning of the sample buffer. Copies requested samples to
/// output buffer and removes them from the sample buffer. If there are less than
@ -144,8 +144,8 @@ protected:
/// Sets output pipe.
void setOutPipe(FIFOSamplePipe *pOutput)
{
assert(output == NULL);
assert(pOutput != NULL);
assert(output == nullptr);
assert(pOutput != nullptr);
output = pOutput;
}
@ -153,7 +153,7 @@ protected:
/// 'setOutPipe' function.
FIFOProcessor()
{
output = NULL;
output = nullptr;
}
/// Constructor. Configures output pipe.
@ -164,7 +164,7 @@ protected:
}
/// Destructor.
virtual ~FIFOProcessor()
virtual ~FIFOProcessor() override
{
}
@ -175,7 +175,7 @@ protected:
/// When using this function to output samples, also remember to 'remove' the
/// output samples from the buffer by calling the
/// 'receiveSamples(numSamples)' function
virtual SAMPLETYPE *ptrBegin()
virtual SAMPLETYPE *ptrBegin() override
{
return output->ptrBegin();
}
@ -189,7 +189,7 @@ public:
/// \return Number of samples returned.
virtual uint receiveSamples(SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples.
uint maxSamples ///< How many samples to receive at max.
)
) override
{
return output->receiveSamples(outBuffer, maxSamples);
}
@ -200,26 +200,26 @@ public:
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
)
) override
{
return output->receiveSamples(maxSamples);
}
/// Returns number of samples currently available.
virtual uint numSamples() const
virtual uint numSamples() const override
{
return output->numSamples();
}
/// Returns nonzero if there aren't any samples available for outputting.
virtual int isEmpty() const
virtual int isEmpty() const override
{
return output->isEmpty();
}
/// allow trimming (downwards) amount of samples in pipeline.
/// Returns adjusted amount of samples
virtual uint adjustAmountOfSamples(uint numSamples)
virtual uint adjustAmountOfSamples(uint numSamples) override
{
return output->adjustAmountOfSamples(numSamples);
}

View File

@ -56,8 +56,9 @@ typedef unsigned long ulong;
namespace soundtouch
{
/// Max allowed number of channels
#define SOUNDTOUCH_MAX_CHANNELS 16
/// Max allowed number of channels. This is not a hard limit but to have some
/// maximum value for argument sanity checks -- can be increased if necessary
#define SOUNDTOUCH_MAX_CHANNELS 32
/// Activate these undef's to overrule the possible sampletype
/// setting inherited from some other header file:
@ -121,10 +122,10 @@ namespace soundtouch
#endif
// If defined, allows the SIMD-optimized routines to take minor shortcuts
// for improved performance. Undefine to require faithfully similar SIMD
// calculations as in normal C implementation.
#define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION 1
// If defined, allows the SIMD-optimized routines to skip unevenly aligned
// memory offsets that can cause performance penalty in some SIMD implementations.
// Causes slight compromise in sound quality.
// #define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION 1
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
@ -149,8 +150,9 @@ namespace soundtouch
// floating point samples
typedef float SAMPLETYPE;
// data type for sample accumulation: Use double to utilize full precision.
typedef double LONG_SAMPLETYPE;
// data type for sample accumulation: Use float also here to enable
// efficient autovectorization
typedef float LONG_SAMPLETYPE;
#ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
// Allow SSE optimizations
@ -159,7 +161,13 @@ namespace soundtouch
#endif // SOUNDTOUCH_INTEGER_SAMPLES
};
#if ((SOUNDTOUCH_ALLOW_SSE) || (__SSE__) || (SOUNDTOUCH_USE_NEON))
#if SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
#define ST_SIMD_AVOID_UNALIGNED
#endif
#endif
}
// define ST_NO_EXCEPTION_HANDLING switch to disable throwing std exceptions:
// #define ST_NO_EXCEPTION_HANDLING 1

View File

@ -72,10 +72,10 @@ namespace soundtouch
{
/// Soundtouch library version string
#define SOUNDTOUCH_VERSION "2.1pre"
#define SOUNDTOUCH_VERSION "2.3.3"
/// SoundTouch library version id
#define SOUNDTOUCH_VERSION_ID (20009)
#define SOUNDTOUCH_VERSION_ID (20303)
//
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
@ -209,7 +209,7 @@ protected :
public:
SoundTouch();
virtual ~SoundTouch();
virtual ~SoundTouch() override;
/// Get SoundTouch library version string
static const char *getVersionString();
@ -287,7 +287,7 @@ public:
uint numSamples ///< Number of samples in buffer. Notice
///< that in case of stereo-sound a single sample
///< contains data for both channels.
);
) override;
/// Output samples from beginning of the sample buffer. Copies requested samples to
/// output buffer and removes them from the sample buffer. If there are less than
@ -296,7 +296,7 @@ public:
/// \return Number of samples returned.
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
uint maxSamples ///< How many samples to receive at max.
);
) override;
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere.
@ -304,11 +304,11 @@ public:
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
);
) override;
/// Clears all the samples in the object's output and internal processing
/// buffers.
virtual void clear();
virtual void clear() override;
/// Changes a setting controlling the processing system behaviour. See the
/// 'SETTING_...' defines for available setting ID's.

View File

@ -0,0 +1,3 @@
// autotools configuration step replaces this file with a configured version.
// this empty file stub is provided to avoid error about missing include file
// when not using autotools build

View File

@ -3,3 +3,6 @@
/* Use Integer as Sample type */
#undef SOUNDTOUCH_INTEGER_SAMPLES
/* Use ARM NEON extension */
#undef SOUNDTOUCH_USE_NEON

View File

@ -31,8 +31,9 @@ echo ***************************************************************************
echo **
echo ** ERROR: Visual Studio path not set.
echo **
echo ** Run "vsvars32.bat" or "vcvars32.bat" from Visual Studio installation dir,
echo ** e.g. "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin",
echo ** Open "tools"->"Developer Command Line" from Visual Studio IDE, or
echo ** run "vcvars32.bat" from Visual Studio installation dir, e.g.
echo ** "C:\Program Files (x86)\Microsoft Visual Studio xxx\VC\bin",
echo ** then try again.
echo **
echo ****************************************************************************

View File

@ -1,5 +1,7 @@
# SoundTouch library
## About
SoundTouch is an open-source audio processing library that allows changing the sound tempo, pitch and playback rate parameters independently from each other:
* Change **tempo** while maintaining the original pitch
* Change **pitch** while maintaining the original tempo
@ -7,7 +9,9 @@ SoundTouch is an open-source audio processing library that allows changing the s
same time
* Change any combination of tempo/pitch/rate
Visit [SoundTouch website](https://www.surina.net/soundtouch) and see the [README file](README.html) for more information and audio examples.
Visit [SoundTouch website](https://www.surina.net/soundtouch) and see the [README file](https://www.surina.net/soundtouch/readme.html) for more information and audio examples.
### The latest stable release is 2.3.3
## Example
@ -17,7 +21,7 @@ Use SoundStretch example app for modifying wav audio files, for example as follo
soundstretch my_original_file.wav output_file.wav -tempo=+15 -pitch=-3
```
See the [README file](README.html) for more usage examples and instructions how to build SoundTouch + SoundStretch.
See the [README file](http://soundtouch.surina.net/README.html) for more usage examples and instructions how to build SoundTouch + SoundStretch.
Ready [SoundStretch application executables](https://www.surina.net/soundtouch/download.html) are available for download for Windows and Mac OS.
@ -33,6 +37,18 @@ SoundTouch is written in C++ and compiles in virtually any platform:
The source code package includes dynamic library import modules for C#, Java and Pascal/Delphi languages.
## Tarballs
Source code release tarballs:
* https://www.surina.net/soundtouch/soundtouch-2.3.3.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.3.2.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.3.1.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.3.0.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.2.0.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.1.2.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.1.1.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.0.0.tar.gz
## License
SoundTouch is released under LGPL v2.1:

View File

@ -103,6 +103,7 @@ in the <strong>soundtouch-jni.cpp </strong>source code file for more details.</p
the Java interface class that loasd & accesses the JNI routines in the natively compiled library.
The example Android application uses this class as interface for processing audio files
with SoundTouch.</li>
<li><b>Android-lib/build.gradle</b>: Top level build script file for Android Studio 3.1.4+</li>
</ul>
<p>
Feel free to examine and extend the provided cpp/java source code example file pair to

View File

@ -0,0 +1,55 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
}
}
allprojects {
repositories {
jcenter()
google()
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "net.surina.soundtouchexample"
minSdkVersion 14
targetSdkVersion 21
externalNativeBuild.ndkBuild {
arguments "NDK_APPLICATION=jni/Application.mk",
"APP_ALLOW_MISSING_DEPS:=true"
}
}
sourceSets {
main {
manifest.srcFile "./AndroidManifest.xml"
java.srcDirs = ["./src"]
res.srcDirs = ["res"]
}
}
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
}
}
buildTypes {
release {
minifyEnabled false
}
}
}

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Sat Jan 13 09:12:34 PST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-all.zip

172
source/Android-lib/gradlew vendored Executable file
View File

@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
source/Android-lib/gradlew.bat vendored Normal file
View File

@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -1,22 +1,8 @@
# Copyright (C) 2010 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../SoundStretch
# *** Remember: Change -O0 into -O2 in add-applications.mk ***
LOCAL_MODULE := soundtouch
@ -38,7 +24,7 @@ LOCAL_LDLIBS += -llog
# Custom Flags:
# -fvisibility=hidden : don't export all symbols
LOCAL_CFLAGS += -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections
LOCAL_CFLAGS += -fvisibility=hidden -fdata-sections -ffunction-sections -ffast-math
# OpenMP mode : enable these flags to enable using OpenMP for parallel computation
#LOCAL_CFLAGS += -fopenmp

View File

@ -4,6 +4,6 @@
APP_ABI := all #armeabi-v7a armeabi
APP_OPTIM := release
APP_STL := stlport_static
APP_STL := c++_static
APP_CPPFLAGS := -fexceptions # -D SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS

View File

@ -41,12 +41,12 @@ static void _setErrmsg(const char *msg)
_errMsg = msg;
}
#if 0 // apparently following workaround not needed any more with concurrent Android SDKs
#ifdef _OPENMP
#include <pthread.h>
extern pthread_key_t gomp_tls_key;
static void * _p_gomp_tls = NULL;
static void * _p_gomp_tls = nullptr;
/// Function to initialize threading for OpenMP.
///
@ -54,7 +54,7 @@ static void * _p_gomp_tls = NULL;
/// called from the Android App main thread because in the main thread the gomp_tls storage is
/// properly set, however, Android does not properly initialize gomp_tls storage for other threads.
/// Thus if OpenMP routines are invoked from some other thread than the main thread,
/// the OpenMP routine will crash the application due to NULL pointer access on uninitialized storage.
/// the OpenMP routine will crash the application due to nullptr access on uninitialized storage.
///
/// This workaround stores the gomp_tls storage from main thread, and copies to other threads.
/// In order this to work, the Application main thread needws to call at least "getVersionString"
@ -63,7 +63,7 @@ static int _init_threading(bool warn)
{
void *ptr = pthread_getspecific(gomp_tls_key);
LOGV("JNI thread-specific TLS storage %ld", (long)ptr);
if (ptr == NULL)
if (ptr == nullptr)
{
LOGV("JNI set missing TLS storage to %ld", (long)_p_gomp_tls);
pthread_setspecific(gomp_tls_key, _p_gomp_tls);
@ -74,7 +74,7 @@ static int _init_threading(bool warn)
_p_gomp_tls = ptr;
}
// Where critical, show warning if storage still not properly initialized
if ((warn) && (_p_gomp_tls == NULL))
if ((warn) && (_p_gomp_tls == nullptr))
{
_setErrmsg("Error - OpenMP threading not properly initialized: Call SoundTouch.getVersionString() from the App main thread!");
return -1;
@ -90,6 +90,7 @@ static int _init_threading(bool warn)
}
#endif
#endif
// Processes the sound file
static void _processFile(SoundTouch *pSoundTouch, const char *inFileName, const char *outFileName)
@ -162,8 +163,9 @@ extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getVersionSt
// Call example SoundTouch routine
verStr = SoundTouch::getVersionString();
/// gomp_tls storage bug workaround - see comments in _init_threading() function!
_init_threading(false);
// gomp_tls storage bug workaround - see comments in _init_threading() function!
// update: apparently this is not needed any more with concurrent Android SDKs
// _init_threading(false);
int threads = 0;
#pragma omp parallel
@ -232,7 +234,8 @@ extern "C" DLL_PUBLIC int Java_net_surina_soundtouch_SoundTouch_processFile(JNIE
LOGV("JNI process file %s", inputFile);
/// gomp_tls storage bug workaround - see comments in _init_threading() function!
if (_init_threading(true)) return -1;
// update: apparently this is not needed any more with concurrent Android SDKs
// if (_init_threading(true)) return -1;
try
{

View File

@ -17,8 +17,9 @@
include $(top_srcdir)/config/am_include.mk
if SOUNDTOUCH_FLOAT_SAMPLES
# build SoundTouchDLL only if float samples used
SUBDIRS=SoundTouch SoundStretch SoundTouchDLL
else
SUBDIRS=SoundTouch SoundStretch
# set to something if you want other stuff to be included in the distribution tarball
#EXTRA_DIST=
endif

View File

@ -40,11 +40,11 @@ soundstretch_SOURCES=main.cpp RunParameters.cpp WavFile.cpp
soundstretch_LDADD=../SoundTouch/libSoundTouch.la -lm
## linker flags.
# OP 2011-7-17 Linker flag -s disabled to prevent stripping symbols by default
# Linker flag -s disabled to prevent stripping symbols by default
#soundstretch_LDFLAGS=-s
## additional compiler flags
soundstretch_CXXFLAGS=-O3 $(AM_CXXFLAGS)
soundstretch_CXXFLAGS=$(AM_CXXFLAGS)
#clean-local:
# -rm -f additional-files-to-remove-on-make-clean

View File

@ -30,12 +30,15 @@
////////////////////////////////////////////////////////////////////////////////
#include <string>
#include <stdlib.h>
#include <cstdlib>
#include "RunParameters.h"
using namespace std;
namespace soundstretch
{
// Program usage instructions
static const char licenseText[] =
@ -94,9 +97,8 @@ static int _toLowerCase(int c)
return c;
}
// Constructor
RunParameters::RunParameters(const int nParams, const char * const paramStr[])
RunParameters::RunParameters(int nParams, const CHARTYPE* paramStr[])
{
int i;
int nFirstParam;
@ -112,28 +114,17 @@ RunParameters::RunParameters(const int nParams, const char * const paramStr[])
}
string msg = whatText;
msg += usage;
ST_THROW_RT_ERROR(msg.c_str());
throw(msg);
}
inFileName = NULL;
outFileName = NULL;
tempoDelta = 0;
pitchDelta = 0;
rateDelta = 0;
quick = 0;
noAntiAlias = 0;
goalBPM = 0;
speech = false;
detectBPM = false;
// Get input & output file names
inFileName = (char*)paramStr[1];
outFileName = (char*)paramStr[2];
inFileName = paramStr[1];
outFileName = paramStr[2];
if (outFileName[0] == '-')
{
// no outputfile name was given but parameters
outFileName = NULL;
// outputfile name was omitted but other parameter switches given instead
outFileName = STRING_CONST("");
nFirstParam = 2;
}
else
@ -182,25 +173,33 @@ void RunParameters::checkLimits()
}
}
// Unknown switch parameter -- throws an exception with an error message
void RunParameters::throwIllegalParamExp(const string &str) const
// Convert STRING to std::string. Actually needed only if STRING is std::wstring, but conversion penalty is negligible
std::string convertString(const STRING& str)
{
string msg = "ERROR : Illegal parameter \"";
msg += str;
msg += "\".\n\n";
msg += usage;
ST_THROW_RT_ERROR(msg.c_str());
std::string res;
for (auto c : str)
{
res += (char)c;
}
return res;
}
// Unknown switch parameter -- throws an exception with an error message
void RunParameters::throwIllegalParamExp(const STRING &str) const
{
string msg = "ERROR : Illegal parameter \"";
msg += convertString(str);
msg += "\".\n\n";
msg += usage;
ST_THROW_RT_ERROR(msg);
}
void RunParameters::throwLicense() const
{
ST_THROW_RT_ERROR(licenseText);
}
float RunParameters::parseSwitchValue(const string &str) const
double RunParameters::parseSwitchValue(const STRING& str) const
{
int pos;
@ -212,14 +211,14 @@ float RunParameters::parseSwitchValue(const string &str) const
}
// Read numerical parameter value after '='
return (float)atof(str.substr(pos + 1).c_str());
return stof(str.substr(pos + 1).c_str());
}
// Interprets a single switch parameter string of format "-switch=xx"
// Valid switches are "-tempo=xx", "-pitch=xx" and "-rate=xx". Stores
// switch values into 'params' structure.
void RunParameters::parseSwitchParam(const string &str)
void RunParameters::parseSwitchParam(const STRING& str)
{
int upS;
@ -289,3 +288,5 @@ void RunParameters::parseSwitchParam(const string &str)
throwIllegalParamExp(str);
}
}
}

View File

@ -32,34 +32,39 @@
#ifndef RUNPARAMETERS_H
#define RUNPARAMETERS_H
#include "STTypes.h"
#include <string>
#include "STTypes.h"
#include "SS_CharTypes.h"
#include "WavFile.h"
using namespace std;
namespace soundstretch
{
/// Parses command line parameters into program parameters
class RunParameters
{
private:
void throwIllegalParamExp(const string &str) const;
void throwIllegalParamExp(const STRING& str) const;
void throwLicense() const;
void parseSwitchParam(const string &str);
void parseSwitchParam(const STRING& str);
void checkLimits();
float parseSwitchValue(const string &str) const;
double parseSwitchValue(const STRING& tr) const;
public:
char *inFileName;
char *outFileName;
float tempoDelta;
float pitchDelta;
float rateDelta;
int quick;
int noAntiAlias;
float goalBPM;
bool detectBPM;
bool speech;
STRING inFileName;
STRING outFileName;
double tempoDelta{ 0 };
double pitchDelta{ 0 };
double rateDelta{ 0 };
int quick{ 0 };
int noAntiAlias{ 0 };
double goalBPM{ 0 };
bool detectBPM{ false };
bool speech{ false };
RunParameters(const int nParams, const char * const paramStr[]);
RunParameters(int nParams, const CHARTYPE* paramStr[]);
};
}
#endif

View File

@ -0,0 +1,52 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Char type for SoundStretch
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef SS_CHARTYPE_H
#define SS_CHARTYPE_H
#include <string>
namespace soundstretch
{
#if _WIN32
// wide-char types for supporting non-latin file paths in Windows
using CHARTYPE = wchar_t;
using STRING = std::wstring;
#define STRING_CONST(x) (L"" x)
#else
// gnu platform can natively support UTF-8 paths using "char*" set
using CHARTYPE = char;
using STRING = std::string;
#define STRING_CONST(x) (x)
#endif
}
#endif //SS_CHARTYPE_H

View File

@ -42,14 +42,23 @@
#include <string>
#include <sstream>
#include <cstring>
#include <assert.h>
#include <limits.h>
#include <cassert>
#include <climits>
#include "WavFile.h"
#include "STTypes.h"
using namespace std;
namespace soundstretch
{
#if _WIN32
#define FOPEN(name, mode) _wfopen(name, STRING_CONST(mode))
#else
#define FOPEN(name, mode) fopen(name, mode)
#endif
static const char riffStr[] = "RIFF";
static const char waveStr[] = "WAVE";
static const char fmtStr[] = "fmt ";
@ -123,7 +132,7 @@ static const char dataStr[] = "data";
}
// dummy helper-function
static inline void _swap16Buffer(short *pData, int numBytes)
static inline void _swap16Buffer(short*, int)
{
// do nothing
}
@ -138,7 +147,7 @@ static const char dataStr[] = "data";
WavFileBase::WavFileBase()
{
convBuff = NULL;
convBuff = nullptr;
convBuffSize = 0;
}
@ -169,17 +178,13 @@ void *WavFileBase::getConvBuffer(int sizeBytes)
// Class WavInFile
//
WavInFile::WavInFile(const char *fileName)
WavInFile::WavInFile(const STRING& fileName)
{
// Try to open the file for reading
fptr = fopen(fileName, "rb");
if (fptr == NULL)
fptr = FOPEN(fileName.c_str(), "rb");
if (fptr == nullptr)
{
// didn't succeed
string msg = "Error : Unable to open file \"";
msg += fileName;
msg += "\" for reading.";
ST_THROW_RT_ERROR(msg.c_str());
ST_THROW_RT_ERROR("Error : Unable to open file for reading.");
}
init();
@ -192,9 +197,7 @@ WavInFile::WavInFile(FILE *file)
fptr = file;
if (!file)
{
// didn't succeed
string msg = "Error : Unable to access input stream for reading";
ST_THROW_RT_ERROR(msg.c_str());
ST_THROW_RT_ERROR("Error : Unable to access input stream for reading");
}
init();
@ -213,7 +216,6 @@ void WavInFile::init()
hdrsOk = readWavHeaders();
if (hdrsOk != 0)
{
// Something didn't match in the wav file headers
ST_THROW_RT_ERROR("Input file is corrupt or not a WAV file");
}
@ -223,7 +225,6 @@ void WavInFile::init()
(header.format.byte_per_sample < 1) || (header.format.byte_per_sample > 320) ||
(header.format.bits_per_sample < 8) || (header.format.bits_per_sample > 32))
{
// Something didn't match in the wav file headers
ST_THROW_RT_ERROR("Error: Illegal wav file header format parameters.");
}
@ -234,7 +235,7 @@ void WavInFile::init()
WavInFile::~WavInFile()
{
if (fptr) fclose(fptr);
fptr = NULL;
fptr = nullptr;
}
@ -450,7 +451,7 @@ int WavInFile::read(float *buffer, int maxElems)
int WavInFile::eof() const
{
// return true if all data has been read or file eof has reached
return (dataRead == header.data.data_len || feof(fptr));
return ((uint)dataRead == header.data.data_len || feof(fptr));
}
@ -703,17 +704,13 @@ uint WavInFile::getElapsedMS() const
// Class WavOutFile
//
WavOutFile::WavOutFile(const char *fileName, int sampleRate, int bits, int channels)
WavOutFile::WavOutFile(const STRING& fileName, int sampleRate, int bits, int channels)
{
bytesWritten = 0;
fptr = fopen(fileName, "wb");
if (fptr == NULL)
fptr = FOPEN(fileName.c_str(), "wb");
if (fptr == nullptr)
{
string msg = "Error : Unable to open file \"";
msg += fileName;
msg += "\" for writing.";
//pmsg = msg.c_str;
ST_THROW_RT_ERROR(msg.c_str());
ST_THROW_RT_ERROR("Error : Unable to open file for writing.");
}
fillInHeader(sampleRate, bits, channels);
@ -725,10 +722,9 @@ WavOutFile::WavOutFile(FILE *file, int sampleRate, int bits, int channels)
{
bytesWritten = 0;
fptr = file;
if (fptr == NULL)
if (fptr == nullptr)
{
string msg = "Error : Unable to access output file stream.";
ST_THROW_RT_ERROR(msg.c_str());
ST_THROW_RT_ERROR("Error : Unable to access output file stream.");
}
fillInHeader(sampleRate, bits, channels);
@ -740,7 +736,7 @@ WavOutFile::~WavOutFile()
{
finishHeader();
if (fptr) fclose(fptr);
fptr = NULL;
fptr = nullptr;
}
@ -875,7 +871,7 @@ void WavOutFile::write(const short *buffer, int numElems)
// use temp buffer to swap byte order if necessary
short* pTemp = (short*)getConvBuffer(numElems * sizeof(short));
memcpy(pTemp, buffer, numElems * 2);
memcpy(pTemp, buffer, (size_t)numElems * 2L);
_swap16Buffer(pTemp, numElems);
res = (int)fwrite(pTemp, 2, numElems, fptr);
@ -924,7 +920,7 @@ void WavOutFile::write(const float *buffer, int numElems)
bytesPerSample = header.format.bits_per_sample / 8;
numBytes = numElems * bytesPerSample;
short *temp = (short*)getConvBuffer(numBytes);
void* temp = getConvBuffer(numBytes + 7); // round bit up to avoid buffer overrun with 24bit-value assignment
switch (bytesPerSample)
{
@ -984,3 +980,5 @@ void WavOutFile::write(const float *buffer, int numElems)
}
bytesWritten += numBytes;
}
}

View File

@ -40,7 +40,12 @@
#ifndef WAVFILE_H
#define WAVFILE_H
#include <stdio.h>
#include <cstdio>
#include <string>
#include "SS_CharTypes.h"
namespace soundstretch
{
#ifndef uint
typedef unsigned int uint;
@ -118,9 +123,6 @@ private:
/// File pointer.
FILE *fptr;
/// Position within the audio stream
long position;
/// Counter of how many bytes of sample data have been read from the file.
long dataRead;
@ -148,7 +150,7 @@ private:
public:
/// Constructor: Opens the given WAV file. If the file can't be opened,
/// throws 'runtime_error' exception.
WavInFile(const char *filename);
WavInFile(const STRING& filename);
WavInFile(FILE *file);
@ -244,7 +246,7 @@ private:
public:
/// Constructor: Creates a new WAV file. Throws a 'runtime_error' exception
/// if file creation fails.
WavOutFile(const char *fileName, ///< Filename
WavOutFile(const STRING& fileName, ///< Filename
int sampleRate, ///< Sample rate (e.g. 44100 etc)
int bits, ///< Bits per sample (8 or 16 bits)
int channels ///< Number of channels (1=mono, 2=stereo)
@ -274,4 +276,6 @@ public:
);
};
}
#endif

View File

@ -29,10 +29,12 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <memory>
#include <stdexcept>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <string>
#include <cstdio>
#include <ctime>
#include "RunParameters.h"
#include "WavFile.h"
#include "SoundTouch.h"
@ -41,6 +43,9 @@
using namespace soundtouch;
using namespace std;
namespace soundstretch
{
// Processing chunk size (size chosen to be divisible by 2, 4, 6, 8, 10, 12, 14, 16 channels ...)
#define BUFF_SIZE 6720
@ -68,76 +73,67 @@ static const char _helloText[] =
"more information.\n"
"\n";
static void openFiles(WavInFile **inFile, WavOutFile **outFile, const RunParameters *params)
static void openFiles(unique_ptr<WavInFile>& inFile, unique_ptr<WavOutFile>& outFile, const RunParameters& params)
{
int bits, samplerate, channels;
if (strcmp(params->inFileName, "stdin") == 0)
if (params.inFileName == STRING_CONST("stdin"))
{
// used 'stdin' as input file
SET_STREAM_TO_BIN_MODE(stdin);
*inFile = new WavInFile(stdin);
inFile = make_unique<WavInFile>(stdin);
}
else
{
// open input file...
*inFile = new WavInFile(params->inFileName);
inFile = make_unique<WavInFile>(params.inFileName.c_str());
}
// ... open output file with same sound parameters
bits = (int)(*inFile)->getNumBits();
samplerate = (int)(*inFile)->getSampleRate();
channels = (int)(*inFile)->getNumChannels();
const int bits = (int)inFile->getNumBits();
const int samplerate = (int)inFile->getSampleRate();
const int channels = (int)inFile->getNumChannels();
if (params->outFileName)
if (!params.outFileName.empty())
{
if (strcmp(params->outFileName, "stdout") == 0)
if (params.outFileName == STRING_CONST("stdout"))
{
SET_STREAM_TO_BIN_MODE(stdout);
*outFile = new WavOutFile(stdout, samplerate, bits, channels);
outFile = make_unique<WavOutFile>(stdout, samplerate, bits, channels);
}
else
{
*outFile = new WavOutFile(params->outFileName, samplerate, bits, channels);
outFile = make_unique<WavOutFile>(params.outFileName.c_str(), samplerate, bits, channels);
}
}
else
{
*outFile = NULL;
}
}
// Sets the 'SoundTouch' object up according to input file sound format &
// command line parameters
static void setup(SoundTouch *pSoundTouch, const WavInFile *inFile, const RunParameters *params)
static void setup(SoundTouch& soundTouch, const WavInFile& inFile, const RunParameters& params)
{
int sampleRate;
int channels;
const int sampleRate = (int)inFile.getSampleRate();
const int channels = (int)inFile.getNumChannels();
soundTouch.setSampleRate(sampleRate);
soundTouch.setChannels(channels);
sampleRate = (int)inFile->getSampleRate();
channels = (int)inFile->getNumChannels();
pSoundTouch->setSampleRate(sampleRate);
pSoundTouch->setChannels(channels);
soundTouch.setTempoChange(params.tempoDelta);
soundTouch.setPitchSemiTones(params.pitchDelta);
soundTouch.setRateChange(params.rateDelta);
pSoundTouch->setTempoChange(params->tempoDelta);
pSoundTouch->setPitchSemiTones(params->pitchDelta);
pSoundTouch->setRateChange(params->rateDelta);
soundTouch.setSetting(SETTING_USE_QUICKSEEK, params.quick);
soundTouch.setSetting(SETTING_USE_AA_FILTER, !(params.noAntiAlias));
pSoundTouch->setSetting(SETTING_USE_QUICKSEEK, params->quick);
pSoundTouch->setSetting(SETTING_USE_AA_FILTER, !(params->noAntiAlias));
if (params->speech)
if (params.speech)
{
// use settings for speech processing
pSoundTouch->setSetting(SETTING_SEQUENCE_MS, 40);
pSoundTouch->setSetting(SETTING_SEEKWINDOW_MS, 15);
pSoundTouch->setSetting(SETTING_OVERLAP_MS, 8);
soundTouch.setSetting(SETTING_SEQUENCE_MS, 40);
soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 15);
soundTouch.setSetting(SETTING_OVERLAP_MS, 8);
fprintf(stderr, "Tune processing parameters for speech processing.\n");
}
// print processing information
if (params->outFileName)
if (!params.outFileName.empty())
{
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
fprintf(stderr, "Uses 16bit integer sample type in processing.\n\n");
@ -149,9 +145,9 @@ static void setup(SoundTouch *pSoundTouch, const WavInFile *inFile, const RunPar
#endif
// print processing information only if outFileName given i.e. some processing will happen
fprintf(stderr, "Processing the file with the following changes:\n");
fprintf(stderr, " tempo change = %+g %%\n", params->tempoDelta);
fprintf(stderr, " pitch change = %+g semitones\n", params->pitchDelta);
fprintf(stderr, " rate change = %+g %%\n\n", params->rateDelta);
fprintf(stderr, " tempo change = %+lg %%\n", params.tempoDelta);
fprintf(stderr, " pitch change = %+lg semitones\n", params.pitchDelta);
fprintf(stderr, " rate change = %+lg %%\n\n", params.rateDelta);
fprintf(stderr, "Working...");
}
else
@ -165,30 +161,24 @@ static void setup(SoundTouch *pSoundTouch, const WavInFile *inFile, const RunPar
// Processes the sound
static void process(SoundTouch *pSoundTouch, WavInFile *inFile, WavOutFile *outFile)
static void process(SoundTouch& soundTouch, WavInFile& inFile, WavOutFile& outFile)
{
int nSamples;
int nChannels;
int buffSizeSamples;
SAMPLETYPE sampleBuffer[BUFF_SIZE];
int nSamples;
if ((inFile == NULL) || (outFile == NULL)) return; // nothing to do.
nChannels = (int)inFile->getNumChannels();
const int nChannels = (int)inFile.getNumChannels();
assert(nChannels > 0);
buffSizeSamples = BUFF_SIZE / nChannels;
const int buffSizeSamples = BUFF_SIZE / nChannels;
// Process samples read from the input file
while (inFile->eof() == 0)
while (inFile.eof() == 0)
{
int num;
// Read a chunk of samples from the input file
num = inFile->read(sampleBuffer, BUFF_SIZE);
nSamples = num / (int)inFile->getNumChannels();
const int num = inFile.read(sampleBuffer, BUFF_SIZE);
int nSamples = num / (int)inFile.getNumChannels();
// Feed the samples into SoundTouch processor
pSoundTouch->putSamples(sampleBuffer, nSamples);
soundTouch.putSamples(sampleBuffer, nSamples);
// Read ready samples from SoundTouch processor & write them output file.
// NOTES:
@ -200,61 +190,57 @@ static void process(SoundTouch *pSoundTouch, WavInFile *inFile, WavOutFile *outF
// outputs samples.
do
{
nSamples = pSoundTouch->receiveSamples(sampleBuffer, buffSizeSamples);
outFile->write(sampleBuffer, nSamples * nChannels);
nSamples = soundTouch.receiveSamples(sampleBuffer, buffSizeSamples);
outFile.write(sampleBuffer, nSamples * nChannels);
} while (nSamples != 0);
}
// Now the input file is processed, yet 'flush' few last samples that are
// hiding in the SoundTouch's internal processing pipeline.
pSoundTouch->flush();
soundTouch.flush();
do
{
nSamples = pSoundTouch->receiveSamples(sampleBuffer, buffSizeSamples);
outFile->write(sampleBuffer, nSamples * nChannels);
nSamples = soundTouch.receiveSamples(sampleBuffer, buffSizeSamples);
outFile.write(sampleBuffer, nSamples * nChannels);
} while (nSamples != 0);
}
// Detect BPM rate of inFile and adjust tempo setting accordingly if necessary
static void detectBPM(WavInFile *inFile, RunParameters *params)
static void detectBPM(WavInFile& inFile, RunParameters& params)
{
float bpmValue;
int nChannels;
BPMDetect bpm(inFile->getNumChannels(), inFile->getSampleRate());
BPMDetect bpm(inFile.getNumChannels(), inFile.getSampleRate());
SAMPLETYPE sampleBuffer[BUFF_SIZE];
// detect bpm rate
fprintf(stderr, "Detecting BPM rate...");
fflush(stderr);
nChannels = (int)inFile->getNumChannels();
assert(BUFF_SIZE % nChannels == 0);
const int nChannels = (int)inFile.getNumChannels();
int readSize = BUFF_SIZE - BUFF_SIZE % nChannels; // round read size down to multiple of num.channels
// Process the 'inFile' in small blocks, repeat until whole file has
// been processed
while (inFile->eof() == 0)
while (inFile.eof() == 0)
{
int num, samples;
// Read sample data from input file
num = inFile->read(sampleBuffer, BUFF_SIZE);
const int num = inFile.read(sampleBuffer, readSize);
// Enter the new samples to the bpm analyzer class
samples = num / nChannels;
const int samples = num / nChannels;
bpm.inputSamples(sampleBuffer, samples);
}
// Now the whole song data has been analyzed. Read the resulting bpm.
bpmValue = bpm.getBpm();
const float bpmValue = bpm.getBpm();
fprintf(stderr, "Done!\n");
// rewind the file after bpm detection
inFile->rewind();
inFile.rewind();
if (bpmValue > 0)
{
fprintf(stderr, "Detected BPM rate %.1f\n\n", bpmValue);
fprintf(stderr, "Detected BPM rate %.1lf\n\n", bpmValue);
}
else
{
@ -262,61 +248,74 @@ static void detectBPM(WavInFile *inFile, RunParameters *params)
return;
}
if (params->goalBPM > 0)
if (params.goalBPM > 0)
{
// adjust tempo to given bpm
params->tempoDelta = (params->goalBPM / bpmValue - 1.0f) * 100.0f;
fprintf(stderr, "The file will be converted to %.1f BPM\n\n", params->goalBPM);
params.tempoDelta = (params.goalBPM / bpmValue - 1.0f) * 100.0f;
fprintf(stderr, "The file will be converted to %.1lf BPM\n\n", params.goalBPM);
}
}
int main(const int nParams, const char * const paramStr[])
void printHelloText()
{
WavInFile *inFile;
WavOutFile *outFile;
RunParameters *params;
SoundTouch soundTouch;
fprintf(stderr, _helloText, soundTouch.getVersionString());
}
void ss_main(RunParameters& params)
{
unique_ptr<WavInFile> inFile;
unique_ptr<WavOutFile> outFile;
SoundTouch soundTouch;
fprintf(stderr, _helloText, SoundTouch::getVersionString());
try
{
// Parse command line parameters
params = new RunParameters(nParams, paramStr);
// Open input & output files
openFiles(&inFile, &outFile, params);
openFiles(inFile, outFile, params);
if (params->detectBPM == true)
if (params.detectBPM == true)
{
// detect sound BPM (and adjust processing parameters
// accordingly if necessary)
detectBPM(inFile, params);
detectBPM(*inFile, params);
}
// Setup the 'SoundTouch' object for processing the sound
setup(&soundTouch, inFile, params);
setup(soundTouch, *inFile, params);
// clock_t cs = clock(); // for benchmarking processing duration
// Process the sound
process(&soundTouch, inFile, outFile);
if (inFile && outFile)
{
process(soundTouch, *inFile, *outFile);
}
// clock_t ce = clock(); // for benchmarking processing duration
// printf("duration: %lf\n", (double)(ce-cs)/CLOCKS_PER_SEC);
// Close WAV file handles & dispose of the objects
delete inFile;
delete outFile;
delete params;
fprintf(stderr, "Done!\n");
}
}
#if _WIN32
int wmain(int argc, const wchar_t* args[])
#else
int main(int argc, const char* args[])
#endif
{
try
{
soundstretch::printHelloText();
soundstretch::RunParameters params(argc, args);
soundstretch::ss_main(params);
}
catch (const runtime_error& e)
{
// An exception occurred during processing, display an error message
fprintf(stderr, "%s\n", e.what());
return -1;
}
catch (const string& e)
{
fprintf(stderr, "%s\n", e.c_str());
return -1;
}
return 0;
}

View File

@ -21,32 +21,32 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}</ProjectGuid>
<RootNamespace>soundstretch</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -114,9 +114,10 @@
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -133,10 +134,7 @@
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>if not exist ..\..\bin mkdir ..\..\bin
@ -167,6 +165,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<DebugInformationFormat />
<CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -181,9 +180,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
<PostBuildEvent>
<Command>if not exist ..\..\bin mkdir ..\..\bin
@ -215,6 +212,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -231,9 +229,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX64</TargetMachine>
</Link>
<PostBuildEvent>
<Command>if not exist ..\..\bin mkdir ..\..\bin
@ -266,6 +262,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -280,9 +277,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX64</TargetMachine>
</Link>
<PostBuildEvent>
<Command>if not exist ..\..\bin mkdir ..\..\bin
@ -323,6 +318,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
</ItemGroup>
<ItemGroup>
<ClInclude Include="RunParameters.h" />
<ClInclude Include="SS_CharTypes.h" />
<ClInclude Include="WavFile.h" />
</ItemGroup>
<ItemGroup>

View File

@ -54,7 +54,7 @@ using namespace soundtouch;
static void _DEBUG_SAVE_AAFIR_COEFFS(SAMPLETYPE *coeffs, int len)
{
FILE *fptr = fopen("aa_filter_coeffs.txt", "wt");
if (fptr == NULL) return;
if (fptr == nullptr) return;
for (int i = 0; i < len; i ++)
{

View File

@ -186,8 +186,10 @@ BPMDetect::BPMDetect(int numChannels, int aSampleRate) :
// choose decimation factor so that result is approx. 1000 Hz
decimateBy = sampleRate / TARGET_SRATE;
assert(decimateBy > 0);
assert(INPUT_BLOCK_SIZE < decimateBy * DECIMATED_BLOCK_SIZE);
if ((decimateBy <= 0) || (decimateBy * DECIMATED_BLOCK_SIZE < INPUT_BLOCK_SIZE))
{
ST_THROW_RT_ERROR("Too small samplerate");
}
// Calculate window length & starting item according to desired min & max bpms
windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM);
@ -299,7 +301,7 @@ void BPMDetect::updateXCorr(int process_samples)
pBuffer = buffer->ptrBegin();
// calculate decay factor for xcorr filtering
float xcorr_decay = (float)pow(0.5, 1.0 / (XCORR_DECAY_TIME_CONSTANT * TARGET_SRATE / process_samples));
float xcorr_decay = (float)pow(0.5, process_samples / (XCORR_DECAY_TIME_CONSTANT * TARGET_SRATE));
// prescale pbuffer
float tmp[XCORR_UPDATE_SEQUENCE];
@ -311,7 +313,7 @@ void BPMDetect::updateXCorr(int process_samples)
#pragma omp parallel for
for (offs = windowStart; offs < windowLen; offs ++)
{
double sum;
float sum;
int i;
sum = 0;
@ -339,7 +341,6 @@ void BPMDetect::updateBeatPos(int process_samples)
// static double thr = 0.0003;
double posScale = (double)this->decimateBy / (double)this->sampleRate;
int resetDur = (int)(0.12 / posScale + 0.5);
double corrScale = 1.0 / (double)(windowLen - windowStart);
// prescale pbuffer
float tmp[XCORR_UPDATE_SEQUENCE / 2];
@ -351,7 +352,7 @@ void BPMDetect::updateBeatPos(int process_samples)
#pragma omp parallel for
for (int offs = windowStart; offs < windowLen; offs++)
{
double sum = 0;
float sum = 0;
for (int i = 0; i < process_samples; i++)
{
sum += tmp[i] * pBuffer[offs + i];
@ -375,8 +376,6 @@ void BPMDetect::updateBeatPos(int process_samples)
// detect beats
for (int i = 0; i < skipstep; i++)
{
LONG_SAMPLETYPE max = 0;
float sum = beatcorr_ringbuff[beatcorr_ringbuffpos];
sum -= beat_lpf.update(sum);
@ -555,13 +554,13 @@ float BPMDetect::getBpm()
/// - "values" receive array of beat detection strengths
/// - max_num indicates max.size of "pos" and "values" array.
///
/// You can query a suitable array sized by calling this with NULL in "pos" & "values".
/// You can query a suitable array sized by calling this with nullptr in "pos" & "values".
///
/// \return number of beats in the arrays.
int BPMDetect::getBeats(float *pos, float *values, int max_num)
{
int num = beats.size();
if ((!pos) || (!values)) return num; // pos or values NULL, return just size
int num = (int)beats.size();
if ((!pos) || (!values)) return num; // pos or values nullptr, return just size
for (int i = 0; (i < num) && (i < max_num); i++)
{

View File

@ -50,8 +50,8 @@ FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
{
assert(numChannels > 0);
sizeInBytes = 0; // reasonable initial value
buffer = NULL;
bufferUnaligned = NULL;
buffer = nullptr;
bufferUnaligned = nullptr;
samplesInBuffer = 0;
bufferPos = 0;
channels = (uint)numChannels;
@ -63,8 +63,8 @@ FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
FIFOSampleBuffer::~FIFOSampleBuffer()
{
delete[] bufferUnaligned;
bufferUnaligned = NULL;
buffer = NULL;
bufferUnaligned = nullptr;
buffer = nullptr;
}
@ -166,7 +166,7 @@ void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
assert(sizeInBytes % 2 == 0);
tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
if (tempUnaligned == NULL)
if (tempUnaligned == nullptr)
{
ST_THROW_RT_ERROR("Couldn't allocate memory!\n");
}
@ -265,3 +265,11 @@ uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples)
}
return samplesInBuffer;
}
/// Add silence to end of buffer
void FIFOSampleBuffer::addSilent(uint nSamples)
{
memset(ptrEnd(nSamples), 0, sizeof(SAMPLETYPE) * nSamples * channels);
samplesInBuffer += nSamples;
}

View File

@ -56,16 +56,17 @@ using namespace soundtouch;
FIRFilter::FIRFilter()
{
resultDivFactor = 0;
resultDivider = 0;
length = 0;
lengthDiv8 = 0;
filterCoeffs = NULL;
filterCoeffs = nullptr;
filterCoeffsStereo = nullptr;
}
FIRFilter::~FIRFilter()
{
delete[] filterCoeffs;
delete[] filterCoeffsStereo;
}
@ -73,40 +74,27 @@ FIRFilter::~FIRFilter()
uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
{
int j, end;
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
// when using floating point samples, use a scaler instead of a divider
// because division is much slower operation than multiplying.
double dScaler = 1.0 / (double)resultDivider;
#endif
// hint compiler autovectorization that loop length is divisible by 8
uint ilength = length & -8;
assert(length != 0);
assert(src != NULL);
assert(dest != NULL);
assert(filterCoeffs != NULL);
assert((length != 0) && (length == ilength) && (src != nullptr) && (dest != nullptr) && (filterCoeffs != nullptr));
assert(numSamples > ilength);
end = 2 * (numSamples - length);
end = 2 * (numSamples - ilength);
#pragma omp parallel for
for (j = 0; j < end; j += 2)
{
const SAMPLETYPE *ptr;
LONG_SAMPLETYPE suml, sumr;
uint i;
suml = sumr = 0;
ptr = src + j;
for (i = 0; i < length; i += 4)
for (uint i = 0; i < ilength; i ++)
{
// loop is unrolled by factor of 4 here for efficiency
suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
ptr[2 * i + 2] * filterCoeffs[i + 1] +
ptr[2 * i + 4] * filterCoeffs[i + 2] +
ptr[2 * i + 6] * filterCoeffs[i + 3];
sumr += ptr[2 * i + 1] * filterCoeffs[i + 0] +
ptr[2 * i + 3] * filterCoeffs[i + 1] +
ptr[2 * i + 5] * filterCoeffs[i + 2] +
ptr[2 * i + 7] * filterCoeffs[i + 3];
suml += ptr[2 * i] * filterCoeffsStereo[2 * i];
sumr += ptr[2 * i + 1] * filterCoeffsStereo[2 * i + 1];
}
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
@ -116,14 +104,11 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
// saturate to 16 bit integer limits
sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
#else
suml *= dScaler;
sumr *= dScaler;
#endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j] = (SAMPLETYPE)suml;
dest[j + 1] = (SAMPLETYPE)sumr;
}
return numSamples - length;
return numSamples - ilength;
}
@ -131,37 +116,29 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
{
int j, end;
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
// when using floating point samples, use a scaler instead of a divider
// because division is much slower operation than multiplying.
double dScaler = 1.0 / (double)resultDivider;
#endif
assert(length != 0);
// hint compiler autovectorization that loop length is divisible by 8
int ilength = length & -8;
end = numSamples - length;
assert(ilength != 0);
end = numSamples - ilength;
#pragma omp parallel for
for (j = 0; j < end; j ++)
{
const SAMPLETYPE *pSrc = src + j;
LONG_SAMPLETYPE sum;
uint i;
int i;
sum = 0;
for (i = 0; i < length; i += 4)
for (i = 0; i < ilength; i ++)
{
// loop is unrolled by factor of 4 here for efficiency
sum += pSrc[i + 0] * filterCoeffs[i + 0] +
pSrc[i + 1] * filterCoeffs[i + 1] +
pSrc[i + 2] * filterCoeffs[i + 2] +
pSrc[i + 3] * filterCoeffs[i + 3];
sum += pSrc[i] * filterCoeffs[i];
}
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
sum >>= resultDivFactor;
// saturate to 16 bit integer limits
sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
#else
sum *= dScaler;
#endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j] = (SAMPLETYPE)sum;
}
@ -173,26 +150,24 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
{
int j, end;
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
// when using floating point samples, use a scaler instead of a divider
// because division is much slower operation than multiplying.
double dScaler = 1.0 / (double)resultDivider;
#endif
assert(length != 0);
assert(src != NULL);
assert(dest != NULL);
assert(filterCoeffs != NULL);
assert(numChannels < 16);
assert(src != nullptr);
assert(dest != nullptr);
assert(filterCoeffs != nullptr);
assert(numChannels <= SOUNDTOUCH_MAX_CHANNELS);
end = numChannels * (numSamples - length);
// hint compiler autovectorization that loop length is divisible by 8
int ilength = length & -8;
end = numChannels * (numSamples - ilength);
#pragma omp parallel for
for (j = 0; j < end; j += numChannels)
{
const SAMPLETYPE *ptr;
LONG_SAMPLETYPE sums[16];
uint c, i;
uint c;
int i;
for (c = 0; c < numChannels; c ++)
{
@ -201,7 +176,7 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
ptr = src + j;
for (i = 0; i < length; i ++)
for (i = 0; i < ilength; i ++)
{
SAMPLETYPE coef=filterCoeffs[i];
for (c = 0; c < numChannels; c ++)
@ -215,13 +190,11 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
{
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
sums[c] >>= resultDivFactor;
#else
sums[c] *= dScaler;
#endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j+c] = (SAMPLETYPE)sums[c];
}
}
return numSamples - length;
return numSamples - ilength;
}
@ -238,11 +211,27 @@ void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint u
assert(length == newLength);
resultDivFactor = uResultDivFactor;
resultDivider = (SAMPLETYPE)::pow(2.0, (int)resultDivFactor);
delete[] filterCoeffs;
filterCoeffs = new SAMPLETYPE[length];
memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE));
delete[] filterCoeffsStereo;
filterCoeffsStereo = new SAMPLETYPE[length*2];
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
// scale coefficients already here if using floating samples
const double scale = ::pow(0.5, (int)resultDivFactor);;
#else
const short scale = 1;
#endif
for (uint i = 0; i < length; i ++)
{
filterCoeffs[i] = (SAMPLETYPE)(coeffs[i] * scale);
// create also stereo set of filter coefficients: this allows compiler
// to autovectorize filter evaluation much more efficiently
filterCoeffsStereo[2 * i] = (SAMPLETYPE)(coeffs[i] * scale);
filterCoeffsStereo[2 * i + 1] = (SAMPLETYPE)(coeffs[i] * scale);
}
}
@ -283,7 +272,7 @@ uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSample
// Operator 'new' is overloaded so that it automatically creates a suitable instance
// depending on if we've a MMX-capable CPU available or not.
void * FIRFilter::operator new(size_t s)
void * FIRFilter::operator new(size_t)
{
// Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
ST_THROW_RT_ERROR("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!");
@ -296,6 +285,7 @@ FIRFilter * FIRFilter::newInstance()
uint uExtensions;
uExtensions = detectCPUextensions();
(void)uExtensions;
// Check if MMX/SSE instruction set extensions supported by CPU

View File

@ -52,11 +52,9 @@ protected:
// Result divider factor in 2^k format
uint resultDivFactor;
// Result divider value.
SAMPLETYPE resultDivider;
// Memory for filter coefficients
SAMPLETYPE *filterCoeffs;
SAMPLETYPE *filterCoeffsStereo;
virtual uint evaluateFilterStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
@ -105,12 +103,12 @@ public:
short *filterCoeffsUnalign;
short *filterCoeffsAlign;
virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const;
virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const override;
public:
FIRFilterMMX();
~FIRFilterMMX();
virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor);
virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor) override;
};
#endif // SOUNDTOUCH_ALLOW_MMX
@ -124,12 +122,12 @@ public:
float *filterCoeffsUnalign;
float *filterCoeffsAlign;
virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const;
virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const override;
public:
FIRFilterSSE();
~FIRFilterSSE();
virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor);
virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor) override;
};
#endif // SOUNDTOUCH_ALLOW_SSE

View File

@ -41,21 +41,27 @@ namespace soundtouch
class InterpolateCubic : public TransposerBase
{
protected:
virtual void resetRegisters();
virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
int &srcSamples) override;
virtual int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
int &srcSamples) override;
virtual int transposeMulti(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
int &srcSamples) override;
double fract;
public:
InterpolateCubic();
virtual void resetRegisters() override;
virtual int getLatency() const override
{
return 1;
}
};
}

View File

@ -142,7 +142,7 @@ int InterpolateLinearInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE
LONG_SAMPLETYPE temp, vol1;
assert(iFract < SCALE);
vol1 = (SCALE - iFract);
vol1 = (LONG_SAMPLETYPE)(SCALE - iFract);
for (int c = 0; c < numChannels; c ++)
{
temp = vol1 * src[c] + iFract * src[c + numChannels];

View File

@ -45,21 +45,26 @@ protected:
int iFract;
int iRate;
virtual void resetRegisters();
virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
int &srcSamples) override;
virtual int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
int &srcSamples) override;
virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples) override;
public:
InterpolateLinearInteger();
/// Sets new target rate. Normal rate = 1.0, smaller values represent slower
/// rate, larger faster rates.
virtual void setRate(double newRate);
virtual void setRate(double newRate) override;
virtual void resetRegisters() override;
virtual int getLatency() const override
{
return 0;
}
};
@ -69,8 +74,6 @@ class InterpolateLinearFloat : public TransposerBase
protected:
double fract;
virtual void resetRegisters();
virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
@ -81,6 +84,13 @@ protected:
public:
InterpolateLinearFloat();
virtual void resetRegisters();
int getLatency() const
{
return 0;
}
};
}

View File

@ -171,9 +171,9 @@ int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest,
/// Transpose stereo audio. Returns number of produced output samples, and
/// updates "srcSamples" to amount of consumed source samples
int InterpolateShannon::transposeMulti(SAMPLETYPE *pdest,
const SAMPLETYPE *psrc,
int &srcSamples)
int InterpolateShannon::transposeMulti(SAMPLETYPE *,
const SAMPLETYPE *,
int &)
{
// not implemented
assert(false);

View File

@ -46,21 +46,27 @@ namespace soundtouch
class InterpolateShannon : public TransposerBase
{
protected:
void resetRegisters();
int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
int &srcSamples) override;
int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
int &srcSamples) override;
int transposeMulti(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
int &srcSamples) override;
double fract;
public:
InterpolateShannon();
void resetRegisters() override;
virtual int getLatency() const override
{
return 3;
}
};
}

View File

@ -33,7 +33,7 @@ libSoundTouch_la_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp \
InterpolateShannon.cpp
# Compiler flags
AM_CXXFLAGS+=-O3
#AM_CXXFLAGS+=
# Compile the files that need MMX and SSE individually.
libSoundTouch_la_LIBADD=libSoundTouchMMX.la libSoundTouchSSE.la

View File

@ -57,7 +57,7 @@ int PeakFinder::findTop(const float *data, int peakpos) const
refvalue = data[peakpos];
// seek within <EFBFBD>10 points
// seek within ±10 points
start = peakpos - 10;
if (start < minPos) start = minPos;
end = peakpos + 10;
@ -142,7 +142,7 @@ int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, i
peaklevel = data[peakpos];
assert(peaklevel >= level);
pos = peakpos;
while ((pos >= minPos) && (pos < maxPos))
while ((pos >= minPos) && (pos + direction < maxPos))
{
if (data[pos + direction] < level) return pos; // crossing found
pos += direction;
@ -256,7 +256,7 @@ double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
// accept harmonic peak if
// (a) it is found
// (b) is within <EFBFBD>4% of the expected harmonic interval
// (b) is within ±4% of the expected harmonic interval
// (c) has at least half x-corr value of the max. peak
double diff = harmonic * peaktmp / highPeak;

View File

@ -61,6 +61,7 @@ RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
// Instantiates the anti-alias filter
pAAFilter = new AAFilter(64);
pTransposer = TransposerBase::newInstance();
clear();
}
@ -77,6 +78,7 @@ void RateTransposer::enableAAFilter(bool newMode)
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
// Disable Anti-alias filter if desirable to avoid click at rate change zero value crossover
bUseAAFilter = newMode;
clear();
#endif
}
@ -129,8 +131,6 @@ void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
// the 'set_returnBuffer_size' function.
void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
{
uint count;
if (nSamples == 0) return;
// Store samples to input buffer
@ -140,7 +140,7 @@ void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
// the filter
if (bUseAAFilter == false)
{
count = pTransposer->transpose(outputBuffer, inputBuffer);
(void)pTransposer->transpose(outputBuffer, inputBuffer);
return;
}
@ -192,6 +192,11 @@ void RateTransposer::clear()
outputBuffer.clear();
midBuffer.clear();
inputBuffer.clear();
pTransposer->resetRegisters();
// prefill buffer to avoid losing first samples at beginning of stream
int prefill = getLatency();
inputBuffer.addSilent(prefill);
}
@ -209,7 +214,8 @@ int RateTransposer::isEmpty() const
/// Return approximate initial input-output latency
int RateTransposer::getLatency() const
{
return (bUseAAFilter) ? pAAFilter->getLength() : 0;
return pTransposer->getLatency() +
((bUseAAFilter) ? (pAAFilter->getLength() / 2) : 0);
}
@ -301,7 +307,7 @@ TransposerBase *TransposerBase::newInstance()
default:
assert(false);
return NULL;
return nullptr;
}
#endif
}

View File

@ -59,8 +59,6 @@ public:
};
protected:
virtual void resetRegisters() = 0;
virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples) = 0;
@ -83,6 +81,9 @@ public:
virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src);
virtual void setRate(double newRate);
virtual void setChannels(int channels);
virtual int getLatency() const = 0;
virtual void resetRegisters() = 0;
// static factory function
static TransposerBase *newInstance();
@ -123,7 +124,7 @@ protected:
public:
RateTransposer();
virtual ~RateTransposer();
virtual ~RateTransposer() override;
/// Returns the output buffer object
FIFOSamplePipe *getOutput() { return &outputBuffer; };
@ -146,13 +147,13 @@ public:
/// Adds 'numSamples' pcs of samples from the 'samples' memory position into
/// the input of the object.
void putSamples(const SAMPLETYPE *samples, uint numSamples);
void putSamples(const SAMPLETYPE *samples, uint numSamples) override;
/// Clears all the samples in the object
void clear();
void clear() override;
/// Returns nonzero if there aren't any samples available for outputting.
int isEmpty() const;
int isEmpty() const override;
/// Return approximate initial input-output latency
int getLatency() const;

View File

@ -413,15 +413,15 @@ int SoundTouch::getSetting(int settingId) const
return (uint)pTDStretch->isQuickSeekEnabled();
case SETTING_SEQUENCE_MS:
pTDStretch->getParameters(NULL, &temp, NULL, NULL);
pTDStretch->getParameters(nullptr, &temp, nullptr, nullptr);
return temp;
case SETTING_SEEKWINDOW_MS:
pTDStretch->getParameters(NULL, NULL, &temp, NULL);
pTDStretch->getParameters(nullptr, nullptr, &temp, nullptr);
return temp;
case SETTING_OVERLAP_MS:
pTDStretch->getParameters(NULL, NULL, NULL, &temp);
pTDStretch->getParameters(nullptr, nullptr, nullptr, &temp);
return temp;
case SETTING_NOMINAL_INPUT_SEQUENCE :

View File

@ -20,32 +20,32 @@
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{68A5DD20-7057-448B-8FE0-B6AC8D205509}</ProjectGuid>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -112,6 +112,7 @@
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName>
<BrowseInformationFile>$(IntDir)</BrowseInformationFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -153,6 +154,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\lib</Command>
</EnableEnhancedInstructionSet>
<XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName>
<BrowseInformationFile>$(IntDir)</BrowseInformationFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -183,11 +185,12 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\lib</Command>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName>
<BrowseInformationFile>$(IntDir)</BrowseInformationFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -227,6 +230,7 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\lib</Command>
</EnableEnhancedInstructionSet>
<XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName>
<BrowseInformationFile>$(IntDir)</BrowseInformationFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

View File

@ -1,4 +1,4 @@
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///
/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
/// while maintaining the original pitch by using a time domain WSOLA-like
@ -54,26 +54,6 @@ using namespace soundtouch;
#define max(x, y) (((x) > (y)) ? (x) : (y))
/*****************************************************************************
*
* Constant definitions
*
*****************************************************************************/
// Table for the hierarchical mixing position seeking algorithm
const short _scanOffsets[5][24]={
{ 124, 186, 248, 310, 372, 434, 496, 558, 620, 682, 744, 806,
868, 930, 992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488, 0},
{-100, -75, -50, -25, 25, 50, 75, 100, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ -20, -15, -10, -5, 5, 10, 15, 20, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ -4, -3, -2, -1, 1, 2, 3, 4, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 121, 114, 97, 114, 98, 105, 108, 32, 104, 99, 117, 111,
116, 100, 110, 117, 111, 115, 0, 0, 0, 0, 0, 0}};
/*****************************************************************************
*
* Implementation of the class 'TDStretch'
@ -86,18 +66,13 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
bQuickSeek = false;
channels = 2;
pMidBuffer = NULL;
pMidBufferUnaligned = NULL;
pMidBuffer = nullptr;
pMidBufferUnaligned = nullptr;
overlapLength = 0;
bAutoSeqSetting = true;
bAutoSeekSetting = true;
maxnorm = 0;
maxnormf = 1e8;
skipFract = 0;
tempo = 1.0f;
setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
setTempo(1.0f);
@ -168,7 +143,7 @@ void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
/// Get routine control parameters, see setParameters() function.
/// Any of the parameters to this function can be NULL, in such case corresponding parameter
/// Any of the parameters to this function can be nullptr, in such case corresponding parameter
/// value isn't returned.
void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const
{
@ -224,6 +199,9 @@ void TDStretch::clearInput()
inputBuffer.clear();
clearMidBuffer();
isBeginning = true;
maxnorm = 0;
maxnormf = 1e8;
skipFract = 0;
}
@ -315,9 +293,10 @@ int TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
{
double corr;
// Calculates correlation value for the mixing position corresponding to 'i'
#ifdef _OPENMP
#if defined(_OPENMP) || defined(ST_SIMD_AVOID_UNALIGNED)
// in parallel OpenMP mode, can't use norm accumulator version as parallel executor won't
// iterate the loop in sequential order
// in SIMD mode, avoid accumulator version to allow avoiding unaligned positions
corr = calcCrossCorr(refPos + channels * i, pMidBuffer, norm);
#else
// In non-parallel version call "calcCrossCorrAccumulate" that is otherwise same
@ -675,11 +654,10 @@ void TDStretch::processSamples()
// Adjust processing offset at beginning of track by not perform initial overlapping
// and compensating that in the 'input buffer skip' calculation
isBeginning = false;
int skip = (int)(tempo * overlapLength + 0.5);
int skip = (int)(tempo * overlapLength + 0.5 * seekLength + 0.5);
#ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
#ifdef SOUNDTOUCH_ALLOW_SSE
// if SSE mode, round the skip amount to value corresponding to aligned memory address
#ifdef ST_SIMD_AVOID_UNALIGNED
// in SIMD mode, round the skip amount to value corresponding to aligned memory address
if (channels == 1)
{
skip &= -4;
@ -689,9 +667,11 @@ void TDStretch::processSamples()
skip &= -2;
}
#endif
#endif
skipFract -= skip;
assert(nominalSkip >= -skipFract);
if (skipFract <= -nominalSkip)
{
skipFract = -nominalSkip;
}
}
// ... then copy sequence samples from 'inputBuffer' to output:
@ -760,7 +740,7 @@ void TDStretch::acceptNewOverlapLength(int newOverlapLength)
// Operator 'new' is overloaded so that it automatically creates a suitable instance
// depending on if we've a MMX/SSE/etc-capable CPU available or not.
void * TDStretch::operator new(size_t s)
void * TDStretch::operator new(size_t)
{
// Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
ST_THROW_RT_ERROR("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!");
@ -773,6 +753,7 @@ TDStretch * TDStretch::newInstance()
uint uExtensions;
uExtensions = detectCPUextensions();
(void)uExtensions;
// Check if MMX/SSE instruction set extensions supported by CPU
@ -830,21 +811,19 @@ void TDStretch::overlapStereo(short *poutput, const short *input) const
// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Multi'
// version of the routine.
void TDStretch::overlapMulti(SAMPLETYPE *poutput, const SAMPLETYPE *input) const
void TDStretch::overlapMulti(short *poutput, const short *input) const
{
SAMPLETYPE m1=(SAMPLETYPE)0;
SAMPLETYPE m2;
short m1;
int i = 0;
for (m2 = (SAMPLETYPE)overlapLength; m2; m2 --)
for (m1 = 0; m1 < overlapLength; m1 ++)
{
short m2 = (short)(overlapLength - m1);
for (int c = 0; c < channels; c ++)
{
poutput[i] = (input[i] * m1 + pMidBuffer[i] * m2) / overlapLength;
i++;
}
m1++;
}
}
@ -889,20 +868,23 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare, do
unsigned long lnorm;
int i;
#ifdef ST_SIMD_AVOID_UNALIGNED
// in SIMD mode skip 'mixingPos' positions that aren't aligned to 16-byte boundary
if (((ulongptr)mixingPos) & 15) return -1e50;
#endif
// hint compiler autovectorization that loop length is divisible by 8
int ilength = (channels * overlapLength) & -8;
corr = lnorm = 0;
// Same routine for stereo and mono. For stereo, unroll loop for better
// efficiency and gives slightly better resolution against rounding.
// For mono it same routine, just unrolls loop by factor of 4
for (i = 0; i < channels * overlapLength; i += 4)
// Same routine for stereo and mono
for (i = 0; i < ilength; i += 2)
{
corr += (mixingPos[i] * compare[i] +
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm; // notice: do intermediate division here to avoid integer overflow
corr += (mixingPos[i + 2] * compare[i + 2] +
mixingPos[i + 3] * compare[i + 3]) >> overlapDividerBitsNorm;
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm;
lnorm += (mixingPos[i] * mixingPos[i] +
mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBitsNorm; // notice: do intermediate division here to avoid integer overflow
lnorm += (mixingPos[i + 2] * mixingPos[i + 2] +
mixingPos[i + 3] * mixingPos[i + 3]) >> overlapDividerBitsNorm;
mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBitsNorm;
// do intermediate scalings to avoid integer overflow
}
if (lnorm > maxnorm)
@ -925,9 +907,12 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare, do
double TDStretch::calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm)
{
long corr;
unsigned long lnorm;
long lnorm;
int i;
// hint compiler autovectorization that loop length is divisible by 8
int ilength = (channels * overlapLength) & -8;
// cancel first normalizer tap from previous round
lnorm = 0;
for (i = 1; i <= channels; i ++)
@ -936,15 +921,11 @@ double TDStretch::calcCrossCorrAccumulate(const short *mixingPos, const short *c
}
corr = 0;
// Same routine for stereo and mono. For stereo, unroll loop for better
// efficiency and gives slightly better resolution against rounding.
// For mono it same routine, just unrolls loop by factor of 4
for (i = 0; i < channels * overlapLength; i += 4)
// Same routine for stereo and mono.
for (i = 0; i < ilength; i += 2)
{
corr += (mixingPos[i] * compare[i] +
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm; // notice: do intermediate division here to avoid integer overflow
corr += (mixingPos[i + 2] * compare[i + 2] +
mixingPos[i + 3] * compare[i + 3]) >> overlapDividerBitsNorm;
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm;
}
// update normalizer with last samples of this round
@ -1045,27 +1026,24 @@ void TDStretch::calculateOverlapLength(int overlapInMsec)
/// Calculate cross-correlation
double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare, double &anorm)
{
double corr;
double norm;
float corr;
float norm;
int i;
#ifdef ST_SIMD_AVOID_UNALIGNED
// in SIMD mode skip 'mixingPos' positions that aren't aligned to 16-byte boundary
if (((ulongptr)mixingPos) & 15) return -1e50;
#endif
// hint compiler autovectorization that loop length is divisible by 8
int ilength = (channels * overlapLength) & -8;
corr = norm = 0;
// Same routine for stereo and mono. For Stereo, unroll by factor of 2.
// For mono it's same routine yet unrollsd by factor of 4.
for (i = 0; i < channels * overlapLength; i += 4)
// Same routine for stereo and mono
for (i = 0; i < ilength; i ++)
{
corr += mixingPos[i] * compare[i] +
mixingPos[i + 1] * compare[i + 1];
norm += mixingPos[i] * mixingPos[i] +
mixingPos[i + 1] * mixingPos[i + 1];
// unroll the loop for better CPU efficiency:
corr += mixingPos[i + 2] * compare[i + 2] +
mixingPos[i + 3] * compare[i + 3];
norm += mixingPos[i + 2] * mixingPos[i + 2] +
mixingPos[i + 3] * mixingPos[i + 3];
corr += mixingPos[i] * compare[i];
norm += mixingPos[i] * mixingPos[i];
}
anorm = norm;
@ -1076,7 +1054,7 @@ double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare, do
/// Update cross-correlation by accumulating "norm" coefficient by previously calculated value
double TDStretch::calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm)
{
double corr;
float corr;
int i;
corr = 0;
@ -1087,14 +1065,13 @@ double TDStretch::calcCrossCorrAccumulate(const float *mixingPos, const float *c
norm -= mixingPos[-i] * mixingPos[-i];
}
// Same routine for stereo and mono. For Stereo, unroll by factor of 2.
// For mono it's same routine yet unrollsd by factor of 4.
for (i = 0; i < channels * overlapLength; i += 4)
// hint compiler autovectorization that loop length is divisible by 8
int ilength = (channels * overlapLength) & -8;
// Same routine for stereo and mono
for (i = 0; i < ilength; i ++)
{
corr += mixingPos[i] * compare[i] +
mixingPos[i + 1] * compare[i + 1] +
mixingPos[i + 2] * compare[i + 2] +
mixingPos[i + 3] * compare[i + 3];
corr += mixingPos[i] * compare[i];
}
// update normalizer with last samples of this round

View File

@ -165,7 +165,7 @@ protected:
public:
TDStretch();
virtual ~TDStretch();
virtual ~TDStretch() override;
/// Operator 'new' is overloaded so that it automatically creates a suitable instance
/// depending on if we've a MMX/SSE/etc-capable CPU available or not.
@ -187,7 +187,7 @@ public:
void setTempo(double newTempo);
/// Returns nonzero if there aren't any samples available for outputting.
virtual void clear();
virtual void clear() override;
/// Clears the input buffer
void clearInput();
@ -217,7 +217,7 @@ public:
);
/// Get routine control parameters, see setParameters() function.
/// Any of the parameters to this function can be NULL, in such case corresponding parameter
/// Any of the parameters to this function can be nullptr, in such case corresponding parameter
/// value isn't returned.
void getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const;
@ -227,7 +227,7 @@ public:
const SAMPLETYPE *samples, ///< Input sample data
uint numSamples ///< Number of samples in 'samples' so that one sample
///< contains both channels if stereo
);
) override;
/// return nominal input sample requirement for triggering a processing batch
int getInputSampleReq() const
@ -256,10 +256,10 @@ public:
class TDStretchMMX : public TDStretch
{
protected:
double calcCrossCorr(const short *mixingPos, const short *compare, double &norm);
double calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm);
virtual void overlapStereo(short *output, const short *input) const;
virtual void clearCrossCorrState();
double calcCrossCorr(const short *mixingPos, const short *compare, double &norm) override;
double calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm) override;
virtual void overlapStereo(short *output, const short *input) const override;
virtual void clearCrossCorrState() override;
};
#endif /// SOUNDTOUCH_ALLOW_MMX
@ -269,8 +269,8 @@ public:
class TDStretchSSE : public TDStretch
{
protected:
double calcCrossCorr(const float *mixingPos, const float *compare, double &norm);
double calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm);
double calcCrossCorr(const float *mixingPos, const float *compare, double &norm) override;
double calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm) override;
};
#endif /// SOUNDTOUCH_ALLOW_SSE

View File

@ -294,8 +294,8 @@ void TDStretchMMX::overlapStereo(short *output, const short *input) const
FIRFilterMMX::FIRFilterMMX() : FIRFilter()
{
filterCoeffsAlign = NULL;
filterCoeffsUnalign = NULL;
filterCoeffsAlign = nullptr;
filterCoeffsUnalign = nullptr;
}

View File

@ -80,7 +80,7 @@ double TDStretchSSE::calcCrossCorr(const float *pV1, const float *pV2, double &a
// Compile-time define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided
// for choosing if this little cheating is allowed.
#ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
#ifdef ST_SIMD_AVOID_UNALIGNED
// Little cheating allowed, return valid correlation only for
// aligned locations, meaning every second round for stereo sound.
@ -195,25 +195,22 @@ double TDStretchSSE::calcCrossCorrAccumulate(const float *pV1, const float *pV2,
FIRFilterSSE::FIRFilterSSE() : FIRFilter()
{
filterCoeffsAlign = NULL;
filterCoeffsUnalign = NULL;
filterCoeffsAlign = nullptr;
filterCoeffsUnalign = nullptr;
}
FIRFilterSSE::~FIRFilterSSE()
{
delete[] filterCoeffsUnalign;
filterCoeffsAlign = NULL;
filterCoeffsUnalign = NULL;
filterCoeffsAlign = nullptr;
filterCoeffsUnalign = nullptr;
}
// (overloaded) Calculates filter coefficients for SSE routine
void FIRFilterSSE::setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor)
{
uint i;
float fDivider;
FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor);
// Scale the filter coefficients so that it won't be necessary to scale the filtering result
@ -223,13 +220,13 @@ void FIRFilterSSE::setCoefficients(const float *coeffs, uint newLength, uint uRe
filterCoeffsUnalign = new float[2 * newLength + 4];
filterCoeffsAlign = (float *)SOUNDTOUCH_ALIGN_POINTER_16(filterCoeffsUnalign);
fDivider = (float)resultDivider;
const float scale = ::pow(0.5, (int)resultDivFactor);
// rearrange the filter coefficients for mmx routines
for (i = 0; i < newLength; i ++)
// rearrange the filter coefficients for sse routines
for (auto i = 0U; i < newLength; i ++)
{
filterCoeffsAlign[2 * i + 0] =
filterCoeffsAlign[2 * i + 1] = coeffs[i + 0] / fDivider;
filterCoeffsAlign[2 * i + 1] = coeffs[i] * scale;
}
}
@ -245,10 +242,10 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n
if (count < 2) return 0;
assert(source != NULL);
assert(dest != NULL);
assert(source != nullptr);
assert(dest != nullptr);
assert((length % 8) == 0);
assert(filterCoeffsAlign != NULL);
assert(filterCoeffsAlign != nullptr);
assert(((ulongptr)filterCoeffsAlign) % 16 == 0);
// filter is evaluated for two stereo samples with each iteration, thus use of 'j += 2'

View File

@ -16,9 +16,10 @@
#include "../../SoundStretch/WavFile.h"
using namespace std;
using namespace soundstretch;
// DllTest main
int main(int argc, char *argv[])
int wmain(int argc, const wchar_t *argv[])
{
// Check program arguments
if (argc < 4)
@ -27,22 +28,22 @@ int main(int argc, char *argv[])
return -1;
}
const char *inFileName = argv[1];
const char *outFileName = argv[2];
string str_sampleType = argv[3];
wstring inFileName = argv[1];
wstring outFileName = argv[2];
wstring str_sampleType = argv[3];
bool floatSample;
if (str_sampleType.compare("float") == 0)
if (str_sampleType == L"float")
{
floatSample = true;
}
else if (str_sampleType.compare("short") == 0)
else if (str_sampleType == L"short")
{
floatSample = false;
}
else
{
cerr << "Missing or invalid sampletype '" << str_sampleType << "'. Expected either short or float" << endl;
cerr << "Missing or invalid sampletype. Expected either short or float" << endl;
return -1;
}

View File

@ -22,32 +22,32 @@
<ProjectGuid>{E3C0726F-28F4-4F0B-8183-B87CA60C063C}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>DllTest</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>

View File

@ -0,0 +1,10 @@
This is Lazarus Pascal example that loads the SoundTouch dynamic-load library
and queries the library version as a simple example how to load SoundTouch from
Pascal / Lazarus.
Set the SoundTouch dynamic library file name in the 'InitDLL' procedure of
file 'SoundTouchDLL.pas' depending on if you're building for Windows or Linux.
The example expects the the 'libSoundTouchDll.so' (linux) or 'SoundTouch.dll' (Windows)
library binary files is found within this project directory, either via soft-link
(in Linux) or as a copied file.

View File

@ -2,11 +2,8 @@ unit SoundTouchDLL;
//////////////////////////////////////////////////////////////////////////////
//
// SoundTouch.dll wrapper for accessing SoundTouch routines from Delphi/Pascal
//
// Module Author : Christian Budde
//
// 2014-01-12 fixes by Sandro Cumerlato <sandro.cumerlato 'at' gmail.com>
// SoundTouch.dll / libSoundTouchDll.so wrapper for accessing SoundTouch
// routines from Delphi/Pascal/Lazarus
//
////////////////////////////////////////////////////////////////////////////////
//
@ -33,8 +30,8 @@ unit SoundTouchDLL;
interface
uses
Windows;
//uses
//Windows;
type
TSoundTouchHandle = THandle;
@ -107,6 +104,13 @@ type
//< contains data for both channels.
); cdecl;
TSoundTouchPutSamplesI16 = procedure (Handle: TSoundTouchHandle;
const Samples: Pint16; //< Pointer to sample buffer.
NumSamples: Cardinal //< Number of samples in buffer. Notice
//< that in case of stereo-sound a single sample
//< contains data for both channels.
); cdecl;
// Clears all the samples in the object's output and internal processing
// buffers.
TSoundTouchClear = procedure (Handle: TSoundTouchHandle); cdecl;
@ -131,16 +135,20 @@ type
// Returns number of samples currently unprocessed.
TSoundTouchNumUnprocessedSamples = function (Handle: TSoundTouchHandle): Cardinal; cdecl;
// Adjusts book-keeping so that given number of samples are removed from beginning of the
// sample buffer without copying them anywhere.
//
// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
// with 'ptrBegin' function.
/// Receive ready samples from the processing pipeline.
///
/// if called with outBuffer=nullptr, just reduces amount of ready samples within the pipeline.
TSoundTouchReceiveSamples = function (Handle: TSoundTouchHandle;
OutBuffer: PSingle; //< Buffer where to copy output samples.
MaxSamples: Integer //< How many samples to receive at max.
): Cardinal; cdecl;
/// int16 version of soundtouch_receiveSamples(): This converts internal float samples
/// into int16 (short) return data type
TSoundTouchReceiveSamplesI16 = function (Handle: TSoundTouchHandle;
OutBuffer: int16; //< Buffer where to copy output samples.
MaxSamples: Integer //< How many samples to receive at max.
): Cardinal; cdecl;
// Returns number of samples currently available.
TSoundTouchNumSamples = function (Handle: TSoundTouchHandle): Cardinal; cdecl;
@ -170,6 +178,7 @@ var
SoundTouchGetSetting : TSoundTouchGetSetting;
SoundTouchNumUnprocessedSamples : TSoundTouchNumUnprocessedSamples;
SoundTouchReceiveSamples : TSoundTouchReceiveSamples;
SoundTouchReceiveSamplesI16 : TSoundTouchReceiveSamplesI16;
SoundTouchNumSamples : TSoundTouchNumSamples;
SoundTouchIsEmpty : TSoundTouchIsEmpty;
@ -232,6 +241,9 @@ type
property IsEmpty: Integer read GetIsEmpty;
end;
// list of exported functions and procedures
function IsSoundTouchLoaded: Boolean;
implementation
{ TSoundTouch }
@ -416,19 +428,23 @@ begin
end;
var
SoundTouchLibHandle: HINST;
SoundTouchDLLFile: PAnsiChar = 'SoundTouch.dll';
SoundTouchLibHandle: THandle;
SoundTouchDLLFile: AnsiString = 'libSoundTouchDll.so';
//SoundTouchDLLFile: AnsiString = 'SoundTouch.dll';
// bpm detect functions. untested -- if these don't work then remove:
bpm_createInstance: function(chan: CInt32; sampleRate : CInt32): THandle; cdecl;
bpm_createInstance: function(chan: int32; sampleRate : int32): THandle; cdecl;
bpm_destroyInstance: procedure(h: THandle); cdecl;
bpm_getBpm: function(h: THandle): cfloat; cdecl;
bpm_putSamples: procedure(h: THandle; const samples: pcfloat;
numSamples: cardinal); cdecl;
bpm_getBpm: function(h: THandle): Single; cdecl;
bpm_putSamples: procedure(h: THandle; const samples: PSingle; numSamples: cardinal); cdecl;
procedure InitDLL;
begin
SoundTouchLibHandle := LoadLibrary(SoundTouchDLLFile);
{$ifdef mswindows} // Windows
SoundTouchLibHandle := LoadLibrary('.\SoundTouchDll.dll');
{$else} // Unix
SoundTouchLibHandle := LoadLibrary('./libSoundTouchDll.so');
{$endif}
if SoundTouchLibHandle <> 0 then
try
Pointer(SoundTouchCreateInstance) := GetProcAddress(SoundTouchLibHandle, 'soundtouch_createInstance');
@ -473,6 +489,12 @@ begin
if SoundTouchLibHandle <> 0 then FreeLibrary(SoundTouchLibHandle);
end;
// returns 'true' if SoundTouch dynamic library has been successfully loaded, otherwise 'false'
function IsSoundTouchLoaded: Boolean;
begin;
result := SoundTouchLibHandle <> 0
end;
initialization
InitDLL;

View File

@ -0,0 +1 @@
../.libs/libSoundTouchDll.so

View File

@ -0,0 +1,36 @@
object Form1: TForm1
Left = 2237
Height = 128
Top = 242
Width = 381
Caption = 'SoundTouch test'
ClientHeight = 128
ClientWidth = 381
LCLVersion = '2.2.0.4'
object Load: TButton
Left = 19
Height = 50
Top = 16
Width = 144
Caption = 'Load SoundTouch'
OnClick = LoadClick
TabOrder = 0
end
object EditVersion: TEdit
Left = 184
Height = 34
Top = 80
Width = 184
TabOrder = 1
Text = 'n/a'
TextHint = 'click to populate'
end
object Label1: TLabel
Left = 19
Height = 17
Top = 90
Width = 156
Caption = 'Soundtouch lib version:'
WordWrap = True
end
end

View File

@ -0,0 +1,49 @@
unit main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, SoundTouchDLL;
type
{ TForm1 }
TForm1 = class(TForm)
EditVersion: TEdit;
Label1: TLabel;
Load: TButton;
procedure LoadClick(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.LoadClick(Sender: TObject);
var
version:string;
begin
if IsSoundTouchLoaded() then
version := SoundTouchGetVersionString()
else
version := '<library loading failed>';
EditVersion.Text:= version;
end;
end.

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<General>
<SessionStorage Value="InProjectDir"/>
<Title Value="soundtouchtest"/>
<Scaled Value="True"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<XPManifest>
<DpiAware Value="True"/>
</XPManifest>
<Icon Value="0"/>
</General>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
</RunParams>
<RequiredPackages>
<Item>
<PackageName Value="LCL"/>
</Item>
</RequiredPackages>
<Units>
<Unit>
<Filename Value="soundtouchtest.lpr"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target>
<Filename Value="soundtouchtest"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf3"/>
</Debugging>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions>
<Item>
<Name Value="EAbort"/>
</Item>
<Item>
<Name Value="ECodetoolError"/>
</Item>
<Item>
<Name Value="EFOpenError"/>
</Item>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,25 @@
program soundtouchtest;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
{$IFDEF HASAMIGA}
athreads,
{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, main
{ you can add units after this };
{$R *.res}
begin
RequireDerivedFormResource:=True;
Application.Scaled:=True;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectSession>
<Version Value="12"/>
<BuildModes Active="Default"/>
<Units>
<Unit>
<Filename Value="soundtouchtest.lpr"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="-1"/>
<TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/>
<UsageCount Value="21"/>
</Unit>
<Unit>
<Filename Value="main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<IsVisibleTab Value="True"/>
<CursorPos X="26" Y="43"/>
<UsageCount Value="21"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit>
<Unit>
<Filename Value="../SoundTouchDLL.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="37"/>
<CursorPos X="19"/>
<UsageCount Value="10"/>
</Unit>
<Unit>
<Filename Value="/usr/lib/lazarus/2.2.0/lcl/interfaces/gtk2/gtk2proc.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="7149"/>
<CursorPos X="3" Y="7184"/>
<UsageCount Value="10"/>
</Unit>
<Unit>
<Filename Value="/usr/lib/lazarus/2.2.0/components/freetype/easylazfreetype.pas"/>
<UnitName Value="EasyLazFreeType"/>
<EditorIndex Value="-1"/>
<TopLine Value="539"/>
<CursorPos X="16" Y="574"/>
<UsageCount Value="10"/>
</Unit>
<Unit>
<Filename Value="SoundTouchDLL.pas"/>
<EditorIndex Value="1"/>
<TopLine Value="326"/>
<CursorPos X="127" Y="379"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit>
</Units>
<JumpHistory HistoryIndex="29">
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="439" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="427" Column="37" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="439" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="427" Column="32" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="444" Column="48" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="439" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="416" Column="116" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="439" TopLine="403"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="45" Column="40"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="243" Column="38" TopLine="197"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="487" Column="38" TopLine="429"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="42" Column="8"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="41" Column="44"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="44" Column="6"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="43" Column="39"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="44" Column="7"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="38" Column="7"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="467" TopLine="423"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="212" Column="32" TopLine="78"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="361" Column="37" TopLine="308"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="466" Column="37" TopLine="413"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="467" Column="37" TopLine="413"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="466" Column="13" TopLine="413"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="361" Column="13" TopLine="326"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="110" Column="3" TopLine="74"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="180" Column="37" TopLine="145"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="179" Column="55" TopLine="145"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="146" Column="3" TopLine="145"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="149" TopLine="111"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="151" Column="31" TopLine="116"/>
</Position>
</JumpHistory>
<RunParams>
<FormatVersion Value="2"/>
<Modes ActiveMode=""/>
</RunParams>
</ProjectSession>
</CONFIG>

View File

@ -0,0 +1,47 @@
## Process this file with automake to create Makefile.in
##
## This file is part of SoundTouch, an audio processing library for pitch/time adjustments
##
## SoundTouch is free software; you can redistribute it and/or modify it under the
## terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## SoundTouch is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
## A PARTICULAR PURPOSE. See the GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the Free Software Foundation, Inc., 59 Temple
## Place - Suite 330, Boston, MA 02111-1307, USA
include $(top_srcdir)/config/am_include.mk
noinst_HEADERS=../SoundTouch/AAFilter.h ../SoundTouch/cpu_detect.h ../SoundTouch/cpu_detect_x86.cpp ../SoundTouch/FIRFilter.h \
../SoundTouch/RateTransposer.h ../SoundTouch/TDStretch.h ../SoundTouch/PeakFinder.h ../SoundTouch/InterpolateCubic.h \
../SoundTouch/InterpolateLinear.h ../SoundTouch/InterpolateShannon.h
include_HEADERS=SoundTouchDLL.h
lib_LTLIBRARIES=libSoundTouchDll.la
#
libSoundTouchDll_la_SOURCES=../SoundTouch/AAFilter.cpp ../SoundTouch/FIRFilter.cpp \
../SoundTouch/FIFOSampleBuffer.cpp ../SoundTouch/RateTransposer.cpp ../SoundTouch/SoundTouch.cpp \
../SoundTouch/TDStretch.cpp ../SoundTouch/sse_optimized.cpp ../SoundTouch/cpu_detect_x86.cpp \
../SoundTouch/BPMDetect.cpp ../SoundTouch/PeakFinder.cpp ../SoundTouch/InterpolateLinear.cpp \
../SoundTouch/InterpolateCubic.cpp ../SoundTouch/InterpolateShannon.cpp SoundTouchDLL.cpp
# Compiler flags
# Modify the default 0.0.0 to LIB_SONAME.0.0
AM_LDFLAGS=$(LDFLAGS) -version-info @LIB_SONAME@
if X86
CXXFLAGS1=-mstackrealign -msse
endif
if X86_64
CXXFLAGS2=-fPIC
endif
AM_CXXFLAGS=$(CXXFLAGS) $(CXXFLAGS1) $(CXXFLAGS2) -shared -DDLL_EXPORTS -fvisibility=hidden

View File

@ -90,10 +90,10 @@ SOUNDTOUCHDLL_API HANDLE __cdecl soundtouch_createInstance()
{
tmp->dwMagic = STMAGIC;
tmp->pst = new SoundTouch();
if (tmp->pst == NULL)
if (tmp->pst == nullptr)
{
delete tmp;
tmp = NULL;
tmp = nullptr;
}
}
return (HANDLE)tmp;
@ -107,7 +107,7 @@ SOUNDTOUCHDLL_API void __cdecl soundtouch_destroyInstance(HANDLE h)
sth->dwMagic = 0;
if (sth->pst) delete sth->pst;
sth->pst = NULL;
sth->pst = nullptr;
delete sth;
}
@ -207,22 +207,38 @@ SOUNDTOUCHDLL_API void __cdecl soundtouch_setPitchSemiTones(HANDLE h, float newP
/// Sets the number of channels, 1 = mono, 2 = stereo
SOUNDTOUCHDLL_API void __cdecl soundtouch_setChannels(HANDLE h, uint numChannels)
SOUNDTOUCHDLL_API int __cdecl soundtouch_setChannels(HANDLE h, uint numChannels)
{
STHANDLE *sth = (STHANDLE*)h;
if (sth->dwMagic != STMAGIC) return;
if (sth->dwMagic != STMAGIC) return 0;
try
{
sth->pst->setChannels(numChannels);
}
catch (const std::exception&)
{
return 0;
}
return 1;
}
/// Sets sample rate.
SOUNDTOUCHDLL_API void __cdecl soundtouch_setSampleRate(HANDLE h, uint srate)
SOUNDTOUCHDLL_API int __cdecl soundtouch_setSampleRate(HANDLE h, uint srate)
{
STHANDLE *sth = (STHANDLE*)h;
if (sth->dwMagic != STMAGIC) return;
if (sth->dwMagic != STMAGIC) return 0;
try
{
sth->pst->setSampleRate(srate);
}
catch (const std::exception&)
{
return 0;
}
return 1;
}
/// Flushes the last samples from the processing pipeline to the output.
/// Clears also the internal processing buffers.
@ -231,18 +247,26 @@ SOUNDTOUCHDLL_API void __cdecl soundtouch_setSampleRate(HANDLE h, uint srate)
/// stream. This function may introduce additional blank samples in the end
/// of the sound stream, and thus it's not recommended to call this function
/// in the middle of a sound stream.
SOUNDTOUCHDLL_API void __cdecl soundtouch_flush(HANDLE h)
SOUNDTOUCHDLL_API int __cdecl soundtouch_flush(HANDLE h)
{
STHANDLE *sth = (STHANDLE*)h;
if (sth->dwMagic != STMAGIC) return;
if (sth->dwMagic != STMAGIC) return 0;
try
{
sth->pst->flush();
}
catch (const std::exception&)
{
return 0;
}
return 1;
}
/// Adds 'numSamples' pcs of samples from the 'samples' memory position into
/// the input of the object. Notice that sample rate _has_to_ be set before
/// calling this function, otherwise throws a runtime_error exception.
SOUNDTOUCHDLL_API void __cdecl soundtouch_putSamples(HANDLE h,
SOUNDTOUCHDLL_API int __cdecl soundtouch_putSamples(HANDLE h,
const SAMPLETYPE *samples, ///< Pointer to sample buffer.
unsigned int numSamples ///< Number of samples in buffer. Notice
///< that in case of stereo-sound a single sample
@ -250,10 +274,18 @@ SOUNDTOUCHDLL_API void __cdecl soundtouch_putSamples(HANDLE h,
)
{
STHANDLE *sth = (STHANDLE*)h;
if (sth->dwMagic != STMAGIC) return;
if (sth->dwMagic != STMAGIC) return 0;
try
{
sth->pst->putSamples(samples, numSamples);
}
catch (const std::exception&)
{
return 0;
}
return 1;
}
/// int16 version of soundtouch_putSamples(): This accept int16 (short) sample data
/// and internally converts it to float format before processing
@ -341,11 +373,9 @@ SOUNDTOUCHDLL_API uint __cdecl soundtouch_numUnprocessedSamples(HANDLE h)
}
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere.
/// Receive ready samples from the processing pipeline.
///
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
/// if called with outBuffer=nullptr, just reduces amount of ready samples within the pipeline.
SOUNDTOUCHDLL_API uint __cdecl soundtouch_receiveSamples(HANDLE h,
SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples.
unsigned int maxSamples ///< How many samples to receive at max.
@ -376,7 +406,7 @@ SOUNDTOUCHDLL_API uint __cdecl soundtouch_receiveSamples_i16(HANDLE h,
if (sth->dwMagic != STMAGIC) return 0;
uint outTotal = 0;
if (outBuffer == NULL)
if (outBuffer == nullptr)
{
// only reduce sample count, not receive samples
return sth->pst->receiveSamples(maxSamples);
@ -444,11 +474,18 @@ SOUNDTOUCHDLL_API HANDLE __cdecl bpm_createInstance(int numChannels, int sampleR
if (tmp)
{
tmp->dwMagic = BPMMAGIC;
try
{
tmp->pbpm = new BPMDetect(numChannels, sampleRate);
if (tmp->pbpm == NULL)
}
catch (const std::exception&)
{
tmp->pbpm = nullptr;
}
if (tmp->pbpm == nullptr)
{
delete tmp;
tmp = NULL;
tmp = nullptr;
}
}
return (HANDLE)tmp;
@ -462,7 +499,7 @@ SOUNDTOUCHDLL_API void __cdecl bpm_destroyInstance(HANDLE h)
sth->dwMagic = 0;
if (sth->pbpm) delete sth->pbpm;
sth->pbpm = NULL;
sth->pbpm = nullptr;
delete sth;
}
@ -525,3 +562,21 @@ SOUNDTOUCHDLL_API float __cdecl bpm_getBpm(HANDLE h)
return bpmh->pbpm->getBpm();
}
/// Get beat position arrays. Note: The array includes also really low beat detection values
/// in absence of clear strong beats. Consumer may wish to filter low values away.
/// - "pos" receive array of beat positions
/// - "values" receive array of beat detection strengths
/// - max_num indicates max.size of "pos" and "values" array.
///
/// You can query a suitable array sized by calling this with nullptr in "pos" & "values".
///
/// \return number of beats in the arrays.
SOUNDTOUCHDLL_API int __cdecl bpm_getBeats(HANDLE h, float* pos, float* strength, int count)
{
BPMHANDLE *bpmh = (BPMHANDLE *)h;
if (bpmh->dwMagic != BPMMAGIC) return 0;
return bpmh->pbpm->getBeats(pos, strength, count);
}

View File

@ -48,12 +48,12 @@
#else
// GNU version
#ifdef DLL_EXPORTS
#if defined(DLL_EXPORTS) || defined(SoundTouchDLL_EXPORTS)
// GCC declaration for exporting functions
#define SOUNDTOUCHDLL_API extern "C" __attribute__((__visibility__("default")))
#else
// GCC doesn't require DLL imports
#define SOUNDTOUCHDLL_API
// import function
#define SOUNDTOUCHDLL_API extern "C"
#endif
// Linux-replacements for Windows declarations:
@ -112,10 +112,10 @@ SOUNDTOUCHDLL_API void __cdecl soundtouch_setPitchSemiTones(HANDLE h, float newP
/// Sets the number of channels, 1 = mono, 2 = stereo, n = multichannel
SOUNDTOUCHDLL_API void __cdecl soundtouch_setChannels(HANDLE h, unsigned int numChannels);
SOUNDTOUCHDLL_API int __cdecl soundtouch_setChannels(HANDLE h, unsigned int numChannels);
/// Sets sample rate.
SOUNDTOUCHDLL_API void __cdecl soundtouch_setSampleRate(HANDLE h, unsigned int srate);
SOUNDTOUCHDLL_API int __cdecl soundtouch_setSampleRate(HANDLE h, unsigned int srate);
/// Flushes the last samples from the processing pipeline to the output.
/// Clears also the internal processing buffers.
@ -124,12 +124,12 @@ SOUNDTOUCHDLL_API void __cdecl soundtouch_setSampleRate(HANDLE h, unsigned int s
/// stream. This function may introduce additional blank samples in the end
/// of the sound stream, and thus it's not recommended to call this function
/// in the middle of a sound stream.
SOUNDTOUCHDLL_API void __cdecl soundtouch_flush(HANDLE h);
SOUNDTOUCHDLL_API int __cdecl soundtouch_flush(HANDLE h);
/// Adds 'numSamples' pcs of samples from the 'samples' memory position into
/// the input of the object. Notice that sample rate _has_to_ be set before
/// calling this function, otherwise throws a runtime_error exception.
SOUNDTOUCHDLL_API void __cdecl soundtouch_putSamples(HANDLE h,
SOUNDTOUCHDLL_API int __cdecl soundtouch_putSamples(HANDLE h,
const float *samples, ///< Pointer to sample buffer.
unsigned int numSamples ///< Number of sample frames in buffer. Notice
///< that in case of multi-channel sound a single
@ -225,5 +225,16 @@ SOUNDTOUCHDLL_API void __cdecl bpm_putSamples_i16(HANDLE h,
/// \return Beats-per-minute rate, or zero if detection failed.
SOUNDTOUCHDLL_API float __cdecl bpm_getBpm(HANDLE h);
/// Get beat position arrays. Note: The array includes also really low beat detection values
/// in absence of clear strong beats. Consumer may wish to filter low values away.
/// - "pos" receive array of beat positions
/// - "values" receive array of beat detection strengths
/// - max_num indicates max.size of "pos" and "values" array.
///
/// You can query a suitable array sized by calling this with nullptr in "pos" & "values".
///
/// \return number of beats in the arrays.
SOUNDTOUCHDLL_API int __cdecl bpm_getBeats(HANDLE h, float *pos, float *strength, int count);
#endif // _SoundTouchDLL_h_

View File

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,0
PRODUCTVERSION 2,0,0,0
FILEVERSION 2,3,2,0
PRODUCTVERSION 2,3,2,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "Comments", "SoundTouch Library licensed for 3rd party applications subject to LGPL license v2.1. Visit http://www.surina.net/soundtouch for more information about the SoundTouch library."
VALUE "FileDescription", "SoundTouch Dynamic Link Library"
VALUE "FileVersion", "2.0.0.0"
VALUE "FileVersion", "2.3.3.0"
VALUE "InternalName", "SoundTouch"
VALUE "LegalCopyright", "Copyright (C) Olli Parviainen 2017"
VALUE "LegalCopyright", "Copyright (C) Olli Parviainen 2024"
VALUE "OriginalFilename", "SoundTouch.dll"
VALUE "ProductName", " SoundTouch Dynamic Link Library"
VALUE "ProductVersion", "2.0.0.0"
VALUE "ProductVersion", "2.3.3.0"
END
END
BLOCK "VarFileInfo"

View File

@ -21,28 +21,28 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{164DE61D-6391-4265-8273-30740117D356}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -95,7 +95,8 @@
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<MinimalRebuild>
</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader />
@ -106,6 +107,7 @@
<ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@ -134,7 +136,8 @@ copy $(OutDir)$(TargetName).lib ..\..\lib
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<MinimalRebuild>
</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader />
@ -144,6 +147,7 @@ copy $(OutDir)$(TargetName).lib ..\..\lib
<AssemblerListingLocation>$(OutDir)</AssemblerListingLocation>
<ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@ -182,6 +186,8 @@ copy $(OutDir)$(TargetName).lib ..\..\lib
<ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<MinimalRebuild />
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@ -223,6 +229,8 @@ copy $(OutDir)$(TargetName).lib ..\..\lib
<AssemblerListingLocation>$(OutDir)</AssemblerListingLocation>
<ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
<MinimalRebuild />
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>

View File

@ -1,5 +1,8 @@
#!/bin/bash
#
# This script is deprecated. Don't use this, the makefile can now compile
# the dynamic-link library 'libSoundTouchDLL.so' automatically.
#
# This script compiles SoundTouch dynamic-link library for GNU environment
# with wrapper functions that are easier to import to Java / Mono / etc
#
@ -16,7 +19,11 @@ if [[ $arch == *"86"* ]]; then
fi
fi
echo "*************************************************************************"
echo "NOTE: Rather use the makefile that can now build the dynamic-link library"
echo "*************************************************************************"
echo ""
echo "Building SoundTouchDLL for $arch with flags:$flags"
g++ -O3 -shared $flags -DDLL_EXPORTS -fvisibility=hidden -I../../include \
g++ -O3 -ffast-math -shared $flags -DDLL_EXPORTS -fvisibility=hidden -I../../include \
-I../SoundTouch -o SoundTouchDll.so SoundTouchDLL.cpp ../SoundTouch/*.cpp

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8.1"/>
</startup>
</configuration>

View File

@ -12,7 +12,7 @@ using System.Windows;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp-example")]
[assembly: AssemblyCopyright("Copyright Olli Parviainen © 2017")]
[assembly: AssemblyCopyright("Copyright © Olli Parviainen")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@ -8,8 +8,8 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace csharp_example.Properties
{
namespace csharp_example.Properties {
using System;
/// <summary>
@ -19,31 +19,26 @@ namespace csharp_example.Properties
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("csharp_example.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
@ -56,14 +51,11 @@ namespace csharp_example.Properties
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set
{
set {
resourceCulture = value;
}
}

View File

@ -8,21 +8,17 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace csharp_example.Properties
{
namespace csharp_example.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
public static Settings Default {
get {
return defaultInstance;
}
}

Binary file not shown.

View File

@ -9,14 +9,15 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>csharp_example</RootNamespace>
<AssemblyName>csharp-example</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
@ -24,6 +25,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>