diff -Nru mixxx-1.10.1-1/COPYING mixxx-1.11.0-bzr3863/COPYING --- mixxx-1.10.1-1/COPYING 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/COPYING 2013-05-09 13:58:23.000000000 +0000 @@ -1,3 +1,3 @@ -Mixxx is Copyright (C) 2000-2011 by its respective authors. This version -of the program is distributed under the General Public Licence version 2, +Mixxx is Copyright (C) 2000-2013 by its respective authors. This version +of the program is distributed under the General Public License version 2, as described in the file LICENSE distributed with the program. diff -Nru mixxx-1.10.1-1/LICENSE mixxx-1.11.0-bzr3863/LICENSE --- mixxx-1.10.1-1/LICENSE 2012-06-30 15:32:20.000000000 +0000 +++ mixxx-1.11.0-bzr3863/LICENSE 2013-05-09 13:58:23.000000000 +0000 @@ -1,5 +1,5 @@ -Mixxx version 1.10.1, Digital DJ'ing software. -Copyright (C) 2001-2012 Mixxx development team +Mixxx version 1.11.0, Digital DJ'ing software. +Copyright (C) 2001-2013 Mixxx Development Team Promotional tracks are copyright their respective owners and distributed with permission. @@ -8,11 +8,11 @@ (http://www.portaudio.com/) which is distributed under the PortAudio as-is license which can be found on their website. -This may also be in turn compiled with ASIO support -(http://www.steinberg.de) which is provided by the ASIO SDK, the -license for which can currently be found at: - - http://www.steinberg.de/534+M52087573ab0.html +This may also be in turn compiled with ASIO support, which is provided +by the Steinberg ASIO SDK. The Steinberg ASIO SDK and Steinberg VST +PlugIn SDK are Copyright Steinberg Media Technologies GmbH. ASIO and VST +are trademarks of Steinberg Media Technologies GmbH. The license is +available at http://www.steinberg.net/en/company/developer.html . On Windows you may receive a copy of the Microsoft Visual Studio runtime libraries. These are distributed only for the purpose of allowing @@ -43,13 +43,12 @@ Mixxx comes with ABSOLUTELY NO WARRANTY; - - GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -333,21 +332,6 @@ END OF TERMS AND CONDITIONS -KissFFT License -================== - -Copyright (c) 2003-2004 Mark Borgerding - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Fidlib License ================= GNU LESSER GENERAL PUBLIC LICENSE @@ -808,7 +792,9 @@ DAMAGES. END OF TERMS AND CONDITIONS - Google Test License + + +Google Test License ===================== Copyright 2008, Google Inc. @@ -1319,6 +1305,7 @@ END OF TERMS AND CONDITIONS + FLAC License ================ @@ -1385,7 +1372,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - libshout License ===================== @@ -2325,7 +2311,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - HSS1394 License ================== @@ -2961,6 +2946,7 @@ END OF TERMS AND CONDITIONS + Qt License ============== @@ -3424,7 +3410,6 @@ END OF TERMS AND CONDITIONS - Nokia Qt LGPL Exception version 1.1 As an additional permission to the GNU Lesser General Public License version Binary files /tmp/Ojme9apHqO/mixxx-1.10.1-1/Mixxx-Manual.pdf and /tmp/0vvJ6qcZK0/mixxx-1.11.0-bzr3863/Mixxx-Manual.pdf differ diff -Nru mixxx-1.10.1-1/README mixxx-1.11.0-bzr3863/README --- mixxx-1.10.1-1/README 2012-06-30 15:32:20.000000000 +0000 +++ mixxx-1.11.0-bzr3863/README 2013-05-09 13:58:23.000000000 +0000 @@ -1,4 +1,4 @@ -Mixxx 1.10.1 +Mixxx 1.11.0 * HOMEPAGE ************************************************* http://www.mixxx.org @@ -44,8 +44,13 @@ - taglib (New in 1.9!) - PortAudio-v19 - portmidi -- QT 4.5+ +- QT 4.6+ - scons +- protocol-buffers +- libusb-1.0 +- libmp4v2 (optional, m4a support) +- libfaad (optional, m4a support) +- vamp-plugin-sdk (optional, internal version included) NOTE: If you want JACK support in Mixxx, make sure you compile PortAudio-v19 with JACK support first. @@ -107,16 +112,16 @@ * CONTACT ************************************************** To contact the lead developer, send an email to -adam_d@users.sourceforge.net or subscribe to +rryan@mixxx.org or subscribe to mixxx-devel@lists.sourceforge.net and send a message to the list. * QT ******************************************************* On some platforms, Mixxx may come with a pre-built copy of -Qt. This code is licensed under the GPL and source for this +Qt. This code is licensed under the LGPL and source for this library may be obtained from: - http://trolltech.com/products/qt/downloads + http://qt-project.org/downloads * Microsoft Runtimes *************************************** On Microsoft platforms, Mixxx may come with runtime dlls diff -Nru mixxx-1.10.1-1/SConstruct mixxx-1.11.0-bzr3863/SConstruct --- mixxx-1.10.1-1/SConstruct 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/SConstruct 2013-05-09 13:58:23.000000000 +0000 @@ -26,18 +26,19 @@ import logging logging.getLogger().setLevel(logging.DEBUG) -from build import mixxx, features +from build import mixxx, features, depends target = ARGUMENTS.get('target', None) machine = ARGUMENTS.get('machine', None) build_type = ARGUMENTS.get('build', None) toolchain = ARGUMENTS.get('toolchain', None) available_features = [features.HifiEq, - features.MIDIScript, features.Mad, features.CoreAudio, features.MediaFoundation, features.HSS1394, + features.HID, + features.Bulk, features.VinylControl, features.Shoutcast, features.Profiling, @@ -51,14 +52,14 @@ features.LADSPA, features.MSVCDebug, features.MSVSHacks, + features.Vamp, + features.PromoTracks, # "Features" of dubious quality features.PerfTools, features.AsmLib, features.Tonal, features.IPod, - features.ScriptStudio, - features.CMetrics, features.FFMPEG, ] @@ -85,10 +86,18 @@ File('plugins/SConscript'), variant_dir=Dir(build.build_dir + "/plugins"), duplicate=0, exports=['build']) +#Build Vamp minimal plugins +#VariantDir("vamp-plugins", "src", duplicate=0) +mixxxminimal_depends = [ depends.SoundTouch ] +mixxxminimal_plugins = SConscript( + File('vamp-plugins/SConscript'), + variant_dir=Dir(build.build_dir + "/vamp-plugins"), + duplicate=0, exports=['build', 'mixxxminimal_depends']) + # Setup and build the "mixxx" executable target. Also sets up our install # targets for each platform. SConscript(File('src/SConscript'), variant_dir=Dir(build.build_dir), duplicate=0, - exports=['build', 'sources', 'soundsource_plugins']) + exports=['build', 'sources', 'soundsource_plugins', 'mixxxminimal_plugins']) # For convenience, copy the Mixxx binary out of the build directory to the # root. Don't do it on windows because the binary can't run on its own and needs @@ -97,5 +106,6 @@ Command("mixxx", os.path.join(build.build_dir, "mixxx"), Copy("$TARGET", "$SOURCE")) + #On OS X, if the bundle has been built, copy it up: #Command("Mixxx.app", os.path.join(build.build_dir, "Mixxx.app"), Copy("$TARGET", "$SOURCE")) diff -Nru mixxx-1.10.1-1/build/debian/changelog mixxx-1.11.0-bzr3863/build/debian/changelog --- mixxx-1.10.1-1/build/debian/changelog 2012-06-30 15:32:20.000000000 +0000 +++ mixxx-1.11.0-bzr3863/build/debian/changelog 2013-05-09 14:24:26.000000000 +0000 @@ -1,3 +1,15 @@ +mixxx (1.11.0-0ubuntu1) lucid; urgency=low + + * New upstream release. + + -- RJ Ryan Thu, 09 May 2013 01:19:27 -0400 + +mixxx (1.11.0~beta1-0ubuntu1) lucid; urgency=low + + * New upstream beta release + + -- RJ Ryan Thu, 21 Jun 2012 15:41:22 -0400 + mixxx (1.10.0-0ubuntu1) lucid; urgency=low * New upstream release. diff -Nru mixxx-1.10.1-1/build/debian/control mixxx-1.11.0-bzr3863/build/debian/control --- mixxx-1.10.1-1/build/debian/control 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/build/debian/control 2013-05-09 14:24:26.000000000 +0000 @@ -3,8 +3,9 @@ Priority: optional Maintainer: Ubuntu MOTU Developers XSBC-Original-Maintainer: RJ Ryan -Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, xlibmesa-gl-dev, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4..0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libmp4v2-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev +Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, xlibmesa-gl-dev, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4.6.0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libmp4v2-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev, vamp-plugin-sdk, libprotobuf-dev, protobuf-compiler, libusb-1.0-0-dev Standards-Version: 3.7.3 +Homepage: http://www.mixxx.org/ Package: mixxx Section: sound @@ -13,11 +14,44 @@ Recommends: libmp3lame0 Suggests: pdf-viewer Replaces: mixxx-data -Description: Digital DJ interface - Mixxx allows DJs to perform live mixes with their digital music library. A - robust mixing engine including filters, gains, a crossfader, and pitch control - are provided. Mixxx also features BPM detection to help DJs find the tempo of - songs in their library. - . - Mixxx works with ALSA, JACK, and OSS, and supports many popular DJ controllers - including the Hercules MK2 and M-Audio X-Session Pro. +Description: Free Digital DJ software. Start making live DJ mixes today. +Mixxx is free DJ software that gives you everything you need to perform live DJ mixes. +Blend songs together with automatic BPM matching and remix on-the-fly with looping +and hot cues. Whether you're a pro DJ or just getting started, Mixxx has you covered. + +Mixxx works with ALSA, JACK, OSS and supports many popular DJ controllers. + + Features include: + - Parallel or split scratchable waveform displays + - Waveform summaries + - Spinning vinyl widgets + - MP3, OGG, WAVE, FLAC, and optional unprotected aac (m4a) playback + - Extra playback formats through plugins + - Wave and Ogg recording with optional MP3 support + - Fast, database-powered library + - Crates and playlists for organizing your music + - Reads iTunes, Traktor, and Rhythmbox libraries + - History section keeps track of your setlists + - Internet Broadcasting with Shoutcast and Icecast + - Microphone Support + - Automatic crossfading with Auto DJ + - Pitch-independent time stretch (key lock) + - Adjustable pitch range + - Ramping pitchbend controls + - ReplayGain volume normalization + - Quantized loops, hotcues, and beatloops + - Synchronization and auto-beatmatching + - BPM detection and estimation + - Bulk BPM analysis + - Adjustable EQ shelves + - Crossfader curve control + - Sampler Decks + - Vinyl emulation with Serato, Traktor, and Mixvibes timecode support + - Multichannel soundcard support (playback and capture) + - Headphone cueing with multiple soundcard support + - Skinnable interface with several skins bundled + - Support for many DJ MIDI and HID controllers out-of-the-box + - Advanced MIDI/HID scripting engine + - Multiple simultaneous MIDI/HID controllers + - Multi-core CPU support + - 24-bit/96000 Hz playback and capture diff -Nru mixxx-1.10.1-1/build/debian/control.lucid mixxx-1.11.0-bzr3863/build/debian/control.lucid --- mixxx-1.10.1-1/build/debian/control.lucid 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/build/debian/control.lucid 2013-05-09 14:24:26.000000000 +0000 @@ -3,7 +3,7 @@ Priority: optional Maintainer: Ubuntu MOTU Developers XSBC-Original-Maintainer: RJ Ryan -Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, xlibmesa-gl-dev, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4..0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libmp4v2-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev +Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, xlibmesa-gl-dev, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4..0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libmp4v2-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev, vamp-plugin-sdk, libprotobuf-dev, protobuf-compiler, libusb-1.0-0-dev Standards-Version: 3.7.3 Package: mixxx diff -Nru mixxx-1.10.1-1/build/debian/control.maverick mixxx-1.11.0-bzr3863/build/debian/control.maverick --- mixxx-1.10.1-1/build/debian/control.maverick 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/build/debian/control.maverick 2013-05-09 14:24:26.000000000 +0000 @@ -3,7 +3,7 @@ Priority: optional Maintainer: Ubuntu MOTU Developers XSBC-Original-Maintainer: RJ Ryan -Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, xlibmesa-gl-dev, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4.6.0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libmp4v2-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev, libqtwebkit-dev +Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, xlibmesa-gl-dev, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4.6.0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libmp4v2-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev, libqtwebkit-dev, vamp-plugin-sdk, libprotobuf-dev, protobuf-compiler, libusb-1.0-0-dev Standards-Version: 3.7.3 Package: mixxx diff -Nru mixxx-1.10.1-1/build/debian/control.natty mixxx-1.11.0-bzr3863/build/debian/control.natty --- mixxx-1.10.1-1/build/debian/control.natty 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/build/debian/control.natty 2013-05-09 14:24:26.000000000 +0000 @@ -3,7 +3,7 @@ Priority: optional Maintainer: Ubuntu MOTU Developers XSBC-Original-Maintainer: RJ Ryan -Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4.6.0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libmp4v2-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev, libqtwebkit-dev +Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4.6.0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libmp4v2-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev, libqtwebkit-dev, vamp-plugin-sdk, libprotobuf-dev, protobuf-compiler, libusb-1.0-0-dev Standards-Version: 3.7.3 Package: mixxx diff -Nru mixxx-1.10.1-1/build/debian/control.oneiric mixxx-1.11.0-bzr3863/build/debian/control.oneiric --- mixxx-1.10.1-1/build/debian/control.oneiric 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/build/debian/control.oneiric 2013-05-09 14:24:26.000000000 +0000 @@ -3,7 +3,7 @@ Priority: optional Maintainer: Ubuntu MOTU Developers XSBC-Original-Maintainer: RJ Ryan -Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4.6.0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev, libqtwebkit-dev +Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4.6.0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev, libqtwebkit-dev, vamp-plugin-sdk, libprotobuf-dev, protobuf-compiler, libusb-1.0-0-dev Standards-Version: 3.7.3 Package: mixxx diff -Nru mixxx-1.10.1-1/build/debian/control.precise mixxx-1.11.0-bzr3863/build/debian/control.precise --- mixxx-1.10.1-1/build/debian/control.precise 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/build/debian/control.precise 2013-05-09 14:24:26.000000000 +0000 @@ -0,0 +1,23 @@ +Source: mixxx +Section: sound +Priority: optional +Maintainer: Ubuntu MOTU Developers +XSBC-Original-Maintainer: RJ Ryan +Build-Depends: debhelper (>= 4.0.0), pkg-config, docbook-to-man, libglu1-mesa-dev, libqt4-opengl-dev | libqt4-dev (>= 4.6.0), scons, libjack-dev, portaudio19-dev, libid3tag0-dev, libmad0-dev, libogg-dev, libsndfile1-dev, libasound2-dev, libvorbis-dev, libsoundtouch1-dev, libmp4v2-dev, libfaad-dev, libportmidi-dev, libtag1-dev, libshout-dev, libqtwebkit-dev, vamp-plugin-sdk, libprotobuf-dev, protobuf-compiler, libusb-1.0-0-dev +Standards-Version: 3.7.3 + +Package: mixxx +Section: sound +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libqt4-opengl, libqt4-svg, libqt4-xmlpatterns, libqt4-webkit, libqt4-sql, libqt4-sql-sqlite +Recommends: libmp3lame0 +Suggests: pdf-viewer +Replaces: mixxx-data +Description: Digital DJ interface + Mixxx allows DJs to perform live mixes with their digital music library. A + robust mixing engine including filters, gains, a crossfader, and pitch control + are provided. Mixxx also features BPM detection to help DJs find the tempo of + songs in their library. + . + Mixxx works with ALSA, JACK, and OSS, and supports many popular DJ controllers + including the Hercules MK2 and M-Audio X-Session Pro. diff -Nru mixxx-1.10.1-1/build/debian/copyright mixxx-1.11.0-bzr3863/build/debian/copyright --- mixxx-1.10.1-1/build/debian/copyright 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/build/debian/copyright 2013-05-09 14:24:26.000000000 +0000 @@ -3,16 +3,12 @@ It was downloaded from http://mixxx.sourceforge.net/ - Kissfft can be found at http://kissfft.sourceforge.net/ - gplot and vbrheadersdk have been removed from the original archive as they do not comply with the Debian Free Software Guidelines (DFSG). - -Copyright: + +Copyright: Mixxx Copyright (C) 2000-2004 Haste Andersen and Mixxx developers - Kissfft - Copyright (c) 2003-2004 Mark Borgerding Upstream Authors: Tue Haste Andersen and Ken Haste Andersen @@ -24,30 +20,3 @@ You are free to distribute this software under the terms of the GNU General Public License. On Debian systems, the complete text of the GNU General Public License can be found in the file `/usr/share/common-licenses/GPL'. - -Kissfft is distributed under a revised BSD license: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the author nor the names of any contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff -Nru mixxx-1.10.1-1/build/debian/mixxx.install mixxx-1.11.0-bzr3863/build/debian/mixxx.install --- mixxx-1.10.1-1/build/debian/mixxx.install 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/build/debian/mixxx.install 2013-05-09 14:24:26.000000000 +0000 @@ -2,3 +2,4 @@ usr/share/pixmaps usr/share/applications usr/share/mixxx +usr/lib/mixxx diff -Nru mixxx-1.10.1-1/build/debian/mixxx.sgml mixxx-1.11.0-bzr3863/build/debian/mixxx.sgml --- mixxx-1.10.1-1/build/debian/mixxx.sgml 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/build/debian/mixxx.sgml 2013-05-09 14:24:26.000000000 +0000 @@ -8,7 +8,7 @@ manpage.1: manpage.sgml docbook-to-man $< > $@ - + The docbook-to-man binary is found in the docbook-to-man package. Please remember that if you create the nroff version in one of the debian/rules file targets (such as build), you will need to include @@ -17,15 +17,15 @@ --> - Paul"> - Brossier"> + S."> + Brandt"> - November 26, 2004"> + April 12, 2013"> 1"> - piem@altern.org"> - + s.brandt@mixxx.org"> + MIXXX"> @@ -44,7 +44,7 @@ &dhsurname; - 2003 + 2013 &dhusername; &dhdate; @@ -57,59 +57,363 @@ &dhpackage; - a Digital Disc Jockey Interface + A Digital Disc Jockey Interface &dhpackage; + DESCRIPTION - - This manual page documents briefly the &dhpackage; command. - - &dhpackage; is a digital DJ system, where wave, - ogg and mp3 files can be mixed on a computer for use in live performances. - Filters, crossfader, and speed control are provided. &dhpackage; can sync - the 2 streams automatically, using an algorithm to detect the beat. - - &dhpackage; works with Jack or OSS and can be controlled through the GUI - and with external controllers, including MIDI devices and joysticks. The - GUI supports skins. - - This manual page was written for the &debian; distribution because - the original program does not have a manual page. Instead, it has - documentation in the pdf format; see below. - + + &dhpackage; is free DJ software that gives you + everything you need to perform live DJ mixes. Blend songs together with + automatic BPM matching and remix on-the-fly with looping and hot cues. + Whether you're a pro DJ or just getting started, Mixxx has you covered. + + + + &dhpackage; works with ALSA, JACK, OSS and supports many popular DJ + controllers. + + + + This manual page documents briefly the &dhpackage; + command line options. It does not describe all of the features + of &dhpackage; or how to use it; Instead, it has a documentation in pdf + format; see below. + + + KEY FEATURES + + + + + Parallel or split scratchable waveform displays. + + + MP3, OGG, WAVE, FLAC, and optional AAC (M4A) playback. + + + WAVE, OGG, and optional MP3 recording. + + + Fast, database-powered library. + + + Crates and playlists for organizing your music. + + + Reads iTunes, Traktor, and Rhythmbox libraries. + + + Cross-platform - works on Windows, Mac OS X and Linux. + + + Shoutcast and Icecast broadcasting. + + + Support for many DJ MIDI & HID controllers out-of-the-box. + + + Advanced MIDI scripting engine for maximum flexibility. + + + Vinyl emulation with Serato,Traktor, and Mixvibes timecode support. + + + Bulk BPM and beat detection. + + + ReplayGain volume normalization. + + + Automatic crossfading with Auto DJ. + + + Skinnable interface with several skins bundled. + + + + + For a full list of features go to: + . + + + &dhpackage; does not have AAC (M4A) playback support enabled by default due + to licensing restrictions. To enable playback of unprotected AAC (M4A) + files, you can build &dhpackage; from source. See also: + + + OPTIONS - - This program takes no command line argument. - + + Mixxx is designed to be as user-friendly as possible. As such, its command + line options are only useful for development or debugging, as they make + these tasks easier. &dhpackage; accepts the following + case-sensitive options on the command-line: + + + + + <FILE> + + + + Load the specified music file(s) at start-up. Each file you + specify will be loaded into the next virtual deck. Supported file + types: mp3, ogg, aiff, aif, wav, flac + + + + + + + <PATH> + + + + Top-level directory where Mixxx should look for its resource + files such as MIDI mappings, overriding the default installation + location. + + + + + + + <PATH> + + + + Top-level directory where Mixxx should look for sound source + plugins in addition to default locations. + + + + + + + <PATH> + + + + Top-level directory where Mixxx should look for settings. + + + + + + + + + + Causes Mixxx to display/log all of the MIDI/HID controller data + it receives and script functions it loads. + + + + + + + + + + Enables developer-mode. Includes extra log info, stats on + performance, and a Developer tools menu. + + + + + + + <LOCALE> + + + + Use a custom locale for loading translations (e.g 'fr'). + + + + + + + + + + + Starts &dhpackage; in full-screen mode. + + + + + + + + + + + Display a help message and exit. + + + + + SEE ALSO - - /usr/share/doc/mixxx/Mixxx-Manual.pdf - - The program is fully documented in the above pdf file. - + + /usr/share/doc/mixxx/Mixxx-Manual.pdf + + + The manual in pdf format should have come with your copy of &dhpackage;, + however there is an online copy available: + . + + - AUTHOR + FILES + + + + ~/.mixxx/ + + + + The directory where &dhpackage; stores its user data. + + + + + + ~/.mixxx/mixxx.cfg + + + + The &dhpackage; configuration file. + + + + + + ~/.mixxx/mixxxdb.sqlite + + + + The &dhpackage; library file. + Warning: Deleting your library + will lose all of your metadata. This includes saved hotcues, loops, + comments, ratings, and other library related metadata. Only delete + your library if you are fine with losing these. + + + + + + ~/.mixxx/analysis + + + + The directory where &dhpackage; stores any additional analysis data + that can't fit into the library file. Currently only the waveforms + are saved here. If you delete your library file you should also + delete this folder as the waveforms around 1MB each and are unusable + without the library that generated them. + + + + + + ~/.mixxx/controllers + + + + The directory where &dhpackage; stores user controller mappings. + All mappings that are created with the MIDI learning wizard are + saved here. If there are mappings for a controller in the default + resource directory and this directory &dhpackage; will use + the one saved here. + + + + + + /usr/share/mixxx + + + + The directory where &dhpackage; stores its default resources like + skins, MIDI/HID controller mappings, keyboard mappings, and + translations. + + + + + + /usr/share/doc/mixxx/Mixxx-Manual.pdf + + + + The &dhpackage; manual in pdf format. + + + + + - This manual page was written by &dhusername; (&dhemail;) for the - &debian; system (but may be used by others). Permission is granted to - copy, distribute and/or modify this document under the terms of the &gnu; - General Public License, Version 2 any later version published by the Free - Software Foundation. + + BUGS + + To report a bug or request a feature, go to the &dhpackage; bug tracker: + + + - On Debian systems, the complete text of the GNU General Public - License can be found in /usr/share/common-licenses/GPL. + + AUTHORS + Since 2000, over 150 developers, artists and translators have + helped create &dhpackage;. The current &dhpackage; development team is + led by RJ Ryan rryan@mixxx.org. + + + This manual page was written by &dhusername; &dhemail; for the &debian; + system (and may be used by others). Permission is granted to copy, + distribute and/or modify this document under the terms of the &gnu; + General Public License, Version 2 any later version published by the Free + Software Foundation. + + + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL-2. + + + + History + + + April 12, 2013 + + Completely revised for &dhpackage; 1.11 by Max Linke + and S.Brandt s.brandt@mixxx.org + + + + + November 26, 2004 + + Initial version by Paul Brossier piem@altern.org. + + + + + - Paul"> - Brossier"> + S."> + Brandt"> - November 26, 2004"> + April 12, 2013"> 1"> - piem@altern.org"> - + s.brandt@mixxx.org"> + MIXXX"> @@ -44,7 +44,7 @@ &dhsurname; - 2003 + 2013 &dhusername; &dhdate; @@ -57,59 +57,363 @@ &dhpackage; - a Digital Disc Jockey Interface + A Digital Disc Jockey Interface &dhpackage; + DESCRIPTION - - This manual page documents briefly the &dhpackage; command. - - &dhpackage; is a digital DJ system, where wave, - ogg and mp3 files can be mixed on a computer for use in live performances. - Filters, crossfader, and speed control are provided. &dhpackage; can sync - the 2 streams automatically, using an algorithm to detect the beat. - - &dhpackage; works with Jack or OSS and can be controlled through the GUI - and with external controllers, including MIDI devices and joysticks. The - GUI supports skins. - - This manual page was written for the &debian; distribution because - the original program does not have a manual page. Instead, it has - documentation in the pdf format; see below. - + + &dhpackage; is free DJ software that gives you + everything you need to perform live DJ mixes. Blend songs together with + automatic BPM matching and remix on-the-fly with looping and hot cues. + Whether you're a pro DJ or just getting started, Mixxx has you covered. + + + + &dhpackage; works with ALSA, JACK, OSS and supports many popular DJ + controllers. + + + + This manual page documents briefly the &dhpackage; + command line options. It does not describe all of the features + of &dhpackage; or how to use it; Instead, it has a documentation in pdf + format; see below. + + + KEY FEATURES + + + + + Parallel or split scratchable waveform displays. + + + MP3, OGG, WAVE, FLAC, and optional AAC (M4A) playback. + + + WAVE, OGG, and optional MP3 recording. + + + Fast, database-powered library. + + + Crates and playlists for organizing your music. + + + Reads iTunes, Traktor, and Rhythmbox libraries. + + + Cross-platform - works on Windows, Mac OS X and Linux. + + + Shoutcast and Icecast broadcasting. + + + Support for many DJ MIDI & HID controllers out-of-the-box. + + + Advanced MIDI scripting engine for maximum flexibility. + + + Vinyl emulation with Serato,Traktor, and Mixvibes timecode support. + + + Bulk BPM and beat detection. + + + ReplayGain volume normalization. + + + Automatic crossfading with Auto DJ. + + + Skinnable interface with several skins bundled. + + + + + For a full list of features go to: + . + + + &dhpackage; does not have AAC (M4A) playback support enabled by default due + to licensing restrictions. To enable playback of unprotected AAC (M4A) + files, you can build &dhpackage; from source. See also: + + + OPTIONS - - This program takes no command line argument. - + + Mixxx is designed to be as user-friendly as possible. As such, its command + line options are only useful for development or debugging, as they make + these tasks easier. &dhpackage; accepts the following + case-sensitive options on the command-line: + + + + + <FILE> + + + + Load the specified music file(s) at start-up. Each file you + specify will be loaded into the next virtual deck. Supported file + types: mp3, ogg, aiff, aif, wav, flac + + + + + + + <PATH> + + + + Top-level directory where Mixxx should look for its resource + files such as MIDI mappings, overriding the default installation + location. + + + + + + + <PATH> + + + + Top-level directory where Mixxx should look for sound source + plugins in addition to default locations. + + + + + + + <PATH> + + + + Top-level directory where Mixxx should look for settings. + + + + + + + + + + Causes Mixxx to display/log all of the MIDI/HID controller data + it receives and script functions it loads. + + + + + + + + + + Enables developer-mode. Includes extra log info, stats on + performance, and a Developer tools menu. + + + + + + + <LOCALE> + + + + Use a custom locale for loading translations (e.g 'fr'). + + + + + + + + + + + Starts &dhpackage; in full-screen mode. + + + + + + + + + + + Display a help message and exit. + + + + + SEE ALSO - - /usr/share/doc/mixxx/Mixxx-Manual.pdf - - The program is fully documented in the above pdf file. - + + /usr/share/doc/mixxx/Mixxx-Manual.pdf + + + The manual in pdf format should have come with your copy of &dhpackage;, + however there is an online copy available: + . + + - AUTHOR + FILES + + + + ~/.mixxx/ + + + + The directory where &dhpackage; stores its user data. + + + + + + ~/.mixxx/mixxx.cfg + + + + The &dhpackage; configuration file. + + + + + + ~/.mixxx/mixxxdb.sqlite + + + + The &dhpackage; library file. + Warning: Deleting your library + will lose all of your metadata. This includes saved hotcues, loops, + comments, ratings, and other library related metadata. Only delete + your library if you are fine with losing these. + + + + + + ~/.mixxx/analysis + + + + The directory where &dhpackage; stores any additional analysis data + that can't fit into the library file. Currently only the waveforms + are saved here. If you delete your library file you should also + delete this folder as the waveforms around 1MB each and are unusable + without the library that generated them. + + + + + + ~/.mixxx/controllers + + + + The directory where &dhpackage; stores user controller mappings. + All mappings that are created with the MIDI learning wizard are + saved here. If there are mappings for a controller in the default + resource directory and this directory &dhpackage; will use + the one saved here. + + + + + + /usr/share/mixxx + + + + The directory where &dhpackage; stores its default resources like + skins, MIDI/HID controller mappings, keyboard mappings, and + translations. + + + + + + /usr/share/doc/mixxx/Mixxx-Manual.pdf + + + + The &dhpackage; manual in pdf format. + + + + + - This manual page was written by &dhusername; (&dhemail;) for the - &debian; system (but may be used by others). Permission is granted to - copy, distribute and/or modify this document under the terms of the &gnu; - General Public License, Version 2 any later version published by the Free - Software Foundation. + + BUGS + + To report a bug or request a feature, go to the &dhpackage; bug tracker: + + + - On Debian systems, the complete text of the GNU General Public - License can be found in /usr/share/common-licenses/GPL. + + AUTHORS + Since 2000, over 150 developers, artists and translators have + helped create &dhpackage;. The current &dhpackage; development team is + led by RJ Ryan rryan@mixxx.org. + + + This manual page was written by &dhusername; &dhemail; for the &debian; + system (and may be used by others). Permission is granted to copy, + distribute and/or modify this document under the terms of the &gnu; + General Public License, Version 2 any later version published by the Free + Software Foundation. + + + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL-2. + + + + History + + + April 12, 2013 + + Completely revised for &dhpackage; 1.11 by Max Linke + and S.Brandt s.brandt@mixxx.org + + + + + November 26, 2004 + + Initial version by Paul Brossier piem@altern.org. + + + + + - - - -
-

SoundTouch audio processing library v1.5.0 -

-

SoundTouch library Copyright (c) Olli -Parviainen 2002-2009

-
-

1. Introduction

-

SoundTouch is an open-source audio -processing library that allows changing the sound tempo, pitch -and playback rate parameters independently from each other, i.e.:

-
    -
  • Sound tempo can be increased or decreased while -maintaining the original pitch
  • -
  • Sound pitch can be increased or decreased while -maintaining the original tempo
  • -
  • Change playback rate that affects both tempo -and pitch at the same time
  • -
  • Choose any combination of tempo/pitch/rate
  • -
-

1.1 Contact information

-

Author email: oparviai 'at' iki.fi

-

SoundTouch WWW page: http://www.surina.net/soundtouch

-
-

2. Compiling SoundTouch

-

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 section "sample data format" -for more information.

-

2.1. Building in Microsoft Windows

-

Project files for Microsoft Visual C++ 6.0 and Visual C++ .NET are -supplied with the source code package. 

-

Please notice that SoundTouch -library uses processor-specific optimizations for Pentium III and AMD -processors. Visual Studio .NET and later versions supports the required -instructions by default, but Visual Studio 6.0 requires a processor pack upgrade -to be installed in order to support these optimizations. The processor pack upgrade can be downloaded from -Microsoft site at this URL:

-

http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx

-

If the above URL is unavailable or removed, go -to http://msdn.microsoft.com -and perform a search with keywords "processor pack".

-

To build the binaries with Visual C++ -compiler, either run "make-win.bat" script, or open the -appropriate project files in source code directories with Visual -Studio. The final executable will appear under the "SoundTouch\bin" -directory. If using the Visual Studio IDE instead of the make-win.bat script, directories bin and -lib may need to be created manually to the SoundTouch -package root for the final executables. The make-win.bat script -creates these directories automatically. -

-

2.2. Building in Gnu platforms

-

The SoundTouch library can be compiled in -practically any platform supporting GNU compiler (GCC) tools. -SoundTouch have been tested with gcc version 3.3.4., but it -shouldn't be very specific about the gcc version. Assembler-level -performance optimizations for GNU platform are currently available in -x86 platforms only, they are automatically disabled and replaced with -standard C routines in other processor platforms.

-

To build and install the binaries, run the -following commands in the SoundTouch/ directory:

- - - - - - - - - - - - - - - -
-
./configure  -
-
-

Configures the SoundTouch package for the local -environment.

-
-
make         -
-
-

Builds the SoundTouch library & -SoundStretch utility.

-
-
make install -
-
-

Installs the SoundTouch & BPM libraries -to /usr/local/lib and SoundStretch utility to /usr/local/bin. -Please notice that 'root' privileges may be required to install the -binaries to the destination locations.

-
-

2.2.1 Required GNU tools 

-

Bash shell, GNU C++ compiler, libtool, autoconf and automake 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, in Ubuntu Linux these can be acquired and -installed with the following command:

-
sudo apt-get install automake autoconf libtool build-essential
-

2.2.2 Problems with GCC compiler compatibility

-

At the release time the SoundTouch package has been tested to compile in -GNU/Linux platform. However, in past it's happened that new gcc versions aren't -necessarily compatible with the assembler settings used in the optimized -routines. If you have problems getting the -SoundTouch library compiled, try the workaround of disabling the optimizations -by editing the file "include/STTypes.h" and removing the following -definition there:

-
-
#define ALLOW_OPTIMIZATIONS 1
-
-

2.2.3 Problems with configure script or build process 

-

Incompatibilities between various GNU toolchain versions may cause errors when running the "configure" script or building the source -codes, if your GNU tool versions are not compatible with the versions used for -preparing the SoundTouch kit. 

-

To resolve the issue, regenerate the configure scripts with your local tool -set by running -the "./bootstrap" script included in the SoundTouch source code -kit. After that, run the configure script and make as usually.

-

2.2.4 Compiler issues with non-x86 processors

-

SoundTouch library works also on non-x86 processors.

-

However, in case that you get compiler errors when trying to compile for non-Intel processor, edit the file -"source\SoundTouch\Makefile.am" and remove the "-msse2" -flag on the AM_CXXFLAGS line:

-
AM_CXXFLAGS=-O3 -fcheck-new -I../../include    # Note: -msse2 flag removed!
-

After that, run "./bootstrap" script, and then run configure -and make again.

-
-

3. About implementation & Usage tips

-

3.1. Supported sample data formats

-

The sample data format can be chosen -between 16bit signed integer and 32bit floating point values, the -default is 32bit floating point.

- -

-In Windows environment, the sample data format is chosen -in file "STTypes.h" by choosing one of the following -defines:

-
    -
  • #define INTEGER_SAMPLES -for 16bit signed -integer
  • -
  • #define FLOAT_SAMPLES for -32bit floating point
  • -
-

-In GNU environment, the floating sample format is used by default, but -integer sample format can be chosen by giving the -following switch to the configure script: -

-
./configure --enable-integer-samples
-
- -

The sample data can have either single (mono) -or double (stereo) audio channel. Stereo data is interleaved so -that every other data value is for left channel and every second -for right channel. Notice 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.

-

Sample rates between 8000-48000H are -supported.

-

3.2. Processing latency

-

The processing and latency constraints of -the SoundTouch library are:

-
    -
  • Input/output processing latency for the -SoundTouch processor is around 100 ms. This is when time-stretching is -used. If the rate transposing effect alone is used, the latency -requirement -is much shorter, see section 'About algorithms'.
  • -
  • Processing CD-quality sound (16bit stereo -sound with 44100H sample rate) in real-time or faster is possible -starting from processors equivalent to Intel Pentium 133Mh or better, -if using the "quick" processing algorithm. If not using the "quick" -mode or -if floating point sample data are being used, several times more CPU -power is typically required.
  • -
-

3.3. About algorithms

-

SoundTouch provides three seemingly -independent effects: tempo, pitch and playback rate control. -These three controls are implemented as combination of two primary -effects, sample rate transposing and time-stretching.

-

Sample rate transposing affects -both the audio stream duration and pitch. It's implemented simply -by converting the original audio sample stream to the  desired -duration by interpolating from the original audio samples. In SoundTouch, linear interpolation with anti-alias filtering is -used. Theoretically a higher-order interpolation provide better -result than 1st order linear interpolation, but in audio -application linear interpolation together with anti-alias -filtering performs subjectively about as well as higher-order -filtering would.

-

Time-stretching means changing -the audio stream duration without affecting it's pitch. SoundTouch -uses WSOLA-like time-stretching routines that operate in the time -domain. Compared to sample rate transposing, time-stretching is a -much heavier operation and also requires a longer processing -"window" of sound samples used by the -processing algorithm, thus increasing the algorithm input/output -latency. Typical i/o latency for the SoundTouch -time-stretch algorithm is around 100 ms.

-

Sample rate transposing and time-stretching -are then used together to produce the tempo, pitch and rate -controls:

-
    -
  • 'Tempo' control is -implemented purely by time-stretching.
  • -
  • 'Rate' control is implemented -purely by sample rate transposing.
  • -
  • 'Pitch' control is -implemented as a combination of time-stretching and sample rate -transposing. For example, to increase pitch the audio stream is first -time-stretched to longer duration (without affecting pitch) and then -transposed back to original duration by sample rate transposing, which -simultaneously reduces duration and increases pitch. The result is -original duration but increased pitch.
  • -
-

3.4 Tuning the algorithm parameters

-

The time-stretch algorithm has few -parameters that can be tuned to optimize sound quality for -certain application. The current default parameters have been -chosen by iterative if-then analysis (read: "trial and error") -to obtain best subjective sound quality in pop/rock music -processing, but in applications processing different kind of -sound the default parameter set may result into a sub-optimal -result.

-

The time-stretch algorithm default -parameter values are set by the following #defines in file "TDStretch.h":

-
-
#define DEFAULT_SEQUENCE_MS     AUTOMATIC
-#define DEFAULT_SEEKWINDOW_MS   AUTOMATIC
-#define DEFAULT_OVERLAP_MS      8
-
-

These parameters affect to the time-stretch -algorithm as follows:

-
    -
  • DEFAULT_SEQUENCE_MS: This is -the default length of a single processing sequence in milliseconds -which determines the how the original sound is chopped in -the time-stretch algorithm. Larger values mean fewer sequences -are used in processing. In principle a larger value sounds better when -slowing down the tempo, but worse when increasing the tempo and vice -versa. 
    -
    - By default, this setting value is calculated automatically according to - tempo value.
    -
  • -
  • DEFAULT_SEEKWINDOW_MS: The seeking window -default length in milliseconds is for the algorithm that seeks the best -possible overlapping location. This determines from how -wide a sample "window" the algorithm can use to find an optimal mixing -location when the sound sequences are to be linked back together. 
    -
    -The bigger this window setting is, the higher the possibility to find a -better mixing position becomes, but at the same time large values may -cause a "drifting" sound artifact because neighboring sequences can be -chosen at more uneven intervals. If there's a disturbing artifact that -sounds as if a constant frequency was drifting around, try reducing -this setting.
    -
    - By default, this setting value is calculated automatically according to - tempo value.
    -
  • -
  • DEFAULT_OVERLAP_MS: Overlap -length in milliseconds. When the sound sequences are mixed back -together to form again a continuous sound stream, this parameter -defines how much the ends of the consecutive sequences will overlap with each other.
    -
    - 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.
  • -
-

Notice that these parameters can also be -set during execution time with functions "TDStretch::setParameters()" -and "SoundTouch::setSetting()".

-

The table below summaries how the -parameters can be adjusted for different applications:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Parameter nameDefault value -magnitudeLarger value -affects...Smaller value -affects...Effect to CPU burden
-
SEQUENCE_MS
-
Default value is relatively -large, chosen for slowing down music tempoLarger value is usually -better for slowing down tempo. Growing the value decelerates the -"echoing" artifact when slowing down the tempo.Smaller value might be better -for speeding up tempo. Reducing the value accelerates the "echoing" -artifact when slowing down the tempo Increasing the parameter -value reduces computation burden
-
SEEKWINDOW_MS
-
Default value is relatively -large, chosen for slowing down music tempoLarger value eases finding a -good mixing position, but may cause a "drifting" artifactSmaller reduce possibility to -find a good mixing position, but reduce the "drifting" artifact.Increasing the parameter -value increases computation burden
-
OVERLAP_MS
-
Default value is relatively -large, chosen to suit with above parameters. If you reduce the "sequence -ms" setting, you might wish to try a smaller value.Increasing the parameter -value increases computation burden
-

3.5 Performance Optimizations

-

General optimizations:

-

The time-stretch routine has a 'quick' mode -that substantially speeds up the algorithm but may degrade the -sound quality by a small amount. This mode is activated by -calling SoundTouch::setSetting() function with parameter  id -of SETTING_USE_QUICKSEEK and value "1", i.e.

-
-

setSetting(SETTING_USE_QUICKSEEK, 1);

-
-

CPU-specific optimizations:

-
    -
  • Intel MMX optimized routines are used with -compatible CPUs when 16bit integer sample type is used. MMX optimizations are available both in Win32 and Gnu/x86 platforms. -Compatible processors are Intel PentiumMMX and later; AMD K6-2, Athlon -and later.
  • -
  • Intel SSE optimized routines are used with -compatible CPUs when floating point sample type is used. SSE optimizations are currently implemented for Win32 platform only. -Processors compatible with SSE extension are Intel processors starting -from Pentium-III, and AMD processors starting from Athlon XP.
  • -
  • AMD 3DNow! optimized routines are used with -compatible CPUs when floating point sample type is used, but SSE -extension isn't supported . 3DNow! optimizations are currently -implemented for Win32 platform only. These optimizations are used in -AMD K6-2 and Athlon (classic) CPU's; better performing SSE routines are -used with AMD processor starting from Athlon XP.
  • -
-
-

4. SoundStretch audio processing utility -

-

SoundStretch audio processing utility
-Copyright (c) Olli Parviainen 2002-2009

-

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 used to -process sound in your own program, but it can as well be used for -processing sound files.

-

4.1. SoundStretch Usage Instructions

-

SoundStretch Usage syntax:

-
-
soundstretch infilename outfilename [switches]
-
-

Where:

- - - - - - - - - - - - - - - -
-
"infilename"
-
Name of the input sound -data file (in .WAV audio file format). Give "stdin" as filename to use - standard input pipe.
-
"outfilename"
-
Name of the output sound -file where the resulting sound is saved (in .WAV audio file format). -This parameter may be omitted if you  don't want to save the -output -(e.g. when only calculating BPM rate with '-bpm' switch). Give "stdout" - as filename to use standard output pipe.
-
 [switches]
-
Are one or more control -switches.
-

Available control switches are:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-tempo=n 
-
Change the sound tempo by n -percents (n = -95.0 .. +5000.0 %)
-
-pitch=n
-
Change the sound pitch by n -semitones (n = -60.0 .. + 60.0 semitones)
-
-rate=n
-
Change the sound playback rate by -n percents (n = -95.0 .. +5000.0 %)
-
-bpm=n
-
Detect the Beats-Per-Minute (BPM) rate of the sound and adjust the tempo to meet 'n' - BPMs. When this switch is - applied, the "-tempo" switch is ignored. If "=n" is -omitted, i.e. switch "-bpm" is used alone, then the BPM rate is - estimated and displayed, but tempo not adjusted according to the BPM -value.
-
-quick
-
Use quicker tempo change -algorithm. Gains speed but loses sound quality.
-
-naa
-
Don't use anti-alias -filtering in sample rate transposing. Gains speed but loses sound -quality.
-
-license
-
Displays the program license -text (LGPL)
-

Notes:

-
    -
  • To use standard input/output pipes for processing, give "stdin" - and "stdout" as input/output filenames correspondingly. The - standard input/output pipes will still carry the audio data in .wav audio - file format.
  • -
  • The numerical switches allow both integer (e.g. "-tempo=123") and decimal (e.g. -"-tempo=123.45") numbers.
  • -
  • The "-naa" and/or "-quick" switches can be -used to reduce CPU usage while compromising some sound quality
  • -
  • The BPM detection algorithm works by detecting -repeating bass or drum patterns at low frequencies of <250Hz. A - lower-than-expected BPM figure may be reported for music with uneven or - complex bass patterns.
  • -
-

4.2. SoundStretch usage examples

-

Example 1

-

The following command increases tempo of -the sound file "originalfile.wav" by 12.5% and stores result to file "destinationfile.wav":

-
-
soundstretch originalfile.wav destinationfile.wav -tempo=12.5
-
-

Example 2

-

The following command decreases the sound -pitch (key) of the sound file "orig.wav" by two -semitones and stores the result to file "dest.wav":

-
-
soundstretch orig.wav dest.wav -pitch=-2
-
-

Example 3

-

The following command processes the file "orig.wav" by decreasing the sound tempo by 25.3% and -increasing the sound pitch (key) by 1.5 semitones. Resulting .wav audio data is -directed to standard output pipe:

-
-
soundstretch orig.wav stdout -tempo=-25.3 -pitch=1.5
-
-

Example 4

-

The following command detects the BPM rate -of the file "orig.wav" and adjusts the tempo to match -100 beats per minute. Result is stored to file "dest.wav":

-
-
soundstretch orig.wav dest.wav -bpm=100
-
-

Example 5

-

The following command reads .wav sound data from standard input pipe and -estimates the BPM rate:

-
-
soundstretch stdin -bpm
-
-
-

5. Change History

-

5.1. SoundTouch library Change History

- -

1.5.0:

-
    -
  • Added normalization to correlation calculation and improvement automatic seek/sequence parameter calculation to improve sound quality
  • - -
  • Bugfixes:  -
      -
    • Fixed negative array indexing in quick seek algorithm
    • -
    • FIR autoalias filter running too far in processing buffer
    • -
    • Check against zero sample count in rate transposing
    • -
    • Fix for x86-64 support: Removed pop/push instructions from the cpu detection algorithm. 
    • -
    • Check against empty buffers in FIFOSampleBuffer
    • -
    • Other minor fixes & code cleanup
    • -
    -
  • - -
  • Fixes in compilation scripts for non-Intel platforms
  • -
  • Added Dynamic-Link-Library (DLL) version of SoundTouch library build, - provided with Delphi/Pascal wrapper for calling the dll routines
  • -
  • Added #define PREVENT_CLICK_AT_RATE_CROSSOVER that prevents a click artifact - when crossing the nominal pitch from either positive to negative side or vice - versa
  • - -
- -

1.4.1:

-
    -
  • Fixed a buffer overflow bug in BPM detect algorithm routines if processing - more than 2048 samples at one call 
  • - -
- -

1.4.0:

-
    -
  • Improved sound quality by automatic calculation of time stretch algorithm - processing parameters according to tempo setting
  • -
  • Moved BPM detection routines from SoundStretch application into SoundTouch - library
  • -
  • Bugfixes: Usage of uninitialied variables, GNU build scripts, compiler errors - due to 'const' keyword mismatch.
  • -
  • Source code cleanup
  • - -
- -

v1.3.1: -

-
    -
  • Changed static class declaration to GCC 4.x compiler compatible syntax.
  • -
  • Enabled MMX/SSE-optimized routines also for GCC compilers. Earlier -the MMX/SSE-optimized routines were written in compiler-specific inline -assembler, now these routines are migrated to use compiler intrinsic -syntax which allows compiling the same MMX/SSE-optimized source code with -both Visual C++ and GCC compilers.
  • -
  • Set floating point as the default sample format and added switch to -the GNU configure script for selecting the other sample format.
  • - -
- -

v1.3.0: -

-
    -
  • Fixed tempo routine output duration inaccuracy due to rounding -error
  • -
  • Implemented separate processing routines for integer and -floating arithmetic to allow improvements to floating point routines -(earlier used algorithms mostly optimized for integer arithmetic also -for floating point samples)
  • -
  • Fixed a bug that distorts sound if sample rate changes during the -sound stream
  • -
  • Fixed a memory leak that appeared in MMX/SSE/3DNow! optimized -routines
  • -
  • Reduced redundant code pieces in MMX/SSE/3DNow! optimized -routines vs. the standard C routines.
  • -
  • MMX routine incompatibility with new gcc compiler versions
  • -
  • Other miscellaneous bug fixes
  • -
-

v1.2.1:

-
    -
  • Added automake/autoconf scripts for GNU -platforms (in courtesy of David Durham)
  • -
  • Fixed SCALE overflow bug in rate transposer -routine.
  • -
  • Fixed 64bit address space bugs.
  • -
  • Created a 'soundtouch' namespace for -SAMPLETYPE definitions.
  • -
-

v1.2.0:

-
    -
  • Added support for 32bit floating point sample -data type with SSE/3DNow! optimizations for Win32 platform (SSE/3DNow! optimizations currently not supported in GCC environment)
  • -
  • Replaced 'make-gcc' script for GNU environment -by master Makefile
  • -
  • Added time-stretch routine configurability to -SoundTouch main class
  • -
  • Bugfixes
  • -
-

v1.1.1:

-
    -
  • Moved SoundTouch under lesser GPL license (LGPL). This allows using SoundTouch library in programs that aren't -released under GPL license.
  • -
  • Changed MMX routine organiation so that MMX optimized routines are now implemented in classes that are derived from -the basic classes having the standard non-mmx routines.
  • -
  • MMX routines to support gcc version 3.
  • -
  • Replaced windows makefiles by script using the .dsw files
  • -
-

v1.01:

-
    -
  • "mmx_gcc.cpp": Added "using namespace std" and -removed "return 0" from a function with void return value to fix -compiler errors when compiling the library in Solaris environment.
  • -
  • Moved file "FIFOSampleBuffer.h" to "include" -directory to allow accessing the FIFOSampleBuffer class from external -files.
  • -
-

v1.0:

-
    -
  • Initial release
  • -
-

 

-

5.2. SoundStretch application Change -History

- -

1.4.0:

-
    -
  • Moved BPM detection routines from SoundStretch application into SoundTouch - library
  • -
  • Allow using standard input/output pipes as audio processing input/output - streams
  • - -
- -

v1.3.0:

-
    -
  • Simplified accessing WAV files with floating -point sample format. -
  • -
-

v1.2.1:

-
    -
  • Fixed 64bit address space bugs.
  • -
-

v1.2.0:

-
    -
  • Added support for 32bit floating point sample -data type
  • -
  • Restructured the BPM routines into separate -library
  • -
  • Fixed big-endian conversion bugs in WAV file -routines (hopefully :)
  • -
-

v1.1.1:

-
    -
  • Fixed bugs in WAV file reading & added -byte-order conversion for big-endian processors.
  • -
  • Moved SoundStretch source code under 'example' -directory to highlight difference from SoundTouch stuff.
  • -
  • Replaced windows makefiles by script using the .dsw files
  • -
  • Output file name isn't required if output -isn't desired (e.g. if using the switch '-bpm' in plain format only)
  • -
-

v1.1:

-
    -
  • Fixed "Release" settings in Microsoft Visual -C++ project file (.dsp)
  • -
  • Added beats-per-minute (BPM) detection routine -and command-line switch "-bpm"
  • -
-

v1.01:

-
    -
  • Initial release
  • -
-
-

6. Acknowledgements

-

Kudos for these people who have contributed to development or submitted -bugfixes since -SoundTouch v1.3.1:

-
    -
  • Arthur A
  • -
  • Richard Ash
  • -
  • Stanislav Brabec
  • -
  • Christian Budde
  • -
  • Brian Cameron
  • -
  • Jason Champion
  • -
  • Patrick Colis
  • -
  • Justin Frankel
  • -
  • Jason Garland
  • -
  • Takashi Iwai
  • -
  • Paulo Pizarro
  • -
  • RJ Ryan
  • -
  • John Sheehy
  • -
-

Moral greetings to all other contributors and users also!

-
-

7. 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 version 2.1 as published by the Free Software -Foundation.

-

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

-
- - - diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/RateTransposer.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/RateTransposer.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/RateTransposer.cpp 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/RateTransposer.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,628 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// Sample rate transposer. Changes sample rate by using linear interpolation -/// together with anti-alias filtering (first order interpolation with anti- -/// alias filtering should be quite adequate for this application) -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-10-31 16:37:24 +0200 (Sat, 31 Oct 2009) $ -// File revision : $Revision: 4 $ -// -// $Id: RateTransposer.cpp 74 2009-10-31 14:37:24Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include "RateTransposer.h" -#include "AAFilter.h" - -using namespace std; -using namespace soundtouch; - - -/// A linear samplerate transposer class that uses integer arithmetics. -/// for the transposing. -class RateTransposerInteger : public RateTransposer -{ -protected: - int iSlopeCount; - int iRate; - SAMPLETYPE sPrevSampleL, sPrevSampleR; - - virtual void resetRegisters(); - - virtual uint transposeStereo(SAMPLETYPE *dest, - const SAMPLETYPE *src, - uint numSamples); - virtual uint transposeMono(SAMPLETYPE *dest, - const SAMPLETYPE *src, - uint numSamples); - -public: - RateTransposerInteger(); - virtual ~RateTransposerInteger(); - - /// Sets new target rate. Normal rate = 1.0, smaller values represent slower - /// rate, larger faster rates. - virtual void setRate(float newRate); - -}; - - -/// A linear samplerate transposer class that uses floating point arithmetics -/// for the transposing. -class RateTransposerFloat : public RateTransposer -{ -protected: - float fSlopeCount; - SAMPLETYPE sPrevSampleL, sPrevSampleR; - - virtual void resetRegisters(); - - virtual uint transposeStereo(SAMPLETYPE *dest, - const SAMPLETYPE *src, - uint numSamples); - virtual uint transposeMono(SAMPLETYPE *dest, - const SAMPLETYPE *src, - uint numSamples); - -public: - RateTransposerFloat(); - virtual ~RateTransposerFloat(); -}; - - - - -// 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 * RateTransposer::operator new(size_t s) -{ - throw runtime_error("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!"); - return NULL; -} - - -RateTransposer *RateTransposer::newInstance() -{ -#ifdef INTEGER_SAMPLES - return ::new RateTransposerInteger; -#else - return ::new RateTransposerFloat; -#endif -} - - -// Constructor -RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer) -{ - numChannels = 2; - bUseAAFilter = TRUE; - fRate = 0; - - // Instantiates the anti-alias filter with default tap length - // of 32 - pAAFilter = new AAFilter(32); -} - - - -RateTransposer::~RateTransposer() -{ - delete pAAFilter; -} - - - -/// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable -void RateTransposer::enableAAFilter(BOOL newMode) -{ - bUseAAFilter = newMode; -} - - -/// Returns nonzero if anti-alias filter is enabled. -BOOL RateTransposer::isAAFilterEnabled() const -{ - return bUseAAFilter; -} - - -AAFilter *RateTransposer::getAAFilter() -{ - return pAAFilter; -} - - - -// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower -// iRate, larger faster iRates. -void RateTransposer::setRate(float newRate) -{ - double fCutoff; - - fRate = newRate; - - // design a new anti-alias filter - if (newRate > 1.0f) - { - fCutoff = 0.5f / newRate; - } - else - { - fCutoff = 0.5f * newRate; - } - pAAFilter->setCutoffFreq(fCutoff); -} - - -// Outputs as many samples of the 'outputBuffer' as possible, and if there's -// any room left, outputs also as many of the incoming samples as possible. -// The goal is to drive the outputBuffer empty. -// -// It's allowed for 'output' and 'input' parameters to point to the same -// memory position. -/* -void RateTransposer::flushStoreBuffer() -{ - if (storeBuffer.isEmpty()) return; - - outputBuffer.moveSamples(storeBuffer); -} -*/ - - -// Adds 'nSamples' pcs of samples from the 'samples' memory position into -// the input of the object. -void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples) -{ - processSamples(samples, nSamples); -} - - - -// Transposes up the sample rate, causing the observed playback 'rate' of the -// sound to decrease -void RateTransposer::upsample(const SAMPLETYPE *src, uint nSamples) -{ - uint count, sizeTemp, num; - - // If the parameter 'uRate' value is smaller than 'SCALE', first transpose - // the samples and then apply the anti-alias filter to remove aliasing. - - // First check that there's enough room in 'storeBuffer' - // (+16 is to reserve some slack in the destination buffer) - sizeTemp = (uint)((float)nSamples / fRate + 16.0f); - - // Transpose the samples, store the result into the end of "storeBuffer" - count = transpose(storeBuffer.ptrEnd(sizeTemp), src, nSamples); - storeBuffer.putSamples(count); - - // Apply the anti-alias filter to samples in "store output", output the - // result to "dest" - num = storeBuffer.numSamples(); - count = pAAFilter->evaluate(outputBuffer.ptrEnd(num), - storeBuffer.ptrBegin(), num, (uint)numChannels); - outputBuffer.putSamples(count); - - // Remove the processed samples from "storeBuffer" - storeBuffer.receiveSamples(count); -} - - -// Transposes down the sample rate, causing the observed playback 'rate' of the -// sound to increase -void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples) -{ - uint count, sizeTemp; - - // If the parameter 'uRate' value is larger than 'SCALE', first apply the - // anti-alias filter to remove high frequencies (prevent them from folding - // over the lover frequencies), then transpose. - - // Add the new samples to the end of the storeBuffer - storeBuffer.putSamples(src, nSamples); - - // Anti-alias filter the samples to prevent folding and output the filtered - // data to tempBuffer. Note : because of the FIR filter length, the - // filtering routine takes in 'filter_length' more samples than it outputs. - assert(tempBuffer.isEmpty()); - sizeTemp = storeBuffer.numSamples(); - - count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp), - storeBuffer.ptrBegin(), sizeTemp, (uint)numChannels); - - if (count == 0) return; - - // Remove the filtered samples from 'storeBuffer' - storeBuffer.receiveSamples(count); - - // Transpose the samples (+16 is to reserve some slack in the destination buffer) - sizeTemp = (uint)((float)nSamples / fRate + 16.0f); - count = transpose(outputBuffer.ptrEnd(sizeTemp), tempBuffer.ptrBegin(), count); - outputBuffer.putSamples(count); -} - - -// Transposes sample rate by applying anti-alias filter to prevent folding. -// Returns amount of samples returned in the "dest" buffer. -// The maximum amount of samples that can be returned at a time is set by -// the 'set_returnBuffer_size' function. -void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples) -{ - uint count; - uint sizeReq; - - if (nSamples == 0) return; - assert(pAAFilter); - - // If anti-alias filter is turned off, simply transpose without applying - // the filter - if (bUseAAFilter == FALSE) - { - sizeReq = (uint)((float)nSamples / fRate + 1.0f); - count = transpose(outputBuffer.ptrEnd(sizeReq), src, nSamples); - outputBuffer.putSamples(count); - return; - } - - // Transpose with anti-alias filter - if (fRate < 1.0f) - { - upsample(src, nSamples); - } - else - { - downsample(src, nSamples); - } -} - - -// Transposes the sample rate of the given samples using linear interpolation. -// Returns the number of samples returned in the "dest" buffer -inline uint RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) -{ - if (numChannels == 2) - { - return transposeStereo(dest, src, nSamples); - } - else - { - return transposeMono(dest, src, nSamples); - } -} - - -// Sets the number of channels, 1 = mono, 2 = stereo -void RateTransposer::setChannels(int nChannels) -{ - assert(nChannels > 0); - if (numChannels == nChannels) return; - - assert(nChannels == 1 || nChannels == 2); - numChannels = nChannels; - - storeBuffer.setChannels(numChannels); - tempBuffer.setChannels(numChannels); - outputBuffer.setChannels(numChannels); - - // Inits the linear interpolation registers - resetRegisters(); -} - - -// Clears all the samples in the object -void RateTransposer::clear() -{ - outputBuffer.clear(); - storeBuffer.clear(); -} - - -// Returns nonzero if there aren't any samples available for outputting. -int RateTransposer::isEmpty() const -{ - int res; - - res = FIFOProcessor::isEmpty(); - if (res == 0) return 0; - return storeBuffer.isEmpty(); -} - - -////////////////////////////////////////////////////////////////////////////// -// -// RateTransposerInteger - integer arithmetic implementation -// - -/// fixed-point interpolation routine precision -#define SCALE 65536 - -// Constructor -RateTransposerInteger::RateTransposerInteger() : RateTransposer() -{ - // Notice: use local function calling syntax for sake of clarity, - // to indicate the fact that C++ constructor can't call virtual functions. - RateTransposerInteger::resetRegisters(); - RateTransposerInteger::setRate(1.0f); -} - - -RateTransposerInteger::~RateTransposerInteger() -{ -} - - -void RateTransposerInteger::resetRegisters() -{ - iSlopeCount = 0; - sPrevSampleL = - sPrevSampleR = 0; -} - - - -// Transposes the sample rate of the given samples using linear interpolation. -// 'Mono' version of the routine. Returns the number of samples returned in -// the "dest" buffer -uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) -{ - unsigned int i, used; - LONG_SAMPLETYPE temp, vol1; - - if (nSamples == 0) return 0; // no samples, no work - - used = 0; - i = 0; - - // Process the last sample saved from the previous call first... - while (iSlopeCount <= SCALE) - { - vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount); - temp = vol1 * sPrevSampleL + iSlopeCount * src[0]; - dest[i] = (SAMPLETYPE)(temp / SCALE); - i++; - iSlopeCount += iRate; - } - // now always (iSlopeCount > SCALE) - iSlopeCount -= SCALE; - - while (1) - { - while (iSlopeCount > SCALE) - { - iSlopeCount -= SCALE; - used ++; - if (used >= nSamples - 1) goto end; - } - vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount); - temp = src[used] * vol1 + iSlopeCount * src[used + 1]; - dest[i] = (SAMPLETYPE)(temp / SCALE); - - i++; - iSlopeCount += iRate; - } -end: - // Store the last sample for the next round - sPrevSampleL = src[nSamples - 1]; - - return i; -} - - -// Transposes the sample rate of the given samples using linear interpolation. -// 'Stereo' version of the routine. Returns the number of samples returned in -// the "dest" buffer -uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) -{ - unsigned int srcPos, i, used; - LONG_SAMPLETYPE temp, vol1; - - if (nSamples == 0) return 0; // no samples, no work - - used = 0; - i = 0; - - // Process the last sample saved from the sPrevSampleLious call first... - while (iSlopeCount <= SCALE) - { - vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount); - temp = vol1 * sPrevSampleL + iSlopeCount * src[0]; - dest[2 * i] = (SAMPLETYPE)(temp / SCALE); - temp = vol1 * sPrevSampleR + iSlopeCount * src[1]; - dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE); - i++; - iSlopeCount += iRate; - } - // now always (iSlopeCount > SCALE) - iSlopeCount -= SCALE; - - while (1) - { - while (iSlopeCount > SCALE) - { - iSlopeCount -= SCALE; - used ++; - if (used >= nSamples - 1) goto end; - } - srcPos = 2 * used; - vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount); - temp = src[srcPos] * vol1 + iSlopeCount * src[srcPos + 2]; - dest[2 * i] = (SAMPLETYPE)(temp / SCALE); - temp = src[srcPos + 1] * vol1 + iSlopeCount * src[srcPos + 3]; - dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE); - - i++; - iSlopeCount += iRate; - } -end: - // Store the last sample for the next round - sPrevSampleL = src[2 * nSamples - 2]; - sPrevSampleR = src[2 * nSamples - 1]; - - return i; -} - - -// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower -// iRate, larger faster iRates. -void RateTransposerInteger::setRate(float newRate) -{ - iRate = (int)(newRate * SCALE + 0.5f); - RateTransposer::setRate(newRate); -} - - -////////////////////////////////////////////////////////////////////////////// -// -// RateTransposerFloat - floating point arithmetic implementation -// -////////////////////////////////////////////////////////////////////////////// - -// Constructor -RateTransposerFloat::RateTransposerFloat() : RateTransposer() -{ - // Notice: use local function calling syntax for sake of clarity, - // to indicate the fact that C++ constructor can't call virtual functions. - RateTransposerFloat::resetRegisters(); - RateTransposerFloat::setRate(1.0f); -} - - -RateTransposerFloat::~RateTransposerFloat() -{ -} - - -void RateTransposerFloat::resetRegisters() -{ - fSlopeCount = 0; - sPrevSampleL = - sPrevSampleR = 0; -} - - - -// Transposes the sample rate of the given samples using linear interpolation. -// 'Mono' version of the routine. Returns the number of samples returned in -// the "dest" buffer -uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) -{ - unsigned int i, used; - - used = 0; - i = 0; - - // Process the last sample saved from the previous call first... - while (fSlopeCount <= 1.0f) - { - dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]); - i++; - fSlopeCount += fRate; - } - fSlopeCount -= 1.0f; - - if (nSamples > 1) - { - while (1) - { - while (fSlopeCount > 1.0f) - { - fSlopeCount -= 1.0f; - used ++; - if (used >= nSamples - 1) goto end; - } - dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[used] + fSlopeCount * src[used + 1]); - i++; - fSlopeCount += fRate; - } - } -end: - // Store the last sample for the next round - sPrevSampleL = src[nSamples - 1]; - - return i; -} - - -// Transposes the sample rate of the given samples using linear interpolation. -// 'Mono' version of the routine. Returns the number of samples returned in -// the "dest" buffer -uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) -{ - unsigned int srcPos, i, used; - - if (nSamples == 0) return 0; // no samples, no work - - used = 0; - i = 0; - - // Process the last sample saved from the sPrevSampleLious call first... - while (fSlopeCount <= 1.0f) - { - dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]); - dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * src[1]); - i++; - fSlopeCount += fRate; - } - // now always (iSlopeCount > 1.0f) - fSlopeCount -= 1.0f; - - if (nSamples > 1) - { - while (1) - { - while (fSlopeCount > 1.0f) - { - fSlopeCount -= 1.0f; - used ++; - if (used >= nSamples - 1) goto end; - } - srcPos = 2 * used; - - dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos] - + fSlopeCount * src[srcPos + 2]); - dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1] - + fSlopeCount * src[srcPos + 3]); - - i++; - fSlopeCount += fRate; - } - } -end: - // Store the last sample for the next round - sPrevSampleL = src[2 * nSamples - 2]; - sPrevSampleR = src[2 * nSamples - 1]; - - return i; -} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/RateTransposer.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/RateTransposer.h --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/RateTransposer.h 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/RateTransposer.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,159 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// Sample rate transposer. Changes sample rate by using linear interpolation -/// together with anti-alias filtering (first order interpolation with anti- -/// alias filtering should be quite adequate for this application). -/// -/// Use either of the derived classes of 'RateTransposerInteger' or -/// 'RateTransposerFloat' for corresponding integer/floating point tranposing -/// algorithm implementation. -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ -// File revision : $Revision: 4 $ -// -// $Id: RateTransposer.h 63 2009-02-21 16:00:14Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 RateTransposer_H -#define RateTransposer_H - -#include -#include "AAFilter.h" -#include "FIFOSamplePipe.h" -#include "FIFOSampleBuffer.h" - -#include "STTypes.h" - -namespace soundtouch -{ - -/// A common linear samplerate transposer class. -/// -/// Note: Use function "RateTransposer::newInstance()" to create a new class -/// instance instead of the "new" operator; that function automatically -/// chooses a correct implementation depending on if integer or floating -/// arithmetics are to be used. -class RateTransposer : public FIFOProcessor -{ -protected: - /// Anti-alias filter object - AAFilter *pAAFilter; - - float fRate; - - int numChannels; - - /// Buffer for collecting samples to feed the anti-alias filter between - /// two batches - FIFOSampleBuffer storeBuffer; - - /// Buffer for keeping samples between transposing & anti-alias filter - FIFOSampleBuffer tempBuffer; - - /// Output sample buffer - FIFOSampleBuffer outputBuffer; - - BOOL bUseAAFilter; - - virtual void resetRegisters() = 0; - - virtual uint transposeStereo(SAMPLETYPE *dest, - const SAMPLETYPE *src, - uint numSamples) = 0; - virtual uint transposeMono(SAMPLETYPE *dest, - const SAMPLETYPE *src, - uint numSamples) = 0; - inline uint transpose(SAMPLETYPE *dest, - const SAMPLETYPE *src, - uint numSamples); - - void downsample(const SAMPLETYPE *src, - uint numSamples); - void upsample(const SAMPLETYPE *src, - uint numSamples); - - /// Transposes sample rate by applying anti-alias filter to prevent folding. - /// Returns amount of samples returned in the "dest" buffer. - /// The maximum amount of samples that can be returned at a time is set by - /// the 'set_returnBuffer_size' function. - void processSamples(const SAMPLETYPE *src, - uint numSamples); - - -public: - RateTransposer(); - virtual ~RateTransposer(); - - /// Operator 'new' is overloaded so that it automatically creates a suitable instance - /// depending on if we're to use integer or floating point arithmetics. - static void *operator new(size_t s); - - /// Use this function instead of "new" operator to create a new instance of this class. - /// This function automatically chooses a correct implementation, depending on if - /// integer ot floating point arithmetics are to be used. - static RateTransposer *newInstance(); - - /// Returns the output buffer object - FIFOSamplePipe *getOutput() { return &outputBuffer; }; - - /// Returns the store buffer object - FIFOSamplePipe *getStore() { return &storeBuffer; }; - - /// Return anti-alias filter object - AAFilter *getAAFilter(); - - /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable - void enableAAFilter(BOOL newMode); - - /// Returns nonzero if anti-alias filter is enabled. - BOOL isAAFilterEnabled() const; - - /// Sets new target rate. Normal rate = 1.0, smaller values represent slower - /// rate, larger faster rates. - virtual void setRate(float newRate); - - /// Sets the number of channels, 1 = mono, 2 = stereo - void setChannels(int channels); - - /// Adds 'numSamples' pcs of samples from the 'samples' memory position into - /// the input of the object. - void putSamples(const SAMPLETYPE *samples, uint numSamples); - - /// Clears all the samples in the object - void clear(); - - /// Returns nonzero if there aren't any samples available for outputting. - int isEmpty() const; -}; - -} - -#endif diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/STTypes.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/STTypes.h --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/STTypes.h 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/STTypes.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,158 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// Common type definitions for SoundTouch audio processing library. -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-05-17 14:30:57 +0300 (Sun, 17 May 2009) $ -// File revision : $Revision: 3 $ -// -// $Id: STTypes.h 70 2009-05-17 11:30:57Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 STTypes_H -#define STTypes_H - -typedef unsigned int uint; -typedef unsigned long ulong; - -/* -#ifdef __GNUC__ - // In GCC, include soundtouch_config.h made by config scritps - #include "soundtouch_config.h" -#endif -*/ - -#ifndef _WINDEF_ - // if these aren't defined already by Windows headers, define now - - typedef int BOOL; - -#ifndef FALSE - #define FALSE 0 -#endif -#ifndef TRUE - #define TRUE 1 -#endif - -#endif // _WINDEF_ - -namespace soundtouch -{ - -/// Activate these undef's to overrule the possible sampletype -/// setting inherited from some other header file: -//#undef INTEGER_SAMPLES -//#undef FLOAT_SAMPLES - -#if !(INTEGER_SAMPLES || FLOAT_SAMPLES) - - /// Choose either 32bit floating point or 16bit integer sampletype - /// by choosing one of the following defines, unless this selection - /// has already been done in some other file. - //// - /// Notes: - /// - In Windows environment, choose the sample format with the - /// following defines. - /// - In GNU environment, the floating point samples are used by - /// default, but integer samples can be chosen by giving the - /// following switch to the configure script: - /// ./configure --enable-integer-samples - /// However, if you still prefer to select the sample format here - /// also in GNU environment, then please #undef the INTEGER_SAMPLE - /// and FLOAT_SAMPLE defines first as in comments above. - //#define INTEGER_SAMPLES 1 //< 16bit integer samples - #define FLOAT_SAMPLES 1 //< 32bit float samples - - #endif - - #if (WIN32 || __i386__ || __x86_64__) - /// Define this to allow X86-specific assembler/intrinsic optimizations. - /// Notice that library contains also usual C++ versions of each of these - /// these routines, so if you're having difficulties getting the optimized - /// routines compiled for whatever reason, you may disable these optimizations - /// to make the library compile. - - -// XXX Mixxx change: we define this ourselves, and if we let ST do it here, we -// have it defined yet we don't compile in the sse/mmx sources when scons gets -// optimize=1 --bkgood -// #define ALLOW_X86_OPTIMIZATIONS 1 - - #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 ALLOW_NONEXACT_SIMD_OPTIMIZATION 1 - - - #ifdef INTEGER_SAMPLES - // 16bit integer sample type - typedef short SAMPLETYPE; - // data type for sample accumulation: Use 32bit integer to prevent overflows - typedef long LONG_SAMPLETYPE; - - #ifdef FLOAT_SAMPLES - // check that only one sample type is defined - #error "conflicting sample types defined" - #endif // FLOAT_SAMPLES - - #ifdef ALLOW_X86_OPTIMIZATIONS - // Allow MMX optimizations - #define ALLOW_MMX 1 - #endif - - #else - - // floating point samples - typedef float SAMPLETYPE; - // data type for sample accumulation: Use double to utilize full precision. - typedef double LONG_SAMPLETYPE; - - #ifdef ALLOW_X86_OPTIMIZATIONS - // Allow 3DNow! and SSE optimizations - #if WIN32 - #define ALLOW_3DNOW 1 - #endif - - #define ALLOW_SSE 1 - #endif - - #endif // INTEGER_SAMPLES -}; - - -// When this #define is active, eliminates a clicking sound when the "rate" or "pitch" -// parameter setting crosses from value <1 to >=1 or vice versa during processing. -// Default is off as such crossover is untypical case and involves a slight sound -// quality compromise. -//#define PREVENT_CLICK_AT_RATE_CROSSOVER 1 - -#endif diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/SoundTouch.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/SoundTouch.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/SoundTouch.cpp 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/SoundTouch.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,480 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -/// -/// SoundTouch - main class for tempo/pitch/rate adjusting routines. -/// -/// Notes: -/// - Initialize the SoundTouch object instance by setting up the sound stream -/// parameters with functions 'setSampleRate' and 'setChannels', then set -/// desired tempo/pitch/rate settings with the corresponding functions. -/// -/// - The SoundTouch class behaves like a first-in-first-out pipeline: The -/// samples that are to be processed are fed into one of the pipe by calling -/// function 'putSamples', while the ready processed samples can be read -/// from the other end of the pipeline with function 'receiveSamples'. -/// -/// - The SoundTouch processing classes require certain sized 'batches' of -/// samples in order to process the sound. For this reason the classes buffer -/// incoming samples until there are enough of samples available for -/// processing, then they carry out the processing step and consequently -/// make the processed samples available for outputting. -/// -/// - For the above reason, the processing routines introduce a certain -/// 'latency' between the input and output, so that the samples input to -/// SoundTouch may not be immediately available in the output, and neither -/// the amount of outputtable samples may not immediately be in direct -/// relationship with the amount of previously input samples. -/// -/// - The tempo/pitch/rate control parameters can be altered during processing. -/// Please notice though that they aren't currently protected by semaphores, -/// so in multi-thread application external semaphore protection may be -/// required. -/// -/// - This class utilizes classes 'TDStretch' for tempo change (without modifying -/// pitch) and 'RateTransposer' for changing the playback rate (that is, both -/// tempo and pitch in the same ratio) of the sound. The third available control -/// 'pitch' (change pitch but maintain tempo) is produced by a combination of -/// combining the two other controls. -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-05-19 07:57:30 +0300 (Tue, 19 May 2009) $ -// File revision : $Revision: 4 $ -// -// $Id: SoundTouch.cpp 73 2009-05-19 04:57:30Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include - -#include "SoundTouch.h" -#include "TDStretch.h" -#include "RateTransposer.h" -#include "cpu_detect.h" - -using namespace soundtouch; - -/// test if two floating point numbers are equal -#define TEST_FLOAT_EQUAL(a, b) (fabs(a - b) < 1e-10) - - -/// Print library version string for autoconf -extern "C" void soundtouch_ac_test() -{ - printf("SoundTouch Version: %s\n",SOUNDTOUCH_VERSION); -} - - -SoundTouch::SoundTouch() -{ - // Initialize rate transposer and tempo changer instances - - pRateTransposer = RateTransposer::newInstance(); - pTDStretch = TDStretch::newInstance(); - - setOutPipe(pTDStretch); - - rate = tempo = 0; - - virtualPitch = - virtualRate = - virtualTempo = 1.0; - - calcEffectiveRateAndTempo(); - - channels = 0; - bSrateSet = FALSE; -} - - - -SoundTouch::~SoundTouch() -{ - delete pRateTransposer; - delete pTDStretch; -} - - - -/// Get SoundTouch library version string -const char *SoundTouch::getVersionString() -{ - static const char *_version = SOUNDTOUCH_VERSION; - - return _version; -} - - -/// Get SoundTouch library version Id -uint SoundTouch::getVersionId() -{ - return SOUNDTOUCH_VERSION_ID; -} - - -// Sets the number of channels, 1 = mono, 2 = stereo -void SoundTouch::setChannels(uint numChannels) -{ - if (numChannels != 1 && numChannels != 2) - { - throw std::runtime_error("Illegal number of channels"); - } - channels = numChannels; - pRateTransposer->setChannels((int)numChannels); - pTDStretch->setChannels((int)numChannels); -} - - - -// Sets new rate control value. Normal rate = 1.0, smaller values -// represent slower rate, larger faster rates. -void SoundTouch::setRate(float newRate) -{ - virtualRate = newRate; - calcEffectiveRateAndTempo(); -} - - - -// Sets new rate control value as a difference in percents compared -// to the original rate (-50 .. +100 %) -void SoundTouch::setRateChange(float newRate) -{ - virtualRate = 1.0f + 0.01f * newRate; - calcEffectiveRateAndTempo(); -} - - - -// Sets new tempo control value. Normal tempo = 1.0, smaller values -// represent slower tempo, larger faster tempo. -void SoundTouch::setTempo(float newTempo) -{ - virtualTempo = newTempo; - calcEffectiveRateAndTempo(); -} - - - -// Sets new tempo control value as a difference in percents compared -// to the original tempo (-50 .. +100 %) -void SoundTouch::setTempoChange(float newTempo) -{ - virtualTempo = 1.0f + 0.01f * newTempo; - calcEffectiveRateAndTempo(); -} - - - -// Sets new pitch control value. Original pitch = 1.0, smaller values -// represent lower pitches, larger values higher pitch. -void SoundTouch::setPitch(float newPitch) -{ - virtualPitch = newPitch; - calcEffectiveRateAndTempo(); -} - - - -// Sets pitch change in octaves compared to the original pitch -// (-1.00 .. +1.00) -void SoundTouch::setPitchOctaves(float newPitch) -{ - virtualPitch = (float)exp(0.69314718056f * newPitch); - calcEffectiveRateAndTempo(); -} - - - -// Sets pitch change in semi-tones compared to the original pitch -// (-12 .. +12) -void SoundTouch::setPitchSemiTones(int newPitch) -{ - setPitchOctaves((float)newPitch / 12.0f); -} - - - -void SoundTouch::setPitchSemiTones(float newPitch) -{ - setPitchOctaves(newPitch / 12.0f); -} - - -// Calculates 'effective' rate and tempo values from the -// nominal control values. -void SoundTouch::calcEffectiveRateAndTempo() -{ - float oldTempo = tempo; - float oldRate = rate; - - tempo = virtualTempo / virtualPitch; - rate = virtualPitch * virtualRate; - - if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate); - if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo); - -#ifndef PREVENT_CLICK_AT_RATE_CROSSOVER - if (rate <= 1.0f) - { - if (output != pTDStretch) - { - FIFOSamplePipe *tempoOut; - - assert(output == pRateTransposer); - // move samples in the current output buffer to the output of pTDStretch - tempoOut = pTDStretch->getOutput(); - tempoOut->moveSamples(*output); - // move samples in pitch transposer's store buffer to tempo changer's input - pTDStretch->moveSamples(*pRateTransposer->getStore()); - - output = pTDStretch; - } - } - else -#endif - { - if (output != pRateTransposer) - { - FIFOSamplePipe *transOut; - - assert(output == pTDStretch); - // move samples in the current output buffer to the output of pRateTransposer - transOut = pRateTransposer->getOutput(); - transOut->moveSamples(*output); - // move samples in tempo changer's input to pitch transposer's input - pRateTransposer->moveSamples(*pTDStretch->getInput()); - - output = pRateTransposer; - } - } -} - - -// Sets sample rate. -void SoundTouch::setSampleRate(uint srate) -{ - bSrateSet = TRUE; - // set sample rate, leave other tempo changer parameters as they are. - pTDStretch->setParameters((int)srate); -} - - -// Adds 'numSamples' pcs of samples from the 'samples' memory position into -// the input of the object. -void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples) -{ - if (bSrateSet == FALSE) - { - throw std::runtime_error("SoundTouch : Sample rate not defined"); - } - else if (channels == 0) - { - throw std::runtime_error("SoundTouch : Number of channels not defined"); - } - - // Transpose the rate of the new samples if necessary - /* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value... - if (rate == 1.0f) - { - // The rate value is same as the original, simply evaluate the tempo changer. - assert(output == pTDStretch); - if (pRateTransposer->isEmpty() == 0) - { - // yet flush the last samples in the pitch transposer buffer - // (may happen if 'rate' changes from a non-zero value to zero) - pTDStretch->moveSamples(*pRateTransposer); - } - pTDStretch->putSamples(samples, nSamples); - } - */ -#ifndef PREVENT_CLICK_AT_RATE_CROSSOVER - else if (rate <= 1.0f) - { - // transpose the rate down, output the transposed sound to tempo changer buffer - assert(output == pTDStretch); - pRateTransposer->putSamples(samples, nSamples); - pTDStretch->moveSamples(*pRateTransposer); - } - else -#endif - { - // evaluate the tempo changer, then transpose the rate up, - assert(output == pRateTransposer); - pTDStretch->putSamples(samples, nSamples); - pRateTransposer->moveSamples(*pTDStretch); - } -} - - -// Flushes the last samples from the processing pipeline to the output. -// Clears also the internal processing buffers. -// -// Note: This function is meant for extracting the last samples of a sound -// 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. -void SoundTouch::flush() -{ - int i; - uint nOut; - SAMPLETYPE buff[128]; - - nOut = numSamples(); - - memset(buff, 0, 128 * sizeof(SAMPLETYPE)); - // "Push" the last active samples out from the processing pipeline by - // feeding blank samples into the processing pipeline until new, - // processed samples appear in the output (not however, more than - // 8ksamples in any case) - for (i = 0; i < 128; i ++) - { - putSamples(buff, 64); - if (numSamples() != nOut) break; // new samples have appeared in the output! - } - - // Clear working buffers - pRateTransposer->clear(); - pTDStretch->clearInput(); - // yet leave the 'tempoChanger' output intouched as that's where the - // flushed samples are! -} - - -// Changes a setting controlling the processing system behaviour. See the -// 'SETTING_...' defines for available setting ID's. -BOOL SoundTouch::setSetting(int settingId, int value) -{ - int sampleRate, sequenceMs, seekWindowMs, overlapMs; - - // read current tdstretch routine parameters - pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs); - - switch (settingId) - { - case SETTING_USE_AA_FILTER : - // enables / disabless anti-alias filter - pRateTransposer->enableAAFilter((value != 0) ? TRUE : FALSE); - return TRUE; - - case SETTING_AA_FILTER_LENGTH : - // sets anti-alias filter length - pRateTransposer->getAAFilter()->setLength(value); - return TRUE; - - case SETTING_USE_QUICKSEEK : - // enables / disables tempo routine quick seeking algorithm - pTDStretch->enableQuickSeek((value != 0) ? TRUE : FALSE); - return TRUE; - - case SETTING_SEQUENCE_MS: - // change time-stretch sequence duration parameter - pTDStretch->setParameters(sampleRate, value, seekWindowMs, overlapMs); - return TRUE; - - case SETTING_SEEKWINDOW_MS: - // change time-stretch seek window length parameter - pTDStretch->setParameters(sampleRate, sequenceMs, value, overlapMs); - return TRUE; - - case SETTING_OVERLAP_MS: - // change time-stretch overlap length parameter - pTDStretch->setParameters(sampleRate, sequenceMs, seekWindowMs, value); - return TRUE; - - default : - return FALSE; - } -} - - -// Reads a setting controlling the processing system behaviour. See the -// 'SETTING_...' defines for available setting ID's. -// -// Returns the setting value. -int SoundTouch::getSetting(int settingId) const -{ - int temp; - - switch (settingId) - { - case SETTING_USE_AA_FILTER : - return (uint)pRateTransposer->isAAFilterEnabled(); - - case SETTING_AA_FILTER_LENGTH : - return pRateTransposer->getAAFilter()->getLength(); - - case SETTING_USE_QUICKSEEK : - return (uint) pTDStretch->isQuickSeekEnabled(); - - case SETTING_SEQUENCE_MS: - pTDStretch->getParameters(NULL, &temp, NULL, NULL); - return temp; - - case SETTING_SEEKWINDOW_MS: - pTDStretch->getParameters(NULL, NULL, &temp, NULL); - return temp; - - case SETTING_OVERLAP_MS: - pTDStretch->getParameters(NULL, NULL, NULL, &temp); - return temp; - - default : - return 0; - } -} - - -// Clears all the samples in the object's output and internal processing -// buffers. -void SoundTouch::clear() -{ - pRateTransposer->clear(); - pTDStretch->clear(); -} - - - -/// Returns number of samples currently unprocessed. -uint SoundTouch::numUnprocessedSamples() const -{ - FIFOSamplePipe * psp; - if (pTDStretch) - { - psp = pTDStretch->getInput(); - if (psp) - { - return psp->numSamples(); - } - } - return 0; -} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/SoundTouch.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/SoundTouch.h --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/SoundTouch.h 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/SoundTouch.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,252 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -/// -/// SoundTouch - main class for tempo/pitch/rate adjusting routines. -/// -/// Notes: -/// - Initialize the SoundTouch object instance by setting up the sound stream -/// parameters with functions 'setSampleRate' and 'setChannels', then set -/// desired tempo/pitch/rate settings with the corresponding functions. -/// -/// - The SoundTouch class behaves like a first-in-first-out pipeline: The -/// samples that are to be processed are fed into one of the pipe by calling -/// function 'putSamples', while the ready processed samples can be read -/// from the other end of the pipeline with function 'receiveSamples'. -/// -/// - The SoundTouch processing classes require certain sized 'batches' of -/// samples in order to process the sound. For this reason the classes buffer -/// incoming samples until there are enough of samples available for -/// processing, then they carry out the processing step and consequently -/// make the processed samples available for outputting. -/// -/// - For the above reason, the processing routines introduce a certain -/// 'latency' between the input and output, so that the samples input to -/// SoundTouch may not be immediately available in the output, and neither -/// the amount of outputtable samples may not immediately be in direct -/// relationship with the amount of previously input samples. -/// -/// - The tempo/pitch/rate control parameters can be altered during processing. -/// Please notice though that they aren't currently protected by semaphores, -/// so in multi-thread application external semaphore protection may be -/// required. -/// -/// - This class utilizes classes 'TDStretch' for tempo change (without modifying -/// pitch) and 'RateTransposer' for changing the playback rate (that is, both -/// tempo and pitch in the same ratio) of the sound. The third available control -/// 'pitch' (change pitch but maintain tempo) is produced by a combination of -/// combining the two other controls. -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-12-28 22:10:14 +0200 (Mon, 28 Dec 2009) $ -// File revision : $Revision: 4 $ -// -// $Id: SoundTouch.h 78 2009-12-28 20:10:14Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 SoundTouch_H -#define SoundTouch_H - -#include "FIFOSamplePipe.h" -#include "STTypes.h" - -namespace soundtouch -{ - -/// Soundtouch library version string -#define SOUNDTOUCH_VERSION "1.5.0" - -/// SoundTouch library version id -#define SOUNDTOUCH_VERSION_ID (10500) - -// -// Available setting IDs for the 'setSetting' & 'get_setting' functions: - -/// Enable/disable anti-alias filter in pitch transposer (0 = disable) -#define SETTING_USE_AA_FILTER 0 - -/// Pitch transposer anti-alias filter length (8 .. 128 taps, default = 32) -#define SETTING_AA_FILTER_LENGTH 1 - -/// Enable/disable quick seeking algorithm in tempo changer routine -/// (enabling quick seeking lowers CPU utilization but causes a minor sound -/// quality compromising) -#define SETTING_USE_QUICKSEEK 2 - -/// Time-stretch algorithm single processing sequence length in milliseconds. This determines -/// to how long sequences the original sound is chopped in the time-stretch algorithm. -/// See "STTypes.h" or README for more information. -#define SETTING_SEQUENCE_MS 3 - -/// Time-stretch algorithm seeking window length in milliseconds for algorithm that finds the -/// best possible overlapping location. This determines from how wide window the algorithm -/// may look for an optimal joining location when mixing the sound sequences back together. -/// See "STTypes.h" or README for more information. -#define SETTING_SEEKWINDOW_MS 4 - -/// Time-stretch algorithm overlap length in milliseconds. When the chopped sound sequences -/// are mixed back together, to form a continuous sound stream, this parameter defines over -/// how long period the two consecutive sequences are let to overlap each other. -/// See "STTypes.h" or README for more information. -#define SETTING_OVERLAP_MS 5 - - -class SoundTouch : public FIFOProcessor -{ -private: - /// Rate transposer class instance - class RateTransposer *pRateTransposer; - - /// Time-stretch class instance - class TDStretch *pTDStretch; - - /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters. - float virtualRate; - - /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters. - float virtualTempo; - - /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters. - float virtualPitch; - - /// Flag: Has sample rate been set? - BOOL bSrateSet; - - /// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and - /// 'virtualPitch' parameters. - void calcEffectiveRateAndTempo(); - -protected : - /// Number of channels - uint channels; - - /// Effective 'rate' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch' - float rate; - - /// Effective 'tempo' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch' - float tempo; - -public: - SoundTouch(); - virtual ~SoundTouch(); - - /// Get SoundTouch library version string - static const char *getVersionString(); - - /// Get SoundTouch library version Id - static uint getVersionId(); - - /// Sets new rate control value. Normal rate = 1.0, smaller values - /// represent slower rate, larger faster rates. - void setRate(float newRate); - - /// Sets new tempo control value. Normal tempo = 1.0, smaller values - /// represent slower tempo, larger faster tempo. - void setTempo(float newTempo); - - /// Sets new rate control value as a difference in percents compared - /// to the original rate (-50 .. +100 %) - void setRateChange(float newRate); - - /// Sets new tempo control value as a difference in percents compared - /// to the original tempo (-50 .. +100 %) - void setTempoChange(float newTempo); - - /// Sets new pitch control value. Original pitch = 1.0, smaller values - /// represent lower pitches, larger values higher pitch. - void setPitch(float newPitch); - - /// Sets pitch change in octaves compared to the original pitch - /// (-1.00 .. +1.00) - void setPitchOctaves(float newPitch); - - /// Sets pitch change in semi-tones compared to the original pitch - /// (-12 .. +12) - void setPitchSemiTones(int newPitch); - void setPitchSemiTones(float newPitch); - - /// Sets the number of channels, 1 = mono, 2 = stereo - void setChannels(uint numChannels); - - /// Sets sample rate. - void setSampleRate(uint srate); - - /// Flushes the last samples from the processing pipeline to the output. - /// Clears also the internal processing buffers. - // - /// Note: This function is meant for extracting the last samples of a sound - /// 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. - void flush(); - - /// 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. - virtual void putSamples( - const SAMPLETYPE *samples, ///< Pointer to sample buffer. - uint numSamples ///< Number of samples in buffer. Notice - ///< that in case of stereo-sound a single sample - ///< contains data for both channels. - ); - - /// Clears all the samples in the object's output and internal processing - /// buffers. - virtual void clear(); - - /// Changes a setting controlling the processing system behaviour. See the - /// 'SETTING_...' defines for available setting ID's. - /// - /// \return 'TRUE' if the setting was succesfully changed - BOOL setSetting(int settingId, ///< Setting ID number. see SETTING_... defines. - int value ///< New setting value. - ); - - /// Reads a setting controlling the processing system behaviour. See the - /// 'SETTING_...' defines for available setting ID's. - /// - /// \return the setting value. - int getSetting(int settingId ///< Setting ID number, see SETTING_... defines. - ) const; - - /// Returns number of samples currently unprocessed. - virtual uint numUnprocessedSamples() const; - - - /// Other handy functions that are implemented in the ancestor classes (see - /// classes 'FIFOProcessor' and 'FIFOSamplePipe') - /// - /// - receiveSamples() : Use this function to receive 'ready' processed samples from SoundTouch. - /// - numSamples() : Get number of 'ready' samples that can be received with - /// function 'receiveSamples()' - /// - isEmpty() : Returns nonzero if there aren't any 'ready' samples. - /// - clear() : Clears all samples from ready/processing buffers. -}; - -} -#endif diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/TDStretch.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/TDStretch.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/TDStretch.cpp 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/TDStretch.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,1045 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo -/// while maintaining the original pitch by using a time domain WSOLA-like -/// method with several performance-increasing tweaks. -/// -/// Note : MMX optimized functions reside in a separate, platform-specific -/// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp' -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-12-28 21:27:04 +0200 (Mon, 28 Dec 2009) $ -// File revision : $Revision: 1.12 $ -// -// $Id: TDStretch.cpp 77 2009-12-28 19:27:04Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include - -#include "STTypes.h" -#include "cpu_detect.h" -#include "TDStretch.h" - -#include - -using namespace soundtouch; - -#define max(x, y) (((x) > (y)) ? (x) : (y)) - - -/***************************************************************************** - * - * Constant definitions - * - *****************************************************************************/ - -// Table for the hierarchical mixing position seeking algorithm -static 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' - * - *****************************************************************************/ - - -TDStretch::TDStretch() : FIFOProcessor(&outputBuffer) -{ - bQuickSeek = FALSE; - channels = 2; - - pMidBuffer = NULL; - pRefMidBufferUnaligned = NULL; - overlapLength = 0; - - bAutoSeqSetting = TRUE; - bAutoSeekSetting = TRUE; - -// outDebt = 0; - skipFract = 0; - - tempo = 1.0f; - setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS); - setTempo(1.0f); - - clear(); -} - - - -TDStretch::~TDStretch() -{ - delete[] pMidBuffer; - delete[] pRefMidBufferUnaligned; -} - - - -// Sets routine control parameters. These control are certain time constants -// defining how the sound is stretched to the desired duration. -// -// 'sampleRate' = sample rate of the sound -// 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms) -// 'seekwindowMS' = seeking window length for scanning the best overlapping -// position (default = 28 ms) -// 'overlapMS' = overlapping length (default = 12 ms) - -void TDStretch::setParameters(int aSampleRate, int aSequenceMS, - int aSeekWindowMS, int aOverlapMS) -{ - // accept only positive parameter values - if zero or negative, use old values instead - if (aSampleRate > 0) this->sampleRate = aSampleRate; - if (aOverlapMS > 0) this->overlapMs = aOverlapMS; - - if (aSequenceMS > 0) - { - this->sequenceMs = aSequenceMS; - bAutoSeqSetting = FALSE; - } - else if (aSequenceMS == 0) - { - // if zero, use automatic setting - bAutoSeqSetting = TRUE; - } - - if (aSeekWindowMS > 0) - { - this->seekWindowMs = aSeekWindowMS; - bAutoSeekSetting = FALSE; - } - else if (aSeekWindowMS == 0) - { - // if zero, use automatic setting - bAutoSeekSetting = TRUE; - } - - calcSeqParameters(); - - calculateOverlapLength(overlapMs); - - // set tempo to recalculate 'sampleReq' - setTempo(tempo); - -} - - - -/// Get routine control parameters, see setParameters() function. -/// Any of the parameters to this function can be NULL, in such case corresponding parameter -/// value isn't returned. -void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const -{ - if (pSampleRate) - { - *pSampleRate = sampleRate; - } - - if (pSequenceMs) - { - *pSequenceMs = (bAutoSeqSetting) ? (USE_AUTO_SEQUENCE_LEN) : sequenceMs; - } - - if (pSeekWindowMs) - { - *pSeekWindowMs = (bAutoSeekSetting) ? (USE_AUTO_SEEKWINDOW_LEN) : seekWindowMs; - } - - if (pOverlapMs) - { - *pOverlapMs = overlapMs; - } -} - - -// Overlaps samples in 'midBuffer' with the samples in 'pInput' -void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const -{ - int i, itemp; - - for (i = 0; i < overlapLength ; i ++) - { - itemp = overlapLength - i; - pOutput[i] = (pInput[i] * i + pMidBuffer[i] * itemp ) / overlapLength; // >> overlapDividerBits; - } -} - - - -void TDStretch::clearMidBuffer() -{ - memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength); -} - - -void TDStretch::clearInput() -{ - inputBuffer.clear(); - clearMidBuffer(); -} - - -// Clears the sample buffers -void TDStretch::clear() -{ - outputBuffer.clear(); - clearInput(); -} - - - -// Enables/disables the quick position seeking algorithm. Zero to disable, nonzero -// to enable -void TDStretch::enableQuickSeek(BOOL enable) -{ - bQuickSeek = enable; -} - - -// Returns nonzero if the quick seeking algorithm is enabled. -BOOL TDStretch::isQuickSeekEnabled() const -{ - return bQuickSeek; -} - - -// Seeks for the optimal overlap-mixing position. -int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos) -{ - if (channels == 2) - { - // stereo sound - if (bQuickSeek) - { - return seekBestOverlapPositionStereoQuick(refPos); - } - else - { - return seekBestOverlapPositionStereo(refPos); - } - } - else - { - // mono sound - if (bQuickSeek) - { - return seekBestOverlapPositionMonoQuick(refPos); - } - else - { - return seekBestOverlapPositionMono(refPos); - } - } -} - - - - -// Overlaps samples in 'midBuffer' with the samples in 'pInputBuffer' at position -// of 'ovlPos'. -inline void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, uint ovlPos) const -{ - if (channels == 2) - { - // stereo sound - overlapStereo(pOutput, pInput + 2 * ovlPos); - } else { - // mono sound. - overlapMono(pOutput, pInput + ovlPos); - } -} - - - - -// Seeks for the optimal overlap-mixing position. The 'stereo' version of the -// routine -// -// The best position is determined as the position where the two overlapped -// sample sequences are 'most alike', in terms of the highest cross-correlation -// value over the overlapping period -int TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos) -{ - int bestOffs; - double bestCorr, corr; - int i; - - // Slopes the amplitudes of the 'midBuffer' samples - precalcCorrReferenceStereo(); - - bestCorr = FLT_MIN; - bestOffs = 0; - - // Scans for the best correlation value by testing each possible position - // over the permitted range. - for (i = 0; i < seekLength; i ++) - { - // Calculates correlation value for the mixing position corresponding - // to 'i' - corr = (double)calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer); - // heuristic rule to slightly favour values close to mid of the range - double tmp = (double)(2 * i - seekLength) / (double)seekLength; - corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); - - // Checks for the highest correlation value - if (corr > bestCorr) - { - bestCorr = corr; - bestOffs = i; - } - } - // clear cross correlation routine state if necessary (is so e.g. in MMX routines). - clearCrossCorrState(); - - return bestOffs; -} - - -// Seeks for the optimal overlap-mixing position. The 'stereo' version of the -// routine -// -// The best position is determined as the position where the two overlapped -// sample sequences are 'most alike', in terms of the highest cross-correlation -// value over the overlapping period -int TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos) -{ - int j; - int bestOffs; - double bestCorr, corr; - int scanCount, corrOffset, tempOffset; - - // Slopes the amplitude of the 'midBuffer' samples - precalcCorrReferenceStereo(); - - bestCorr = FLT_MIN; - bestOffs = _scanOffsets[0][0]; - corrOffset = 0; - tempOffset = 0; - - // Scans for the best correlation value using four-pass hierarchical search. - // - // The look-up table 'scans' has hierarchical position adjusting steps. - // In first pass the routine searhes for the highest correlation with - // relatively coarse steps, then rescans the neighbourhood of the highest - // correlation with better resolution and so on. - for (scanCount = 0;scanCount < 4; scanCount ++) - { - j = 0; - while (_scanOffsets[scanCount][j]) - { - tempOffset = corrOffset + _scanOffsets[scanCount][j]; - if (tempOffset >= seekLength) break; - - // Calculates correlation value for the mixing position corresponding - // to 'tempOffset' - corr = (double)calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer); - // heuristic rule to slightly favour values close to mid of the range - double tmp = (double)(2 * tempOffset - seekLength) / seekLength; - corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); - - // Checks for the highest correlation value - if (corr > bestCorr) - { - bestCorr = corr; - bestOffs = tempOffset; - } - j ++; - } - corrOffset = bestOffs; - } - // clear cross correlation routine state if necessary (is so e.g. in MMX routines). - clearCrossCorrState(); - - return bestOffs; -} - - - -// Seeks for the optimal overlap-mixing position. The 'mono' version of the -// routine -// -// The best position is determined as the position where the two overlapped -// sample sequences are 'most alike', in terms of the highest cross-correlation -// value over the overlapping period -int TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos) -{ - int bestOffs; - double bestCorr, corr; - int tempOffset; - const SAMPLETYPE *compare; - - // Slopes the amplitude of the 'midBuffer' samples - precalcCorrReferenceMono(); - - bestCorr = FLT_MIN; - bestOffs = 0; - - // Scans for the best correlation value by testing each possible position - // over the permitted range. - for (tempOffset = 0; tempOffset < seekLength; tempOffset ++) - { - compare = refPos + tempOffset; - - // Calculates correlation value for the mixing position corresponding - // to 'tempOffset' - corr = (double)calcCrossCorrMono(pRefMidBuffer, compare); - // heuristic rule to slightly favour values close to mid of the range - double tmp = (double)(2 * tempOffset - seekLength) / seekLength; - corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); - - // Checks for the highest correlation value - if (corr > bestCorr) - { - bestCorr = corr; - bestOffs = tempOffset; - } - } - // clear cross correlation routine state if necessary (is so e.g. in MMX routines). - clearCrossCorrState(); - - return bestOffs; -} - - -// Seeks for the optimal overlap-mixing position. The 'mono' version of the -// routine -// -// The best position is determined as the position where the two overlapped -// sample sequences are 'most alike', in terms of the highest cross-correlation -// value over the overlapping period -int TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos) -{ - int j; - int bestOffs; - double bestCorr, corr; - int scanCount, corrOffset, tempOffset; - - // Slopes the amplitude of the 'midBuffer' samples - precalcCorrReferenceMono(); - - bestCorr = FLT_MIN; - bestOffs = _scanOffsets[0][0]; - corrOffset = 0; - tempOffset = 0; - - // Scans for the best correlation value using four-pass hierarchical search. - // - // The look-up table 'scans' has hierarchical position adjusting steps. - // In first pass the routine searhes for the highest correlation with - // relatively coarse steps, then rescans the neighbourhood of the highest - // correlation with better resolution and so on. - for (scanCount = 0;scanCount < 4; scanCount ++) - { - j = 0; - while (_scanOffsets[scanCount][j]) - { - tempOffset = corrOffset + _scanOffsets[scanCount][j]; - if (tempOffset >= seekLength) break; - - // Calculates correlation value for the mixing position corresponding - // to 'tempOffset' - corr = (double)calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer); - // heuristic rule to slightly favour values close to mid of the range - double tmp = (double)(2 * tempOffset - seekLength) / seekLength; - corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); - - // Checks for the highest correlation value - if (corr > bestCorr) - { - bestCorr = corr; - bestOffs = tempOffset; - } - j ++; - } - corrOffset = bestOffs; - } - // clear cross correlation routine state if necessary (is so e.g. in MMX routines). - clearCrossCorrState(); - - return bestOffs; -} - - -/// clear cross correlation routine state if necessary -void TDStretch::clearCrossCorrState() -{ - // default implementation is empty. -} - - -/// Calculates processing sequence length according to tempo setting -void TDStretch::calcSeqParameters() -{ - // Adjust tempo param according to tempo, so that variating processing sequence length is used - // at varius tempo settings, between the given low...top limits - #define AUTOSEQ_TEMPO_LOW 0.5 // auto setting low tempo range (-50%) - #define AUTOSEQ_TEMPO_TOP 2.0 // auto setting top tempo range (+100%) - - // sequence-ms setting values at above low & top tempo - #define AUTOSEQ_AT_MIN 125.0 - #define AUTOSEQ_AT_MAX 50.0 - #define AUTOSEQ_K ((AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW)) - #define AUTOSEQ_C (AUTOSEQ_AT_MIN - (AUTOSEQ_K) * (AUTOSEQ_TEMPO_LOW)) - - // seek-window-ms setting values at above low & top tempo - #define AUTOSEEK_AT_MIN 25.0 - #define AUTOSEEK_AT_MAX 15.0 - #define AUTOSEEK_K ((AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW)) - #define AUTOSEEK_C (AUTOSEEK_AT_MIN - (AUTOSEEK_K) * (AUTOSEQ_TEMPO_LOW)) - - #define CHECK_LIMITS(x, mi, ma) (((x) < (mi)) ? (mi) : (((x) > (ma)) ? (ma) : (x))) - - double seq, seek; - - if (bAutoSeqSetting) - { - seq = AUTOSEQ_C + AUTOSEQ_K * tempo; - seq = CHECK_LIMITS(seq, AUTOSEQ_AT_MAX, AUTOSEQ_AT_MIN); - sequenceMs = (int)(seq + 0.5); - } - - if (bAutoSeekSetting) - { - seek = AUTOSEEK_C + AUTOSEEK_K * tempo; - seek = CHECK_LIMITS(seek, AUTOSEEK_AT_MAX, AUTOSEEK_AT_MIN); - seekWindowMs = (int)(seek + 0.5); - } - - // Update seek window lengths - seekWindowLength = (sampleRate * sequenceMs) / 1000; - if (seekWindowLength < 2 * overlapLength) - { - seekWindowLength = 2 * overlapLength; - } - seekLength = (sampleRate * seekWindowMs) / 1000; -} - - - -// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower -// tempo, larger faster tempo. -void TDStretch::setTempo(float newTempo) -{ - int intskip; - - tempo = newTempo; - - // Calculate new sequence duration - calcSeqParameters(); - - // Calculate ideal skip length (according to tempo value) - nominalSkip = tempo * (seekWindowLength - overlapLength); - intskip = (int)(nominalSkip + 0.5f); - - // Calculate how many samples are needed in the 'inputBuffer' to - // process another batch of samples - //sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength / 2; - sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength; -} - - - -// Sets the number of channels, 1 = mono, 2 = stereo -void TDStretch::setChannels(int numChannels) -{ - assert(numChannels > 0); - if (channels == numChannels) return; - assert(numChannels == 1 || numChannels == 2); - - channels = numChannels; - inputBuffer.setChannels(channels); - outputBuffer.setChannels(channels); -} - - -// nominal tempo, no need for processing, just pass the samples through -// to outputBuffer -/* -void TDStretch::processNominalTempo() -{ - assert(tempo == 1.0f); - - if (bMidBufferDirty) - { - // If there are samples in pMidBuffer waiting for overlapping, - // do a single sliding overlapping with them in order to prevent a - // clicking distortion in the output sound - if (inputBuffer.numSamples() < overlapLength) - { - // wait until we've got overlapLength input samples - return; - } - // Mix the samples in the beginning of 'inputBuffer' with the - // samples in 'midBuffer' using sliding overlapping - overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0); - outputBuffer.putSamples(overlapLength); - inputBuffer.receiveSamples(overlapLength); - clearMidBuffer(); - // now we've caught the nominal sample flow and may switch to - // bypass mode - } - - // Simply bypass samples from input to output - outputBuffer.moveSamples(inputBuffer); -} -*/ - -#include - -// Processes as many processing frames of the samples 'inputBuffer', store -// the result into 'outputBuffer' -void TDStretch::processSamples() -{ - int ovlSkip, offset; - int temp; - - /* Removed this small optimization - can introduce a click to sound when tempo setting - crosses the nominal value - if (tempo == 1.0f) - { - // tempo not changed from the original, so bypass the processing - processNominalTempo(); - return; - } - */ - - // Process samples as long as there are enough samples in 'inputBuffer' - // to form a processing frame. -// while ((int)inputBuffer.numSamples() >= sampleReq - (outDebt / 4)) - while ((int)inputBuffer.numSamples() >= sampleReq) - { - // If tempo differs from the normal ('SCALE'), scan for the best overlapping - // position - offset = seekBestOverlapPosition(inputBuffer.ptrBegin()); - - // Mix the samples in the 'inputBuffer' at position of 'offset' with the - // samples in 'midBuffer' using sliding overlapping - // ... first partially overlap with the end of the previous sequence - // (that's in 'midBuffer') - overlap(outputBuffer.ptrEnd((uint)overlapLength), inputBuffer.ptrBegin(), (uint)offset); - outputBuffer.putSamples((uint)overlapLength); - - // ... then copy sequence samples from 'inputBuffer' to output: - temp = (seekLength / 2 - offset); - - // compensate cumulated output length diff vs. ideal output -// temp -= outDebt / 4; - - // update ideal vs. true output difference -// outDebt += temp; - - // length of sequence -// temp += (seekWindowLength - 2 * overlapLength); - temp = (seekWindowLength - 2 * overlapLength); - - // crosscheck that we don't have buffer overflow... - if ((int)inputBuffer.numSamples() < (offset + temp + overlapLength * 2)) - { - continue; // just in case, shouldn't really happen - } - - outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), (uint)temp); - - // Copies the end of the current sequence from 'inputBuffer' to - // 'midBuffer' for being mixed with the beginning of the next - // processing sequence and so on - assert((offset + temp + overlapLength * 2) <= (int)inputBuffer.numSamples()); - memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + temp + overlapLength), - channels * sizeof(SAMPLETYPE) * overlapLength); - - // Remove the processed samples from the input buffer. Update - // the difference between integer & nominal skip step to 'skipFract' - // in order to prevent the error from accumulating over time. - skipFract += nominalSkip; // real skip size - ovlSkip = (int)skipFract; // rounded to integer skip - skipFract -= ovlSkip; // maintain the fraction part, i.e. real vs. integer skip - inputBuffer.receiveSamples((uint)ovlSkip); - } -} - - -// Adds 'numsamples' pcs of samples from the 'samples' memory position into -// the input of the object. -void TDStretch::putSamples(const SAMPLETYPE *samples, uint nSamples) -{ - // Add the samples into the input buffer - inputBuffer.putSamples(samples, nSamples); - // Process the samples in input buffer - processSamples(); -} - - - -/// Set new overlap length parameter & reallocate RefMidBuffer if necessary. -void TDStretch::acceptNewOverlapLength(int newOverlapLength) -{ - int prevOvl; - - assert(newOverlapLength >= 0); - prevOvl = overlapLength; - overlapLength = newOverlapLength; - - if (overlapLength > prevOvl) - { - delete[] pMidBuffer; - delete[] pRefMidBufferUnaligned; - - pMidBuffer = new SAMPLETYPE[overlapLength * 2]; - clearMidBuffer(); - - pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)]; - // ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency - pRefMidBuffer = (SAMPLETYPE *)((((ulong)pRefMidBufferUnaligned) + 15) & (ulong)-16); - } -} - - -// 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) -{ - // Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead! - throw std::runtime_error("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!"); - return NULL; -} - - -TDStretch * TDStretch::newInstance() -{ - uint uExtensions; - - uExtensions = detectCPUextensions(); - - // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU - -#ifdef ALLOW_MMX - // MMX routines available only with integer sample types - if (uExtensions & SUPPORT_MMX) - { - return ::new TDStretchMMX; - } - else -#endif // ALLOW_MMX - - -#ifdef ALLOW_SSE - if (uExtensions & SUPPORT_SSE) - { - // SSE support - return ::new TDStretchSSE; - } - else -#endif // ALLOW_SSE - - -#ifdef ALLOW_3DNOW - if (uExtensions & SUPPORT_3DNOW) - { - // 3DNow! support - return ::new TDStretch3DNow; - } - else -#endif // ALLOW_3DNOW - - { - // ISA optimizations not supported, use plain C version - return ::new TDStretch; - } -} - - -////////////////////////////////////////////////////////////////////////////// -// -// Integer arithmetics specific algorithm implementations. -// -////////////////////////////////////////////////////////////////////////////// - -#ifdef INTEGER_SAMPLES - -// Slopes the amplitude of the 'midBuffer' samples so that cross correlation -// is faster to calculate -void TDStretch::precalcCorrReferenceStereo() -{ - int i, cnt2; - int temp, temp2; - - for (i=0 ; i < (int)overlapLength ;i ++) - { - temp = i * (overlapLength - i); - cnt2 = i * 2; - - temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider; - pRefMidBuffer[cnt2] = (short)(temp2); - temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider; - pRefMidBuffer[cnt2 + 1] = (short)(temp2); - } -} - - -// Slopes the amplitude of the 'midBuffer' samples so that cross correlation -// is faster to calculate -void TDStretch::precalcCorrReferenceMono() -{ - int i; - long temp; - long temp2; - - for (i=0 ; i < (int)overlapLength ;i ++) - { - temp = i * (overlapLength - i); - temp2 = (pMidBuffer[i] * temp) / slopingDivider; - pRefMidBuffer[i] = (short)temp2; - } -} - - -// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo' -// version of the routine. -void TDStretch::overlapStereo(short *poutput, const short *input) const -{ - int i; - short temp; - int cnt2; - - for (i = 0; i < overlapLength ; i ++) - { - temp = (short)(overlapLength - i); - cnt2 = 2 * i; - poutput[cnt2] = (input[cnt2] * i + pMidBuffer[cnt2] * temp ) / overlapLength; - poutput[cnt2 + 1] = (input[cnt2 + 1] * i + pMidBuffer[cnt2 + 1] * temp ) / overlapLength; - } -} - -// Calculates the x having the closest 2^x value for the given value -static int _getClosest2Power(double value) -{ - return (int)(log(value) / log(2.0) + 0.5); -} - - -/// Calculates overlap period length in samples. -/// Integer version rounds overlap length to closest power of 2 -/// for a divide scaling operation. -void TDStretch::calculateOverlapLength(int aoverlapMs) -{ - int newOvl; - - assert(aoverlapMs >= 0); - - // calculate overlap length so that it's power of 2 - thus it's easy to do - // integer division by right-shifting. Term "-1" at end is to account for - // the extra most significatnt bit left unused in result by signed multiplication - overlapDividerBits = _getClosest2Power((sampleRate * aoverlapMs) / 1000.0) - 1; - if (overlapDividerBits > 9) overlapDividerBits = 9; - if (overlapDividerBits < 3) overlapDividerBits = 3; - newOvl = (int)pow(2.0, (int)overlapDividerBits + 1); // +1 => account for -1 above - - acceptNewOverlapLength(newOvl); - - // calculate sloping divider so that crosscorrelation operation won't - // overflow 32-bit register. Max. sum of the crosscorrelation sum without - // divider would be 2^30*(N^3-N)/3, where N = overlap length - slopingDivider = (newOvl * newOvl - 1) / 3; -} - - -long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const -{ - long corr; - long norm; - int i; - - corr = norm = 0; - for (i = 1; i < overlapLength; i ++) - { - corr += (mixingPos[i] * compare[i]) >> overlapDividerBits; - norm += (mixingPos[i] * mixingPos[i]) >> overlapDividerBits; - } - - // Normalize result by dividing by sqrt(norm) - this step is easiest - // done using floating point operation - if (norm == 0) norm = 1; // to avoid div by zero - return (long)((double)corr * SHRT_MAX / sqrt((double)norm)); -} - - -long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const -{ - long corr; - long norm; - int i; - - corr = norm = 0; - for (i = 2; i < 2 * overlapLength; i += 2) - { - corr += (mixingPos[i] * compare[i] + - mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits; - norm += (mixingPos[i] * mixingPos[i] + mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBits; - } - - // Normalize result by dividing by sqrt(norm) - this step is easiest - // done using floating point operation - if (norm == 0) norm = 1; // to avoid div by zero - return (long)((double)corr * SHRT_MAX / sqrt((double)norm)); -} - -#endif // INTEGER_SAMPLES - -////////////////////////////////////////////////////////////////////////////// -// -// Floating point arithmetics specific algorithm implementations. -// - -#ifdef FLOAT_SAMPLES - - -// Slopes the amplitude of the 'midBuffer' samples so that cross correlation -// is faster to calculate -void TDStretch::precalcCorrReferenceStereo() -{ - int i, cnt2; - float temp; - - for (i=0 ; i < (int)overlapLength ;i ++) - { - temp = (float)i * (float)(overlapLength - i); - cnt2 = i * 2; - pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp); - pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp); - } -} - - -// Slopes the amplitude of the 'midBuffer' samples so that cross correlation -// is faster to calculate -void TDStretch::precalcCorrReferenceMono() -{ - int i; - float temp; - - for (i=0 ; i < (int)overlapLength ;i ++) - { - temp = (float)i * (float)(overlapLength - i); - pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp); - } -} - - -// Overlaps samples in 'midBuffer' with the samples in 'pInput' -void TDStretch::overlapStereo(float *pOutput, const float *pInput) const -{ - int i; - int cnt2; - float fTemp; - float fScale; - float fi; - - fScale = 1.0f / (float)overlapLength; - - for (i = 0; i < (int)overlapLength ; i ++) - { - fTemp = (float)(overlapLength - i) * fScale; - fi = (float)i * fScale; - cnt2 = 2 * i; - pOutput[cnt2 + 0] = pInput[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp; - pOutput[cnt2 + 1] = pInput[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp; - } -} - - -/// Calculates overlapInMsec period length in samples. -void TDStretch::calculateOverlapLength(int overlapInMsec) -{ - int newOvl; - - assert(overlapInMsec >= 0); - newOvl = (sampleRate * overlapInMsec) / 1000; - if (newOvl < 16) newOvl = 16; - - // must be divisible by 8 - newOvl -= newOvl % 8; - - acceptNewOverlapLength(newOvl); -} - - - -double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const -{ - double corr; - double norm; - int i; - - corr = norm = 0; - for (i = 1; i < overlapLength; i ++) - { - corr += mixingPos[i] * compare[i]; - norm += mixingPos[i] * mixingPos[i]; - } - - if (norm < 1e-9) norm = 1.0; // to avoid div by zero - return corr / sqrt(norm); -} - - -double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const -{ - double corr; - double norm; - int i; - - corr = norm = 0; - for (i = 2; i < 2 * overlapLength; i += 2) - { - corr += mixingPos[i] * compare[i] + - mixingPos[i + 1] * compare[i + 1]; - norm += mixingPos[i] * mixingPos[i] + - mixingPos[i + 1] * mixingPos[i + 1]; - } - - if (norm < 1e-9) norm = 1.0; // to avoid div by zero - return corr / sqrt(norm); -} - -#endif // FLOAT_SAMPLES diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/TDStretch.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/TDStretch.h --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/TDStretch.h 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/TDStretch.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,275 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo -/// while maintaining the original pitch by using a time domain WSOLA-like method -/// with several performance-increasing tweaks. -/// -/// Note : MMX/SSE optimized functions reside in separate, platform-specific files -/// 'mmx_optimized.cpp' and 'sse_optimized.cpp' -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-05-17 14:35:13 +0300 (Sun, 17 May 2009) $ -// File revision : $Revision: 4 $ -// -// $Id: TDStretch.h 71 2009-05-17 11:35:13Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 TDStretch_H -#define TDStretch_H - -#include -#include "STTypes.h" -#include "RateTransposer.h" -#include "FIFOSamplePipe.h" - -namespace soundtouch -{ - -/// Default values for sound processing parameters: -/// Notice that the default parameters are tuned for contemporary popular music -/// processing. For speech processing applications these parameters suit better: -/// #define DEFAULT_SEQUENCE_MS 40 -/// #define DEFAULT_SEEKWINDOW_MS 15 -/// #define DEFAULT_OVERLAP_MS 8 -/// - -/// Default length of a single processing sequence, in milliseconds. This determines to how -/// long sequences the original sound is chopped in the time-stretch algorithm. -/// -/// The larger this value is, the lesser sequences are used in processing. In principle -/// a bigger value sounds better when slowing down tempo, but worse when increasing tempo -/// and vice versa. -/// -/// Increasing this value reduces computational burden & vice versa. -//#define DEFAULT_SEQUENCE_MS 40 -#define DEFAULT_SEQUENCE_MS USE_AUTO_SEQUENCE_LEN - -/// Giving this value for the sequence length sets automatic parameter value -/// according to tempo setting (recommended) -#define USE_AUTO_SEQUENCE_LEN 0 - -/// Seeking window default length in milliseconds for algorithm that finds the best possible -/// overlapping location. This determines from how wide window the algorithm may look for an -/// optimal joining location when mixing the sound sequences back together. -/// -/// The bigger this window setting is, the higher the possibility to find a better mixing -/// position will become, but at the same time large values may cause a "drifting" artifact -/// because consequent sequences will be taken at more uneven intervals. -/// -/// If there's a disturbing artifact that sounds as if a constant frequency was drifting -/// around, try reducing this setting. -/// -/// Increasing this value increases computational burden & vice versa. -//#define DEFAULT_SEEKWINDOW_MS 15 -#define DEFAULT_SEEKWINDOW_MS USE_AUTO_SEEKWINDOW_LEN - -/// Giving this value for the seek window length sets automatic parameter value -/// according to tempo setting (recommended) -#define USE_AUTO_SEEKWINDOW_LEN 0 - -/// Overlap length in milliseconds. When the chopped sound sequences are mixed back together, -/// to form a continuous sound stream, this parameter defines over how long period the two -/// consecutive sequences are let to overlap each other. -/// -/// 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. -/// -/// Increasing this value increases computational burden & vice versa. -#define DEFAULT_OVERLAP_MS 8 - - -/// Class that does the time-stretch (tempo change) effect for the processed -/// sound. -class TDStretch : public FIFOProcessor -{ -protected: - int channels; - int sampleReq; - float tempo; - - SAMPLETYPE *pMidBuffer; - SAMPLETYPE *pRefMidBuffer; - SAMPLETYPE *pRefMidBufferUnaligned; - int overlapLength; - int seekLength; - int seekWindowLength; - int overlapDividerBits; - int slopingDivider; - float nominalSkip; - float skipFract; - FIFOSampleBuffer outputBuffer; - FIFOSampleBuffer inputBuffer; - BOOL bQuickSeek; -// int outDebt; -// BOOL bMidBufferDirty; - - int sampleRate; - int sequenceMs; - int seekWindowMs; - int overlapMs; - BOOL bAutoSeqSetting; - BOOL bAutoSeekSetting; - - void acceptNewOverlapLength(int newOverlapLength); - - virtual void clearCrossCorrState(); - void calculateOverlapLength(int overlapMs); - - virtual LONG_SAMPLETYPE calcCrossCorrStereo(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const; - virtual LONG_SAMPLETYPE calcCrossCorrMono(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const; - - virtual int seekBestOverlapPositionStereo(const SAMPLETYPE *refPos); - virtual int seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos); - virtual int seekBestOverlapPositionMono(const SAMPLETYPE *refPos); - virtual int seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos); - int seekBestOverlapPosition(const SAMPLETYPE *refPos); - - virtual void overlapStereo(SAMPLETYPE *output, const SAMPLETYPE *input) const; - virtual void overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const; - - void clearMidBuffer(); - void overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const; - - void precalcCorrReferenceMono(); - void precalcCorrReferenceStereo(); - - void calcSeqParameters(); - - /// Changes the tempo of the given sound samples. - /// Returns amount of samples returned in the "output" buffer. - /// The maximum amount of samples that can be returned at a time is set by - /// the 'set_returnBuffer_size' function. - void processSamples(); - -public: - TDStretch(); - virtual ~TDStretch(); - - /// 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. - static void *operator new(size_t s); - - /// Use this function instead of "new" operator to create a new instance of this class. - /// This function automatically chooses a correct feature set depending on if the CPU - /// supports MMX/SSE/etc extensions. - static TDStretch *newInstance(); - - /// Returns the output buffer object - FIFOSamplePipe *getOutput() { return &outputBuffer; }; - - /// Returns the input buffer object - FIFOSamplePipe *getInput() { return &inputBuffer; }; - - /// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower - /// tempo, larger faster tempo. - void setTempo(float newTempo); - - /// Returns nonzero if there aren't any samples available for outputting. - virtual void clear(); - - /// Clears the input buffer - void clearInput(); - - /// Sets the number of channels, 1 = mono, 2 = stereo - void setChannels(int numChannels); - - /// Enables/disables the quick position seeking algorithm. Zero to disable, - /// nonzero to enable - void enableQuickSeek(BOOL enable); - - /// Returns nonzero if the quick seeking algorithm is enabled. - BOOL isQuickSeekEnabled() const; - - /// Sets routine control parameters. These control are certain time constants - /// defining how the sound is stretched to the desired duration. - // - /// 'sampleRate' = sample rate of the sound - /// 'sequenceMS' = one processing sequence length in milliseconds - /// 'seekwindowMS' = seeking window length for scanning the best overlapping - /// position - /// 'overlapMS' = overlapping length - void setParameters(int sampleRate, ///< Samplerate of sound being processed (Hz) - int sequenceMS = -1, ///< Single processing sequence length (ms) - int seekwindowMS = -1, ///< Offset seeking window length (ms) - int overlapMS = -1 ///< Sequence overlapping length (ms) - ); - - /// Get routine control parameters, see setParameters() function. - /// Any of the parameters to this function can be NULL, in such case corresponding parameter - /// value isn't returned. - void getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const; - - /// Adds 'numsamples' pcs of samples from the 'samples' memory position into - /// the input of the object. - virtual void putSamples( - const SAMPLETYPE *samples, ///< Input sample data - uint numSamples ///< Number of samples in 'samples' so that one sample - ///< contains both channels if stereo - ); -}; - - - -// Implementation-specific class declarations: - -#ifdef ALLOW_MMX - /// Class that implements MMX optimized routines for 16bit integer samples type. - class TDStretchMMX : public TDStretch - { - protected: - long calcCrossCorrStereo(const short *mixingPos, const short *compare) const; - virtual void overlapStereo(short *output, const short *input) const; - virtual void clearCrossCorrState(); - }; -#endif /// ALLOW_MMX - - -#ifdef ALLOW_3DNOW - /// Class that implements 3DNow! optimized routines for floating point samples type. - class TDStretch3DNow : public TDStretch - { - protected: - double calcCrossCorrStereo(const float *mixingPos, const float *compare) const; - }; -#endif /// ALLOW_3DNOW - - -#ifdef ALLOW_SSE - /// Class that implements SSE optimized routines for floating point samples type. - class TDStretchSSE : public TDStretch - { - protected: - double calcCrossCorrStereo(const float *mixingPos, const float *compare) const; - }; - -#endif /// ALLOW_SSE - -} -#endif /// TDStretch_H diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/cpu_detect.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/cpu_detect.h --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/cpu_detect.h 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/cpu_detect.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// A header file for detecting the Intel MMX instructions set extension. -/// -/// Please see 'mmx_win.cpp', 'mmx_cpp.cpp' and 'mmx_non_x86.cpp' for the -/// routine implementations for x86 Windows, x86 gnu version and non-x86 -/// platforms, respectively. -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ -// File revision : $Revision: 4 $ -// -// $Id: cpu_detect.h 11 2008-02-10 16:26:55Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 _CPU_DETECT_H_ -#define _CPU_DETECT_H_ - -#include "STTypes.h" - -#define SUPPORT_MMX 0x0001 -#define SUPPORT_3DNOW 0x0002 -#define SUPPORT_ALTIVEC 0x0004 -#define SUPPORT_SSE 0x0008 -#define SUPPORT_SSE2 0x0010 - -/// Checks which instruction set extensions are supported by the CPU. -/// -/// \return A bitmask of supported extensions, see SUPPORT_... defines. -uint detectCPUextensions(void); - -/// Disables given set of instruction extensions. See SUPPORT_... defines. -void disableExtensions(uint wDisableMask); - -#endif // _CPU_DETECT_H_ diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/cpu_detect_x64_gcc.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/cpu_detect_x64_gcc.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/cpu_detect_x64_gcc.cpp 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/cpu_detect_x64_gcc.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// Generic version of the x64 CPU detect routine. -/// -/// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x64_win.cpp' -/// for the Microsoft compiler version. -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-06-04 22:22:00 -0400 (Sun, 04 June 2009) $ -// File revision : $Revision: 1 $ -// -// $Id: cpu_detect_x64_gcc.cpp 1 2009-06-04 22:22:00Z pegasus $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#include "cpu_detect.h" - -////////////////////////////////////////////////////////////////////////////// -// -// processor instructions extension detection routines -// -////////////////////////////////////////////////////////////////////////////// - -// Flag variable indicating whick ISA extensions are disabled (for debugging) -static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions - - -// Disables given set of instruction extensions. See SUPPORT_... defines. -void disableExtensions(uint dwDisableMask) -{ - _dwDisabledISA = dwDisableMask; -} - - - -/// Checks which instruction set extensions are supported by the CPU. -uint detectCPUextensions(void) -{ - uint res = 0; - - if (_dwDisabledISA == 0xffffffff) return 0; - - // cpu_detect_x86_gcc segfaults on "%edx", "%eax", "%ecx", "%esi" ); - // Since I don't know how to fix that and just need something working for Mixxx... - - // All 64-bit processors support MMX, SSE, and SSE2 - res = SUPPORT_MMX + SUPPORT_SSE + SUPPORT_SSE2; - -#ifdef x86_64 - res += SUPPORT_3DNOW; -#endif - - return res & ~_dwDisabledISA; -} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/cpu_detect_x64_win.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/cpu_detect_x64_win.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/cpu_detect_x64_win.cpp 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/cpu_detect_x64_win.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// Win32 version of the x64 CPU detect routine. -/// -/// This file is to be compiled in Windows platform with Microsoft Visual C++ -/// Compiler. Please see 'cpu_detect_x86_gcc.cpp' for the gcc compiler version -/// for all GNU platforms. -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-05-03 23:20:00 -0400 (Sun, 03 May 2009) $ -// File revision : $Revision: 1 $ -// -// $Id: cpu_detect_x64_win.cpp 1 2009-05-03 23:20:00Z pegasus $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#include "cpu_detect.h" - -#ifndef WIN64 -#error wrong platform - this source code file is exclusively for Win64 platform -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// processor instructions extension detection routines -// -////////////////////////////////////////////////////////////////////////////// - -// Flag variable indicating whick ISA extensions are disabled (for debugging) -static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions - - -// Disables given set of instruction extensions. See SUPPORT_... defines. -void disableExtensions(uint dwDisableMask) -{ - _dwDisabledISA = dwDisableMask; -} - - - -/// Checks which instruction set extensions are supported by the CPU. -uint detectCPUextensions(void) -{ - uint res = 0; - - if (_dwDisabledISA == 0xffffffff) return 0; - - // MSVC doesn't support inline assembly and wants you to use intrinsics instead - // Since I don't know how to do that and just need something working for Mixxx... - - // All 64-bit processors support MMX, SSE, and SSE2 - res = SUPPORT_MMX + SUPPORT_SSE + SUPPORT_SSE2; - -#ifdef AMD64 - res += SUPPORT_3DNOW; -#endif - - return res & ~_dwDisabledISA; -} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/cpu_detect_x86_gcc.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/cpu_detect_x86_gcc.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/cpu_detect_x86_gcc.cpp 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/cpu_detect_x86_gcc.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// Generic version of the x86 CPU extension detection routine. -/// -/// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp' -/// for the Microsoft compiler version. -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-02-25 19:13:51 +0200 (Wed, 25 Feb 2009) $ -// File revision : $Revision: 4 $ -// -// $Id: cpu_detect_x86_gcc.cpp 67 2009-02-25 17:13:51Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include "cpu_detect.h" -#include "STTypes.h" - -using namespace std; - -#include - -////////////////////////////////////////////////////////////////////////////// -// -// processor instructions extension detection routines -// -////////////////////////////////////////////////////////////////////////////// - -// Flag variable indicating whick ISA extensions are disabled (for debugging) -static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions - -// Disables given set of instruction extensions. See SUPPORT_... defines. -void disableExtensions(uint dwDisableMask) -{ - _dwDisabledISA = dwDisableMask; -} - - - -/// Checks which instruction set extensions are supported by the CPU. -uint detectCPUextensions(void) -{ -#if (!(ALLOW_X86_OPTIMIZATIONS) || !(__GNUC__)) - - return 0; // always disable extensions on non-x86 platforms. - -#else - uint res = 0; - - if (_dwDisabledISA == 0xffffffff) return 0; - - asm volatile( - "\n\txor %%esi, %%esi" // clear %%esi = result register - // check if 'cpuid' instructions is available by toggling eflags bit 21 - - "\n\tpushf" // save eflags to stack - "\n\tmovl (%%esp), %%eax" // load eax from stack (with eflags) - "\n\tmovl %%eax, %%ecx" // save the original eflags values to ecx - "\n\txor $0x00200000, %%eax" // toggle bit 21 - "\n\tmovl %%eax, (%%esp)" // store toggled eflags to stack - "\n\tpopf" // load eflags from stack - "\n\tpushf" // save updated eflags to stack - "\n\tmovl (%%esp), %%eax" // load eax from stack - "\n\tpopf" // pop stack to restore esp - "\n\txor %%edx, %%edx" // clear edx for defaulting no mmx - "\n\tcmp %%ecx, %%eax" // compare to original eflags values - "\n\tjz end" // jumps to 'end' if cpuid not present - // cpuid instruction available, test for presence of mmx instructions - - "\n\tmovl $1, %%eax" - "\n\tcpuid" - "\n\ttest $0x00800000, %%edx" - "\n\tjz end" // branch if MMX not available - - "\n\tor $0x01, %%esi" // otherwise add MMX support bit - - "\n\ttest $0x02000000, %%edx" - "\n\tjz test3DNow" // branch if SSE not available - - "\n\tor $0x08, %%esi" // otherwise add SSE support bit - - "\n\ttest3DNow:" - // test for precense of AMD extensions - "\n\tmov $0x80000000, %%eax" - "\n\tcpuid" - "\n\tcmp $0x80000000, %%eax" - "\n\tjbe end" // branch if no AMD extensions detected - - // test for precense of 3DNow! extension - "\n\tmov $0x80000001, %%eax" - "\n\tcpuid" - "\n\ttest $0x80000000, %%edx" - "\n\tjz end" // branch if 3DNow! not detected - - "\n\tor $0x02, %%esi" // otherwise add 3DNow support bit - - "\n\tend:" - - "\n\tmov %%esi, %0" - - : "=r" (res) - : /* no inputs */ - : "%edx", "%eax", "%ecx", "%esi" ); - - return res & ~_dwDisabledISA; -#endif -} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/cpu_detect_x86_win.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/cpu_detect_x86_win.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/cpu_detect_x86_win.cpp 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/cpu_detect_x86_win.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// Win32 version of the x86 CPU detect routine. -/// -/// This file is to be compiled in Windows platform with Microsoft Visual C++ -/// Compiler. Please see 'cpu_detect_x86_gcc.cpp' for the gcc compiler version -/// for all GNU platforms. -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-02-13 18:22:48 +0200 (Fri, 13 Feb 2009) $ -// File revision : $Revision: 4 $ -// -// $Id: cpu_detect_x86_win.cpp 62 2009-02-13 16:22:48Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#include "cpu_detect.h" - -#ifndef WIN32 -#error wrong platform - this source code file is exclusively for Win32 platform -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// processor instructions extension detection routines -// -////////////////////////////////////////////////////////////////////////////// - -// Flag variable indicating whick ISA extensions are disabled (for debugging) -static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions - - -// Disables given set of instruction extensions. See SUPPORT_... defines. -void disableExtensions(uint dwDisableMask) -{ - _dwDisabledISA = dwDisableMask; -} - - - -/// Checks which instruction set extensions are supported by the CPU. -uint detectCPUextensions(void) -{ - uint res = 0; - - if (_dwDisabledISA == 0xffffffff) return 0; - - _asm - { - ; check if 'cpuid' instructions is available by toggling eflags bit 21 - ; - xor esi, esi ; clear esi = result register - - pushfd ; save eflags to stack - mov eax,dword ptr [esp] ; load eax from stack (with eflags) - mov ecx, eax ; save the original eflags values to ecx - xor eax, 0x00200000 ; toggle bit 21 - mov dword ptr [esp],eax ; store toggled eflags to stack - popfd ; load eflags from stack - - pushfd ; save updated eflags to stack - mov eax,dword ptr [esp] ; load eax from stack - popfd ; pop stack to restore stack pointer - - xor edx, edx ; clear edx for defaulting no mmx - cmp eax, ecx ; compare to original eflags values - jz end ; jumps to 'end' if cpuid not present - - ; cpuid instruction available, test for presence of mmx instructions - mov eax, 1 - cpuid - test edx, 0x00800000 - jz end ; branch if MMX not available - - or esi, SUPPORT_MMX ; otherwise add MMX support bit - - test edx, 0x02000000 - jz test3DNow ; branch if SSE not available - - or esi, SUPPORT_SSE ; otherwise add SSE support bit - - test3DNow: - ; test for precense of AMD extensions - mov eax, 0x80000000 - cpuid - cmp eax, 0x80000000 - jbe end ; branch if no AMD extensions detected - - ; test for precense of 3DNow! extension - mov eax, 0x80000001 - cpuid - test edx, 0x80000000 - jz end ; branch if 3DNow! not detected - - or esi, SUPPORT_3DNOW ; otherwise add 3DNow support bit - - end: - - mov res, esi - } - - return res & ~_dwDisabledISA; -} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/mmx_optimized.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/mmx_optimized.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/mmx_optimized.cpp 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/mmx_optimized.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,320 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// MMX optimized routines. All MMX optimized functions have been gathered into -/// this single source code file, regardless to their class or original source -/// code file, in order to ease porting the library to other compiler and -/// processor platforms. -/// -/// The MMX-optimizations are programmed using MMX compiler intrinsics that -/// are supported both by Microsoft Visual C++ and GCC compilers, so this file -/// should compile with both toolsets. -/// -/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++ -/// 6.0 processor pack" update to support compiler intrinsic syntax. The update -/// is available for download at Microsoft Developers Network, see here: -/// http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-10-31 16:53:23 +0200 (Sat, 31 Oct 2009) $ -// File revision : $Revision: 4 $ -// -// $Id: mmx_optimized.cpp 75 2009-10-31 14:53:23Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#include "STTypes.h" - -#ifdef ALLOW_MMX -// MMX routines available only with integer sample type - -#if !(WIN32 || __i386__ || __x86_64__) -#error "wrong platform - this source code file is exclusively for x86 platforms" -#endif - -using namespace soundtouch; - -////////////////////////////////////////////////////////////////////////////// -// -// implementation of MMX optimized functions of class 'TDStretchMMX' -// -////////////////////////////////////////////////////////////////////////////// - -#include "TDStretch.h" -#include -#include -#include - - -// Calculates cross correlation of two buffers -long TDStretchMMX::calcCrossCorrStereo(const short *pV1, const short *pV2) const -{ - const __m64 *pVec1, *pVec2; - __m64 shifter; - __m64 accu, normaccu; - long corr, norm; - int i; - - pVec1 = (__m64*)pV1; - pVec2 = (__m64*)pV2; - - shifter = _m_from_int(overlapDividerBits); - normaccu = accu = _mm_setzero_si64(); - - // Process 4 parallel sets of 2 * stereo samples each during each - // round to improve CPU-level parallellization. - for (i = 0; i < overlapLength / 8; i ++) - { - __m64 temp, temp2; - - // dictionary of instructions: - // _m_pmaddwd : 4*16bit multiply-add, resulting two 32bits = [a0*b0+a1*b1 ; a2*b2+a3*b3] - // _mm_add_pi32 : 2*32bit add - // _m_psrad : 32bit right-shift - - temp = _mm_add_pi32(_mm_madd_pi16(pVec1[0], pVec2[0]), - _mm_madd_pi16(pVec1[1], pVec2[1])); - temp2 = _mm_add_pi32(_mm_madd_pi16(pVec1[0], pVec1[0]), - _mm_madd_pi16(pVec1[1], pVec1[1])); - accu = _mm_add_pi32(accu, _mm_sra_pi32(temp, shifter)); - normaccu = _mm_add_pi32(normaccu, _mm_sra_pi32(temp2, shifter)); - - temp = _mm_add_pi32(_mm_madd_pi16(pVec1[2], pVec2[2]), - _mm_madd_pi16(pVec1[3], pVec2[3])); - temp2 = _mm_add_pi32(_mm_madd_pi16(pVec1[2], pVec1[2]), - _mm_madd_pi16(pVec1[3], pVec1[3])); - accu = _mm_add_pi32(accu, _mm_sra_pi32(temp, shifter)); - normaccu = _mm_add_pi32(normaccu, _mm_sra_pi32(temp2, shifter)); - - pVec1 += 4; - pVec2 += 4; - } - - // copy hi-dword of mm0 to lo-dword of mm1, then sum mmo+mm1 - // and finally store the result into the variable "corr" - - accu = _mm_add_pi32(accu, _mm_srli_si64(accu, 32)); - corr = _m_to_int(accu); - - normaccu = _mm_add_pi32(normaccu, _mm_srli_si64(normaccu, 32)); - norm = _m_to_int(normaccu); - - // Clear MMS state - _m_empty(); - - // Normalize result by dividing by sqrt(norm) - this step is easiest - // done using floating point operation - if (norm == 0) norm = 1; // to avoid div by zero - return (long)((double)corr * USHRT_MAX / sqrt((double)norm)); - // Note: Warning about the missing EMMS instruction is harmless - // as it'll be called elsewhere. -} - - - -void TDStretchMMX::clearCrossCorrState() -{ - // Clear MMS state - _m_empty(); - //_asm EMMS; -} - - - -// MMX-optimized version of the function overlapStereo -void TDStretchMMX::overlapStereo(short *output, const short *input) const -{ - const __m64 *pVinput, *pVMidBuf; - __m64 *pVdest; - __m64 mix1, mix2, adder, shifter; - int i; - - pVinput = (const __m64*)input; - pVMidBuf = (const __m64*)pMidBuffer; - pVdest = (__m64*)output; - - // mix1 = mixer values for 1st stereo sample - // mix1 = mixer values for 2nd stereo sample - // adder = adder for updating mixer values after each round - - mix1 = _mm_set_pi16(0, overlapLength, 0, overlapLength); - adder = _mm_set_pi16(1, -1, 1, -1); - mix2 = _mm_add_pi16(mix1, adder); - adder = _mm_add_pi16(adder, adder); - - // Overlaplength-division by shifter. "+1" is to account for "-1" deduced in - // overlapDividerBits calculation earlier. - shifter = _m_from_int(overlapDividerBits + 1); - - for (i = 0; i < overlapLength / 4; i ++) - { - __m64 temp1, temp2; - - // load & shuffle data so that input & mixbuffer data samples are paired - temp1 = _mm_unpacklo_pi16(pVMidBuf[0], pVinput[0]); // = i0l m0l i0r m0r - temp2 = _mm_unpackhi_pi16(pVMidBuf[0], pVinput[0]); // = i1l m1l i1r m1r - - // temp = (temp .* mix) >> shifter - temp1 = _mm_sra_pi32(_mm_madd_pi16(temp1, mix1), shifter); - temp2 = _mm_sra_pi32(_mm_madd_pi16(temp2, mix2), shifter); - pVdest[0] = _mm_packs_pi32(temp1, temp2); // pack 2*2*32bit => 4*16bit - - // update mix += adder - mix1 = _mm_add_pi16(mix1, adder); - mix2 = _mm_add_pi16(mix2, adder); - - // --- second round begins here --- - - // load & shuffle data so that input & mixbuffer data samples are paired - temp1 = _mm_unpacklo_pi16(pVMidBuf[1], pVinput[1]); // = i2l m2l i2r m2r - temp2 = _mm_unpackhi_pi16(pVMidBuf[1], pVinput[1]); // = i3l m3l i3r m3r - - // temp = (temp .* mix) >> shifter - temp1 = _mm_sra_pi32(_mm_madd_pi16(temp1, mix1), shifter); - temp2 = _mm_sra_pi32(_mm_madd_pi16(temp2, mix2), shifter); - pVdest[1] = _mm_packs_pi32(temp1, temp2); // pack 2*2*32bit => 4*16bit - - // update mix += adder - mix1 = _mm_add_pi16(mix1, adder); - mix2 = _mm_add_pi16(mix2, adder); - - pVinput += 2; - pVMidBuf += 2; - pVdest += 2; - } - - _m_empty(); // clear MMS state -} - - -////////////////////////////////////////////////////////////////////////////// -// -// implementation of MMX optimized functions of class 'FIRFilter' -// -////////////////////////////////////////////////////////////////////////////// - -#include "FIRFilter.h" - - -FIRFilterMMX::FIRFilterMMX() : FIRFilter() -{ - filterCoeffsUnalign = NULL; -} - - -FIRFilterMMX::~FIRFilterMMX() -{ - delete[] filterCoeffsUnalign; -} - - -// (overloaded) Calculates filter coefficients for MMX routine -void FIRFilterMMX::setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor) -{ - uint i; - FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor); - - // Ensure that filter coeffs array is aligned to 16-byte boundary - delete[] filterCoeffsUnalign; - filterCoeffsUnalign = new short[2 * newLength + 8]; - filterCoeffsAlign = (short *)(((ulong)filterCoeffsUnalign + 15) & -16); - - // rearrange the filter coefficients for mmx routines - for (i = 0;i < length; i += 4) - { - filterCoeffsAlign[2 * i + 0] = coeffs[i + 0]; - filterCoeffsAlign[2 * i + 1] = coeffs[i + 2]; - filterCoeffsAlign[2 * i + 2] = coeffs[i + 0]; - filterCoeffsAlign[2 * i + 3] = coeffs[i + 2]; - - filterCoeffsAlign[2 * i + 4] = coeffs[i + 1]; - filterCoeffsAlign[2 * i + 5] = coeffs[i + 3]; - filterCoeffsAlign[2 * i + 6] = coeffs[i + 1]; - filterCoeffsAlign[2 * i + 7] = coeffs[i + 3]; - } -} - - - -// mmx-optimized version of the filter routine for stereo sound -uint FIRFilterMMX::evaluateFilterStereo(short *dest, const short *src, uint numSamples) const -{ - // Create stack copies of the needed member variables for asm routines : - uint i, j; - __m64 *pVdest = (__m64*)dest; - - if (length < 2) return 0; - - for (i = 0; i < (numSamples - length) / 2; i ++) - { - __m64 accu1; - __m64 accu2; - const __m64 *pVsrc = (const __m64*)src; - const __m64 *pVfilter = (const __m64*)filterCoeffsAlign; - - accu1 = accu2 = _mm_setzero_si64(); - for (j = 0; j < lengthDiv8 * 2; j ++) - { - __m64 temp1, temp2; - - temp1 = _mm_unpacklo_pi16(pVsrc[0], pVsrc[1]); // = l2 l0 r2 r0 - temp2 = _mm_unpackhi_pi16(pVsrc[0], pVsrc[1]); // = l3 l1 r3 r1 - - accu1 = _mm_add_pi32(accu1, _mm_madd_pi16(temp1, pVfilter[0])); // += l2*f2+l0*f0 r2*f2+r0*f0 - accu1 = _mm_add_pi32(accu1, _mm_madd_pi16(temp2, pVfilter[1])); // += l3*f3+l1*f1 r3*f3+r1*f1 - - temp1 = _mm_unpacklo_pi16(pVsrc[1], pVsrc[2]); // = l4 l2 r4 r2 - - accu2 = _mm_add_pi32(accu2, _mm_madd_pi16(temp2, pVfilter[0])); // += l3*f2+l1*f0 r3*f2+r1*f0 - accu2 = _mm_add_pi32(accu2, _mm_madd_pi16(temp1, pVfilter[1])); // += l4*f3+l2*f1 r4*f3+r2*f1 - - // accu1 += l2*f2+l0*f0 r2*f2+r0*f0 - // += l3*f3+l1*f1 r3*f3+r1*f1 - - // accu2 += l3*f2+l1*f0 r3*f2+r1*f0 - // l4*f3+l2*f1 r4*f3+r2*f1 - - pVfilter += 2; - pVsrc += 2; - } - // accu >>= resultDivFactor - accu1 = _mm_srai_pi32(accu1, resultDivFactor); - accu2 = _mm_srai_pi32(accu2, resultDivFactor); - - // pack 2*2*32bits => 4*16 bits - pVdest[0] = _mm_packs_pi32(accu1, accu2); - src += 4; - pVdest ++; - } - - _m_empty(); // clear emms state - - return (numSamples & 0xfffffffe) - length; -} - -#endif // ALLOW_MMX diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.5.0/sse_optimized.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/sse_optimized.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.5.0/sse_optimized.cpp 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.5.0/sse_optimized.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,510 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// -/// SSE optimized routines for Pentium-III, Athlon-XP and later CPUs. All SSE -/// optimized functions have been gathered into this single source -/// code file, regardless to their class or original source code file, in order -/// to ease porting the library to other compiler and processor platforms. -/// -/// The SSE-optimizations are programmed using SSE compiler intrinsics that -/// are supported both by Microsoft Visual C++ and GCC compilers, so this file -/// should compile with both toolsets. -/// -/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++ -/// 6.0 processor pack" update to support SSE instruction set. The update is -/// available for download at Microsoft Developers Network, see here: -/// http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx -/// -/// If the above URL is expired or removed, go to "http://msdn.microsoft.com" and -/// perform a search with keywords "processor pack". -/// -/// Author : Copyright (c) Olli Parviainen -/// Author e-mail : oparviai 'at' iki.fi -/// SoundTouch WWW: http://www.surina.net/soundtouch -/// -//////////////////////////////////////////////////////////////////////////////// -// -// Last changed : $Date: 2009-12-28 22:32:57 +0200 (Mon, 28 Dec 2009) $ -// File revision : $Revision: 4 $ -// -// $Id: sse_optimized.cpp 80 2009-12-28 20:32:57Z oparviai $ -// -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#include "cpu_detect.h" -#include "STTypes.h" - -using namespace soundtouch; - -#ifdef ALLOW_SSE - -// SSE routines available only with float sample type - -////////////////////////////////////////////////////////////////////////////// -// -// implementation of SSE optimized functions of class 'TDStretchSSE' -// -////////////////////////////////////////////////////////////////////////////// - -#include "TDStretch.h" -#include -#include - -// Calculates cross correlation of two buffers -double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) const -{ - int i; - const float *pVec1; - const __m128 *pVec2; - __m128 vSum, vNorm; - - // Note. It means a major slow-down if the routine needs to tolerate - // unaligned __m128 memory accesses. It's way faster if we can skip - // unaligned slots and use _mm_load_ps instruction instead of _mm_loadu_ps. - // This can mean up to ~ 10-fold difference (incl. part of which is - // due to skipping every second round for stereo sound though). - // - // Compile-time define ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided - // for choosing if this little cheating is allowed. - -#ifdef ALLOW_NONEXACT_SIMD_OPTIMIZATION - // Little cheating allowed, return valid correlation only for - // aligned locations, meaning every second round for stereo sound. - - #define _MM_LOAD _mm_load_ps - - if (((ulong)pV1) & 15) return -1e50; // skip unaligned locations - -#else - // No cheating allowed, use unaligned load & take the resulting - // performance hit. - #define _MM_LOAD _mm_loadu_ps -#endif - - // ensure overlapLength is divisible by 8 - assert((overlapLength % 8) == 0); - - // Calculates the cross-correlation value between 'pV1' and 'pV2' vectors - // Note: pV2 _must_ be aligned to 16-bit boundary, pV1 need not. - pVec1 = (const float*)pV1; - pVec2 = (const __m128*)pV2; - vSum = vNorm = _mm_setzero_ps(); - - // Unroll the loop by factor of 4 * 4 operations - for (i = 0; i < overlapLength / 8; i ++) - { - __m128 vTemp; - // vSum += pV1[0..3] * pV2[0..3] - vTemp = _MM_LOAD(pVec1); - vSum = _mm_add_ps(vSum, _mm_mul_ps(vTemp ,pVec2[0])); - vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp ,vTemp)); - - // vSum += pV1[4..7] * pV2[4..7] - vTemp = _MM_LOAD(pVec1 + 4); - vSum = _mm_add_ps(vSum, _mm_mul_ps(vTemp, pVec2[1])); - vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp ,vTemp)); - - // vSum += pV1[8..11] * pV2[8..11] - vTemp = _MM_LOAD(pVec1 + 8); - vSum = _mm_add_ps(vSum, _mm_mul_ps(vTemp, pVec2[2])); - vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp ,vTemp)); - - // vSum += pV1[12..15] * pV2[12..15] - vTemp = _MM_LOAD(pVec1 + 12); - vSum = _mm_add_ps(vSum, _mm_mul_ps(vTemp, pVec2[3])); - vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp ,vTemp)); - - pVec1 += 16; - pVec2 += 4; - } - - // return value = vSum[0] + vSum[1] + vSum[2] + vSum[3] - float *pvNorm = (float*)&vNorm; - double norm = sqrt(pvNorm[0] + pvNorm[1] + pvNorm[2] + pvNorm[3]); - if (norm < 1e-9) norm = 1.0; // to avoid div by zero - - float *pvSum = (float*)&vSum; - return (double)(pvSum[0] + pvSum[1] + pvSum[2] + pvSum[3]) / norm; - - /* This is approximately corresponding routine in C-language yet without normalization: - double corr, norm; - uint i; - - // Calculates the cross-correlation value between 'pV1' and 'pV2' vectors - corr = norm = 0.0; - for (i = 0; i < overlapLength / 8; i ++) - { - corr += pV1[0] * pV2[0] + - pV1[1] * pV2[1] + - pV1[2] * pV2[2] + - pV1[3] * pV2[3] + - pV1[4] * pV2[4] + - pV1[5] * pV2[5] + - pV1[6] * pV2[6] + - pV1[7] * pV2[7] + - pV1[8] * pV2[8] + - pV1[9] * pV2[9] + - pV1[10] * pV2[10] + - pV1[11] * pV2[11] + - pV1[12] * pV2[12] + - pV1[13] * pV2[13] + - pV1[14] * pV2[14] + - pV1[15] * pV2[15]; - - for (j = 0; j < 15; j ++) norm += pV1[j] * pV1[j]; - - pV1 += 16; - pV2 += 16; - } - return corr / sqrt(norm); - */ - - /* This is a bit outdated, corresponding routine in assembler. This may be teeny-weeny bit - faster than intrinsic version, but more difficult to maintain & get compiled on multiple - platforms. - - uint overlapLengthLocal = overlapLength; - float corr; - - _asm - { - // Very important note: data in 'pV2' _must_ be aligned to - // 16-byte boundary! - - // give prefetch hints to CPU of what data are to be needed soonish - // give more aggressive hints on pV1 as that changes while pV2 stays - // same between runs - prefetcht0 [pV1] - prefetcht0 [pV2] - prefetcht0 [pV1 + 32] - - mov eax, dword ptr pV1 - mov ebx, dword ptr pV2 - - xorps xmm0, xmm0 - - mov ecx, overlapLengthLocal - shr ecx, 3 // div by eight - - loop1: - prefetcht0 [eax + 64] // give a prefetch hint to CPU what data are to be needed soonish - prefetcht0 [ebx + 32] // give a prefetch hint to CPU what data are to be needed soonish - movups xmm1, [eax] - mulps xmm1, [ebx] - addps xmm0, xmm1 - - movups xmm2, [eax + 16] - mulps xmm2, [ebx + 16] - addps xmm0, xmm2 - - prefetcht0 [eax + 96] // give a prefetch hint to CPU what data are to be needed soonish - prefetcht0 [ebx + 64] // give a prefetch hint to CPU what data are to be needed soonish - - movups xmm3, [eax + 32] - mulps xmm3, [ebx + 32] - addps xmm0, xmm3 - - movups xmm4, [eax + 48] - mulps xmm4, [ebx + 48] - addps xmm0, xmm4 - - add eax, 64 - add ebx, 64 - - dec ecx - jnz loop1 - - // add the four floats of xmm0 together and return the result. - - movhlps xmm1, xmm0 // move 3 & 4 of xmm0 to 1 & 2 of xmm1 - addps xmm1, xmm0 - movaps xmm2, xmm1 - shufps xmm2, xmm2, 0x01 // move 2 of xmm2 as 1 of xmm2 - addss xmm2, xmm1 - movss corr, xmm2 - } - - return (double)corr; - */ -} - - -////////////////////////////////////////////////////////////////////////////// -// -// implementation of SSE optimized functions of class 'FIRFilter' -// -////////////////////////////////////////////////////////////////////////////// - -#include "FIRFilter.h" - -FIRFilterSSE::FIRFilterSSE() : FIRFilter() -{ - filterCoeffsAlign = NULL; - filterCoeffsUnalign = NULL; -} - - -FIRFilterSSE::~FIRFilterSSE() -{ - delete[] filterCoeffsUnalign; - filterCoeffsAlign = NULL; - filterCoeffsUnalign = NULL; -} - - -// (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 - // also rearrange coefficients suitably for 3DNow! - // Ensure that filter coeffs array is aligned to 16-byte boundary - delete[] filterCoeffsUnalign; - filterCoeffsUnalign = new float[2 * newLength + 4]; - filterCoeffsAlign = (float *)(((unsigned long)filterCoeffsUnalign + 15) & (ulong)-16); - - fDivider = (float)resultDivider; - - // rearrange the filter coefficients for mmx routines - for (i = 0; i < newLength; i ++) - { - filterCoeffsAlign[2 * i + 0] = - filterCoeffsAlign[2 * i + 1] = coeffs[i + 0] / fDivider; - } -} - - - -// SSE-optimized version of the filter routine for stereo sound -uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint numSamples) const -{ - int count = (int)((numSamples - length) & (uint)-2); - int j; - - assert(count % 2 == 0); - - if (count < 2) return 0; - - assert(source != NULL); - assert(dest != NULL); - assert((length % 8) == 0); - assert(filterCoeffsAlign != NULL); - assert(((ulong)filterCoeffsAlign) % 16 == 0); - - // filter is evaluated for two stereo samples with each iteration, thus use of 'j += 2' - for (j = 0; j < count; j += 2) - { - const float *pSrc; - const __m128 *pFil; - __m128 sum1, sum2; - uint i; - - pSrc = (const float*)source; // source audio data - pFil = (const __m128*)filterCoeffsAlign; // filter coefficients. NOTE: Assumes coefficients - // are aligned to 16-byte boundary - sum1 = sum2 = _mm_setzero_ps(); - - for (i = 0; i < length / 8; i ++) - { - // Unroll loop for efficiency & calculate filter for 2*2 stereo samples - // at each pass - - // sum1 is accu for 2*2 filtered stereo sound data at the primary sound data offset - // sum2 is accu for 2*2 filtered stereo sound data for the next sound sample offset. - - sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc) , pFil[0])); - sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 2), pFil[0])); - - sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc + 4), pFil[1])); - sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 6), pFil[1])); - - sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc + 8) , pFil[2])); - sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 10), pFil[2])); - - sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc + 12), pFil[3])); - sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 14), pFil[3])); - - pSrc += 16; - pFil += 4; - } - - // Now sum1 and sum2 both have a filtered 2-channel sample each, but we still need - // to sum the two hi- and lo-floats of these registers together. - - // post-shuffle & add the filtered values and store to dest. - _mm_storeu_ps(dest, _mm_add_ps( - _mm_shuffle_ps(sum1, sum2, _MM_SHUFFLE(1,0,3,2)), // s2_1 s2_0 s1_3 s1_2 - _mm_shuffle_ps(sum1, sum2, _MM_SHUFFLE(3,2,1,0)) // s2_3 s2_2 s1_1 s1_0 - )); - source += 4; - dest += 4; - } - - // Ideas for further improvement: - // 1. If it could be guaranteed that 'source' were always aligned to 16-byte - // boundary, a faster aligned '_mm_load_ps' instruction could be used. - // 2. If it could be guaranteed that 'dest' were always aligned to 16-byte - // boundary, a faster '_mm_store_ps' instruction could be used. - - return (uint)count; - - /* original routine in C-language. please notice the C-version has differently - organized coefficients though. - double suml1, suml2; - double sumr1, sumr2; - uint i, j; - - for (j = 0; j < count; j += 2) - { - const float *ptr; - const float *pFil; - - suml1 = sumr1 = 0.0; - suml2 = sumr2 = 0.0; - ptr = src; - pFil = filterCoeffs; - for (i = 0; i < lengthLocal; i ++) - { - // unroll loop for efficiency. - - suml1 += ptr[0] * pFil[0] + - ptr[2] * pFil[2] + - ptr[4] * pFil[4] + - ptr[6] * pFil[6]; - - sumr1 += ptr[1] * pFil[1] + - ptr[3] * pFil[3] + - ptr[5] * pFil[5] + - ptr[7] * pFil[7]; - - suml2 += ptr[8] * pFil[0] + - ptr[10] * pFil[2] + - ptr[12] * pFil[4] + - ptr[14] * pFil[6]; - - sumr2 += ptr[9] * pFil[1] + - ptr[11] * pFil[3] + - ptr[13] * pFil[5] + - ptr[15] * pFil[7]; - - ptr += 16; - pFil += 8; - } - dest[0] = (float)suml1; - dest[1] = (float)sumr1; - dest[2] = (float)suml2; - dest[3] = (float)sumr2; - - src += 4; - dest += 4; - } - */ - - - /* Similar routine in assembly, again obsoleted due to maintainability - _asm - { - // Very important note: data in 'src' _must_ be aligned to - // 16-byte boundary! - mov edx, count - mov ebx, dword ptr src - mov eax, dword ptr dest - shr edx, 1 - - loop1: - // "outer loop" : during each round 2*2 output samples are calculated - - // give prefetch hints to CPU of what data are to be needed soonish - prefetcht0 [ebx] - prefetcht0 [filterCoeffsLocal] - - mov esi, ebx - mov edi, filterCoeffsLocal - xorps xmm0, xmm0 - xorps xmm1, xmm1 - mov ecx, lengthLocal - - loop2: - // "inner loop" : during each round eight FIR filter taps are evaluated for 2*2 samples - prefetcht0 [esi + 32] // give a prefetch hint to CPU what data are to be needed soonish - prefetcht0 [edi + 32] // give a prefetch hint to CPU what data are to be needed soonish - - movups xmm2, [esi] // possibly unaligned load - movups xmm3, [esi + 8] // possibly unaligned load - mulps xmm2, [edi] - mulps xmm3, [edi] - addps xmm0, xmm2 - addps xmm1, xmm3 - - movups xmm4, [esi + 16] // possibly unaligned load - movups xmm5, [esi + 24] // possibly unaligned load - mulps xmm4, [edi + 16] - mulps xmm5, [edi + 16] - addps xmm0, xmm4 - addps xmm1, xmm5 - - prefetcht0 [esi + 64] // give a prefetch hint to CPU what data are to be needed soonish - prefetcht0 [edi + 64] // give a prefetch hint to CPU what data are to be needed soonish - - movups xmm6, [esi + 32] // possibly unaligned load - movups xmm7, [esi + 40] // possibly unaligned load - mulps xmm6, [edi + 32] - mulps xmm7, [edi + 32] - addps xmm0, xmm6 - addps xmm1, xmm7 - - movups xmm4, [esi + 48] // possibly unaligned load - movups xmm5, [esi + 56] // possibly unaligned load - mulps xmm4, [edi + 48] - mulps xmm5, [edi + 48] - addps xmm0, xmm4 - addps xmm1, xmm5 - - add esi, 64 - add edi, 64 - dec ecx - jnz loop2 - - // Now xmm0 and xmm1 both have a filtered 2-channel sample each, but we still need - // to sum the two hi- and lo-floats of these registers together. - - movhlps xmm2, xmm0 // xmm2 = xmm2_3 xmm2_2 xmm0_3 xmm0_2 - movlhps xmm2, xmm1 // xmm2 = xmm1_1 xmm1_0 xmm0_3 xmm0_2 - shufps xmm0, xmm1, 0xe4 // xmm0 = xmm1_3 xmm1_2 xmm0_1 xmm0_0 - addps xmm0, xmm2 - - movaps [eax], xmm0 - add ebx, 16 - add eax, 16 - - dec edx - jnz loop1 - } - */ -} - -#endif // ALLOW_SSE diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/AAFilter.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/AAFilter.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/AAFilter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/AAFilter.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,184 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// FIR low-pass (anti-alias) filter with filter coefficient design routine and +/// MMX optimization. +/// +/// Anti-alias filter is used to prevent folding of high frequencies when +/// transposing the sample rate with interpolation. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2009-01-11 13:34:24 +0200 (Sun, 11 Jan 2009) $ +// File revision : $Revision: 4 $ +// +// $Id: AAFilter.cpp 45 2009-01-11 11:34:24Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "AAFilter.h" +#include "FIRFilter.h" + +using namespace soundtouch; + +#define PI 3.141592655357989 +#define TWOPI (2 * PI) + +/***************************************************************************** + * + * Implementation of the class 'AAFilter' + * + *****************************************************************************/ + +AAFilter::AAFilter(uint len) +{ + pFIR = FIRFilter::newInstance(); + cutoffFreq = 0.5; + setLength(len); +} + + + +AAFilter::~AAFilter() +{ + delete pFIR; +} + + + +// Sets new anti-alias filter cut-off edge frequency, scaled to +// sampling frequency (nyquist frequency = 0.5). +// The filter will cut frequencies higher than the given frequency. +void AAFilter::setCutoffFreq(double newCutoffFreq) +{ + cutoffFreq = newCutoffFreq; + calculateCoeffs(); +} + + + +// Sets number of FIR filter taps +void AAFilter::setLength(uint newLength) +{ + length = newLength; + calculateCoeffs(); +} + + + +// Calculates coefficients for a low-pass FIR filter using Hamming window +void AAFilter::calculateCoeffs() +{ + uint i; + double cntTemp, temp, tempCoeff,h, w; + double fc2, wc; + double scaleCoeff, sum; + double *work; + SAMPLETYPE *coeffs; + + assert(length >= 2); + assert(length % 4 == 0); + assert(cutoffFreq >= 0); + assert(cutoffFreq <= 0.5); + + work = new double[length]; + coeffs = new SAMPLETYPE[length]; + + fc2 = 2.0 * cutoffFreq; + wc = PI * fc2; + tempCoeff = TWOPI / (double)length; + + sum = 0; + for (i = 0; i < length; i ++) + { + cntTemp = (double)i - (double)(length / 2); + + temp = cntTemp * wc; + if (temp != 0) + { + h = fc2 * sin(temp) / temp; // sinc function + } + else + { + h = 1.0; + } + w = 0.54 + 0.46 * cos(tempCoeff * cntTemp); // hamming window + + temp = w * h; + work[i] = temp; + + // calc net sum of coefficients + sum += temp; + } + + // ensure the sum of coefficients is larger than zero + assert(sum > 0); + + // ensure we've really designed a lowpass filter... + assert(work[length/2] > 0); + assert(work[length/2 + 1] > -1e-6); + assert(work[length/2 - 1] > -1e-6); + + // Calculate a scaling coefficient in such a way that the result can be + // divided by 16384 + scaleCoeff = 16384.0f / sum; + + for (i = 0; i < length; i ++) + { + // scale & round to nearest integer + temp = work[i] * scaleCoeff; + temp += (temp >= 0) ? 0.5 : -0.5; + // ensure no overfloods + assert(temp >= -32768 && temp <= 32767); + coeffs[i] = (SAMPLETYPE)temp; + } + + // Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384 + pFIR->setCoefficients(coeffs, length, 14); + + delete[] work; + delete[] coeffs; +} + + +// Applies the filter to the given sequence of samples. +// Note : The amount of outputted samples is by value of 'filter length' +// smaller than the amount of input samples. +uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const +{ + return pFIR->evaluate(dest, src, numSamples, numChannels); +} + + +uint AAFilter::getLength() const +{ + return pFIR->getLength(); +} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/AAFilter.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/AAFilter.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/AAFilter.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/AAFilter.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,91 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo +/// while maintaining the original pitch by using a time domain WSOLA-like method +/// with several performance-increasing tweaks. +/// +/// Anti-alias filter is used to prevent folding of high frequencies when +/// transposing the sample rate with interpolation. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// File revision : $Revision: 4 $ +// +// $Id: AAFilter.h 11 2008-02-10 16:26:55Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 AAFilter_H +#define AAFilter_H + +#include "STTypes.h" + +namespace soundtouch +{ + +class AAFilter +{ +protected: + class FIRFilter *pFIR; + + /// Low-pass filter cut-off frequency, negative = invalid + double cutoffFreq; + + /// num of filter taps + uint length; + + /// Calculate the FIR coefficients realizing the given cutoff-frequency + void calculateCoeffs(); +public: + AAFilter(uint length); + + ~AAFilter(); + + /// Sets new anti-alias filter cut-off edge frequency, scaled to sampling + /// frequency (nyquist frequency = 0.5). The filter will cut off the + /// frequencies than that. + void setCutoffFreq(double newCutoffFreq); + + /// Sets number of FIR filter taps, i.e. ~filter complexity + void setLength(uint newLength); + + uint getLength() const; + + /// Applies the filter to the given sequence of samples. + /// Note : The amount of outputted samples is by value of 'filter length' + /// smaller than the amount of input samples. + uint evaluate(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples, + uint numChannels) const; +}; + +} + +#endif diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/BPMDetect.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/BPMDetect.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/BPMDetect.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/BPMDetect.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,377 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Beats-per-minute (BPM) detection routine. +/// +/// The beat detection algorithm works as follows: +/// - Use function 'inputSamples' to input a chunks of samples to the class for +/// analysis. It's a good idea to enter a large sound file or stream in smallish +/// chunks of around few kilosamples in order not to extinguish too much RAM memory. +/// - Inputted sound data is decimated to approx 500 Hz to reduce calculation burden, +/// which is basically ok as low (bass) frequencies mostly determine the beat rate. +/// Simple averaging is used for anti-alias filtering because the resulting signal +/// quality isn't of that high importance. +/// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by +/// taking absolute value that's smoothed by sliding average. Signal levels that +/// are below a couple of times the general RMS amplitude level are cut away to +/// leave only notable peaks there. +/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term +/// autocorrelation function of the enveloped signal. +/// - After whole sound data file has been analyzed as above, the bpm level is +/// detected by function 'getBpm' that finds the highest peak of the autocorrelation +/// function, calculates it's precise location and converts this reading to bpm's. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-07-13 11:07:14 +0300 (Wed, 13 Jul 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: BPMDetect.cpp 105 2011-07-13 08:07:14Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "FIFOSampleBuffer.h" +#include "PeakFinder.h" +#include "BPMDetect.h" + +using namespace soundtouch; + +#define INPUT_BLOCK_SAMPLES 2048 +#define DECIMATED_BLOCK_SAMPLES 256 + +/// decay constant for calculating RMS volume sliding average approximation +/// (time constant is about 10 sec) +const float avgdecay = 0.99986f; + +/// Normalization coefficient for calculating RMS sliding average approximation. +const float avgnorm = (1 - avgdecay); + + +//////////////////////////////////////////////////////////////////////////////// + +// Enable following define to create bpm analysis file: + +// #define _CREATE_BPM_DEBUG_FILE + +#ifdef _CREATE_BPM_DEBUG_FILE + + #define DEBUGFILE_NAME "c:\\temp\\soundtouch-bpm-debug.txt" + + static void _SaveDebugData(const float *data, int minpos, int maxpos, double coeff) + { + FILE *fptr = fopen(DEBUGFILE_NAME, "wt"); + int i; + + if (fptr) + { + printf("\n\nWriting BPM debug data into file " DEBUGFILE_NAME "\n\n"); + for (i = minpos; i < maxpos; i ++) + { + fprintf(fptr, "%d\t%.1lf\t%f\n", i, coeff / (double)i, data[i]); + } + fclose(fptr); + } + } +#else + #define _SaveDebugData(a,b,c,d) +#endif + +//////////////////////////////////////////////////////////////////////////////// + + +BPMDetect::BPMDetect(int numChannels, int aSampleRate) +{ + this->sampleRate = aSampleRate; + this->channels = numChannels; + + decimateSum = 0; + decimateCount = 0; + + envelopeAccu = 0; + + // Initialize RMS volume accumulator to RMS level of 3000 (out of 32768) that's + // a typical RMS signal level value for song data. This value is then adapted + // to the actual level during processing. +#ifdef SOUNDTOUCH_INTEGER_SAMPLES + // integer samples + RMSVolumeAccu = (3000 * 3000) / avgnorm; +#else + // float samples, scaled to range [-1..+1[ + RMSVolumeAccu = (0.092f * 0.092f) / avgnorm; +#endif + + cutCoeff = 1.75; + aboveCutAccu = 0; + totalAccu = 0; + + // choose decimation factor so that result is approx. 500 Hz + decimateBy = sampleRate / 500; + assert(decimateBy > 0); + assert(INPUT_BLOCK_SAMPLES < decimateBy * DECIMATED_BLOCK_SAMPLES); + + // Calculate window length & starting item according to desired min & max bpms + windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM); + windowStart = (60 * sampleRate) / (decimateBy * MAX_BPM); + + assert(windowLen > windowStart); + + // allocate new working objects + xcorr = new float[windowLen]; + memset(xcorr, 0, windowLen * sizeof(float)); + + // allocate processing buffer + buffer = new FIFOSampleBuffer(); + // we do processing in mono mode + buffer->setChannels(1); + buffer->clear(); +} + + + +BPMDetect::~BPMDetect() +{ + delete[] xcorr; + delete buffer; +} + + + +/// convert to mono, low-pass filter & decimate to about 500 Hz. +/// return number of outputted samples. +/// +/// Decimation is used to remove the unnecessary frequencies and thus to reduce +/// the amount of data needed to be processed as calculating autocorrelation +/// function is a very-very heavy operation. +/// +/// Anti-alias filtering is done simply by averaging the samples. This is really a +/// poor-man's anti-alias filtering, but it's not so critical in this kind of application +/// (it'd also be difficult to design a high-quality filter with steep cut-off at very +/// narrow band) +int BPMDetect::decimate(SAMPLETYPE *dest, const SAMPLETYPE *src, int numsamples) +{ + int count, outcount; + LONG_SAMPLETYPE out; + + assert(channels > 0); + assert(decimateBy > 0); + outcount = 0; + for (count = 0; count < numsamples; count ++) + { + int j; + + // convert to mono and accumulate + for (j = 0; j < channels; j ++) + { + decimateSum += src[j]; + } + src += j; + + decimateCount ++; + if (decimateCount >= decimateBy) + { + // Store every Nth sample only + out = (LONG_SAMPLETYPE)(decimateSum / (decimateBy * channels)); + decimateSum = 0; + decimateCount = 0; +#ifdef SOUNDTOUCH_INTEGER_SAMPLES + // check ranges for sure (shouldn't actually be necessary) + if (out > 32767) + { + out = 32767; + } + else if (out < -32768) + { + out = -32768; + } +#endif // SOUNDTOUCH_INTEGER_SAMPLES + dest[outcount] = (SAMPLETYPE)out; + outcount ++; + } + } + return outcount; +} + + + +// Calculates autocorrelation function of the sample history buffer +void BPMDetect::updateXCorr(int process_samples) +{ + int offs; + SAMPLETYPE *pBuffer; + + assert(buffer->numSamples() >= (uint)(process_samples + windowLen)); + + pBuffer = buffer->ptrBegin(); + for (offs = windowStart; offs < windowLen; offs ++) + { + LONG_SAMPLETYPE sum; + int i; + + sum = 0; + for (i = 0; i < process_samples; i ++) + { + sum += pBuffer[i] * pBuffer[i + offs]; // scaling the sub-result shouldn't be necessary + } +// xcorr[offs] *= xcorr_decay; // decay 'xcorr' here with suitable coefficients + // if it's desired that the system adapts automatically to + // various bpms, e.g. in processing continouos music stream. + // The 'xcorr_decay' should be a value that's smaller than but + // close to one, and should also depend on 'process_samples' value. + + xcorr[offs] += (float)sum; + } +} + + +// Calculates envelope of the sample data +void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples) +{ + const static double decay = 0.7f; // decay constant for smoothing the envelope + const static double norm = (1 - decay); + + int i; + LONG_SAMPLETYPE out; + double val; + + for (i = 0; i < numsamples; i ++) + { + // calc average RMS volume + RMSVolumeAccu *= avgdecay; + val = (float)fabs((float)samples[i]); + RMSVolumeAccu += val * val; + + // cut amplitudes that are below cutoff ~2 times RMS volume + // (we're interested in peak values, not the silent moments) + val -= cutCoeff * sqrt(RMSVolumeAccu * avgnorm); + if (val > 0) + { + aboveCutAccu += 1.0; // sample above threshold + } + else + { + val = 0; + } + + totalAccu += 1.0; + + // maintain sliding statistic what proportion of 'val' samples is + // above cutoff threshold + aboveCutAccu *= 0.99931; // 2 sec time constant + totalAccu *= 0.99931; + + if (totalAccu > 500) + { + // after initial settling, auto-adjust cutoff level so that ~8% of + // values are above the threshold + double d = (aboveCutAccu / totalAccu) - 0.08; + cutCoeff += 0.001 * d; + } + + // smooth amplitude envelope + envelopeAccu *= decay; + envelopeAccu += val; + out = (LONG_SAMPLETYPE)(envelopeAccu * norm); + +#ifdef SOUNDTOUCH_INTEGER_SAMPLES + // cut peaks (shouldn't be necessary though) + if (out > 32767) out = 32767; +#endif // SOUNDTOUCH_INTEGER_SAMPLES + samples[i] = (SAMPLETYPE)out; + } + + // check that cutoff doesn't get too small - it can be just silent sequence! + if (cutCoeff < 1.5) + { + cutCoeff = 1.5; + } +} + + + +void BPMDetect::inputSamples(const SAMPLETYPE *samples, int numSamples) +{ + SAMPLETYPE decimated[DECIMATED_BLOCK_SAMPLES]; + + // iterate so that max INPUT_BLOCK_SAMPLES processed per iteration + while (numSamples > 0) + { + int block; + int decSamples; + + block = (numSamples > INPUT_BLOCK_SAMPLES) ? INPUT_BLOCK_SAMPLES : numSamples; + + // decimate. note that converts to mono at the same time + decSamples = decimate(decimated, samples, block); + samples += block * channels; + numSamples -= block; + + // envelope new samples and add them to buffer + calcEnvelope(decimated, decSamples); + buffer->putSamples(decimated, decSamples); + } + + // when the buffer has enought samples for processing... + if ((int)buffer->numSamples() > windowLen) + { + int processLength; + + // how many samples are processed + processLength = (int)buffer->numSamples() - windowLen; + + // ... calculate autocorrelations for oldest samples... + updateXCorr(processLength); + // ... and remove them from the buffer + buffer->receiveSamples(processLength); + } +} + + + +float BPMDetect::getBpm() +{ + double peakPos; + double coeff; + PeakFinder peakFinder; + + coeff = 60.0 * ((double)sampleRate / (double)decimateBy); + + // save bpm debug analysis data if debug data enabled + _SaveDebugData(xcorr, windowStart, windowLen, coeff); + + // find peak position + peakPos = peakFinder.detectPeak(xcorr, windowStart, windowLen); + + assert(decimateBy != 0); + if (peakPos < 1e-9) return 0.0; // detection failed. + + // calculate BPM + return (float) (coeff / peakPos); +} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/BPMDetect.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/BPMDetect.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/BPMDetect.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/BPMDetect.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,170 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Beats-per-minute (BPM) detection routine. +/// +/// The beat detection algorithm works as follows: +/// - Use function 'inputSamples' to input a chunks of samples to the class for +/// analysis. It's a good idea to enter a large sound file or stream in smallish +/// chunks of around few kilosamples in order not to extinguish too much RAM memory. +/// - Input sound data is decimated to approx 500 Hz to reduce calculation burden, +/// which is basically ok as low (bass) frequencies mostly determine the beat rate. +/// Simple averaging is used for anti-alias filtering because the resulting signal +/// quality isn't of that high importance. +/// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by +/// taking absolute value that's smoothed by sliding average. Signal levels that +/// are below a couple of times the general RMS amplitude level are cut away to +/// leave only notable peaks there. +/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term +/// autocorrelation function of the enveloped signal. +/// - After whole sound data file has been analyzed as above, the bpm level is +/// detected by function 'getBpm' that finds the highest peak of the autocorrelation +/// function, calculates it's precise location and converts this reading to bpm's. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2010-01-06 20:59:23 +0200 (Wed, 06 Jan 2010) $ +// File revision : $Revision: 4 $ +// +// $Id: BPMDetect.h 86 2010-01-06 18:59:23Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 _BPMDetect_H_ +#define _BPMDetect_H_ + +#include "STTypes.h" +#include "FIFOSampleBuffer.h" + +namespace soundtouch +{ + +/// Minimum allowed BPM rate. Used to restrict accepted result above a reasonable limit. +#define MIN_BPM 29 + +/// Maximum allowed BPM rate. Used to restrict accepted result below a reasonable limit. +#define MAX_BPM 230 + + +/// Class for calculating BPM rate for audio data. +class BPMDetect +{ +protected: + /// Auto-correlation accumulator bins. + float *xcorr; + + /// Amplitude envelope sliding average approximation level accumulator + double envelopeAccu; + + /// RMS volume sliding average approximation level accumulator + double RMSVolumeAccu; + + /// Level below which to cut off signals + double cutCoeff; + + /// Accumulator for accounting what proportion of samples exceed cutCoeff level + double aboveCutAccu; + + /// Accumulator for total samples to calculate proportion of samples that exceed cutCoeff level + double totalAccu; + + /// Sample average counter. + int decimateCount; + + /// Sample average accumulator for FIFO-like decimation. + soundtouch::LONG_SAMPLETYPE decimateSum; + + /// Decimate sound by this coefficient to reach approx. 500 Hz. + int decimateBy; + + /// Auto-correlation window length + int windowLen; + + /// Number of channels (1 = mono, 2 = stereo) + int channels; + + /// sample rate + int sampleRate; + + /// Beginning of auto-correlation window: Autocorrelation isn't being updated for + /// the first these many correlation bins. + int windowStart; + + /// FIFO-buffer for decimated processing samples. + soundtouch::FIFOSampleBuffer *buffer; + + /// Updates auto-correlation function for given number of decimated samples that + /// are read from the internal 'buffer' pipe (samples aren't removed from the pipe + /// though). + void updateXCorr(int process_samples /// How many samples are processed. + ); + + /// Decimates samples to approx. 500 Hz. + /// + /// \return Number of output samples. + int decimate(soundtouch::SAMPLETYPE *dest, ///< Destination buffer + const soundtouch::SAMPLETYPE *src, ///< Source sample buffer + int numsamples ///< Number of source samples. + ); + + /// Calculates amplitude envelope for the buffer of samples. + /// Result is output to 'samples'. + void calcEnvelope(soundtouch::SAMPLETYPE *samples, ///< Pointer to input/output data buffer + int numsamples ///< Number of samples in buffer + ); + +public: + /// Constructor. + BPMDetect(int numChannels, ///< Number of channels in sample data. + int sampleRate ///< Sample rate in Hz. + ); + + /// Destructor. + virtual ~BPMDetect(); + + /// Inputs a block of samples for analyzing: Envelopes the samples and then + /// updates the autocorrelation estimation. When whole song data has been input + /// in smaller blocks using this function, read the resulting bpm with 'getBpm' + /// function. + /// + /// Notice that data in 'samples' array can be disrupted in processing. + void inputSamples(const soundtouch::SAMPLETYPE *samples, ///< Pointer to input/working data buffer + int numSamples ///< Number of samples in buffer + ); + + + /// Analyzes the results and returns the BPM rate. Use this function to read result + /// after whole song data has been input to the class by consecutive calls of + /// 'inputSamples' function. + /// + /// \return Beats-per-minute rate, or zero if detection failed. + float getBpm(); +}; + +} + +#endif // _BPMDetect_H_ diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/COPYING.TXT mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/COPYING.TXT --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/COPYING.TXT 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/COPYING.TXT 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 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 +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/FIFOSampleBuffer.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/FIFOSampleBuffer.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/FIFOSampleBuffer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/FIFOSampleBuffer.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,262 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// A buffer class for temporarily storaging sound samples, operates as a +/// first-in-first-out pipe. +/// +/// Samples are added to the end of the sample buffer with the 'putSamples' +/// function, and are received from the beginning of the buffer by calling +/// the 'receiveSamples' function. The class automatically removes the +/// outputted samples from the buffer, as well as grows the buffer size +/// whenever necessary. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2009-02-27 19:24:42 +0200 (Fri, 27 Feb 2009) $ +// File revision : $Revision: 4 $ +// +// $Id: FIFOSampleBuffer.cpp 68 2009-02-27 17:24:42Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "FIFOSampleBuffer.h" + +using namespace soundtouch; + +// Constructor +FIFOSampleBuffer::FIFOSampleBuffer(int numChannels) +{ + assert(numChannels > 0); + sizeInBytes = 0; // reasonable initial value + buffer = NULL; + bufferUnaligned = NULL; + samplesInBuffer = 0; + bufferPos = 0; + channels = (uint)numChannels; + ensureCapacity(32); // allocate initial capacity +} + + +// destructor +FIFOSampleBuffer::~FIFOSampleBuffer() +{ + delete[] bufferUnaligned; + bufferUnaligned = NULL; + buffer = NULL; +} + + +// Sets number of channels, 1 = mono, 2 = stereo +void FIFOSampleBuffer::setChannels(int numChannels) +{ + uint usedBytes; + + assert(numChannels > 0); + usedBytes = channels * samplesInBuffer; + channels = (uint)numChannels; + samplesInBuffer = usedBytes / channels; +} + + +// if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and +// zeroes this pointer by copying samples from the 'bufferPos' pointer +// location on to the beginning of the buffer. +void FIFOSampleBuffer::rewind() +{ + if (buffer && bufferPos) + { + memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer); + bufferPos = 0; + } +} + + +// Adds 'numSamples' pcs of samples from the 'samples' memory position to +// the sample buffer. +void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples) +{ + memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels); + samplesInBuffer += nSamples; +} + + +// Increases the number of samples in the buffer without copying any actual +// samples. +// +// This function is used to update the number of samples in the sample buffer +// when accessing the buffer directly with 'ptrEnd' function. Please be +// careful though! +void FIFOSampleBuffer::putSamples(uint nSamples) +{ + uint req; + + req = samplesInBuffer + nSamples; + ensureCapacity(req); + samplesInBuffer += nSamples; +} + + +// 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 +// inserting new samples into the sample buffer directly. Please be careful! +// +// Parameter 'slackCapacity' tells the function how much free capacity (in +// terms of samples) there _at least_ should be, in order to the caller to +// succesfully insert all the required samples to the buffer. When necessary, +// the function grows the buffer size to comply with this requirement. +// +// When using this function as means for inserting new samples, also remember +// to increase the sample count afterwards, by calling the +// 'putSamples(numSamples)' function. +SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity) +{ + ensureCapacity(samplesInBuffer + slackCapacity); + return buffer + samplesInBuffer * channels; +} + + +// Returns a pointer to the beginning of the currently non-outputted samples. +// This function is provided for accessing the output samples directly. +// Please be careful! +// +// When using this function to output samples, also remember to 'remove' the +// outputted samples from the buffer by calling the +// 'receiveSamples(numSamples)' function +SAMPLETYPE *FIFOSampleBuffer::ptrBegin() +{ + assert(buffer); + return buffer + bufferPos * channels; +} + + +// Ensures that the buffer has enought capacity, i.e. space for _at least_ +// 'capacityRequirement' number of samples. The buffer is grown in steps of +// 4 kilobytes to eliminate the need for frequently growing up the buffer, +// as well as to round the buffer size up to the virtual memory page size. +void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement) +{ + SAMPLETYPE *tempUnaligned, *temp; + + if (capacityRequirement > getCapacity()) + { + // enlarge the buffer in 4kbyte steps (round up to next 4k boundary) + sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096; + assert(sizeInBytes % 2 == 0); + tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)]; + if (tempUnaligned == NULL) + { + throw std::runtime_error("Couldn't allocate memory!\n"); + } + // Align the buffer to begin at 16byte cache line boundary for optimal performance + temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & (ulong)-16); + if (samplesInBuffer) + { + memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE)); + } + delete[] bufferUnaligned; + buffer = temp; + bufferUnaligned = tempUnaligned; + bufferPos = 0; + } + else + { + // simply rewind the buffer (if necessary) + rewind(); + } +} + + +// Returns the current buffer capacity in terms of samples +uint FIFOSampleBuffer::getCapacity() const +{ + return sizeInBytes / (channels * sizeof(SAMPLETYPE)); +} + + +// Returns the number of samples currently in the buffer +uint FIFOSampleBuffer::numSamples() const +{ + return samplesInBuffer; +} + + +// Output samples from beginning of the sample buffer. Copies demanded number +// of samples to output and removes them from the sample buffer. If there +// are less than 'numsample' samples in the buffer, returns all available. +// +// Returns number of samples copied. +uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples) +{ + uint num; + + num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples; + + memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num); + return receiveSamples(num); +} + + +// Removes samples from the beginning of the sample buffer without copying them +// anywhere. Used to reduce the number of samples in the buffer, when accessing +// the sample buffer with the 'ptrBegin' function. +uint FIFOSampleBuffer::receiveSamples(uint maxSamples) +{ + if (maxSamples >= samplesInBuffer) + { + uint temp; + + temp = samplesInBuffer; + samplesInBuffer = 0; + return temp; + } + + samplesInBuffer -= maxSamples; + bufferPos += maxSamples; + + return maxSamples; +} + + +// Returns nonzero if the sample buffer is empty +int FIFOSampleBuffer::isEmpty() const +{ + return (samplesInBuffer == 0) ? 1 : 0; +} + + +// Clears the sample buffer +void FIFOSampleBuffer::clear() +{ + samplesInBuffer = 0; + bufferPos = 0; +} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/FIFOSampleBuffer.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/FIFOSampleBuffer.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/FIFOSampleBuffer.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/FIFOSampleBuffer.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,174 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// A buffer class for temporarily storaging sound samples, operates as a +/// first-in-first-out pipe. +/// +/// Samples are added to the end of the sample buffer with the 'putSamples' +/// function, and are received from the beginning of the buffer by calling +/// the 'receiveSamples' function. The class automatically removes the +/// output samples from the buffer as well as grows the storage size +/// whenever necessary. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// File revision : $Revision: 4 $ +// +// $Id: FIFOSampleBuffer.h 63 2009-02-21 16:00:14Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 FIFOSampleBuffer_H +#define FIFOSampleBuffer_H + +#include "FIFOSamplePipe.h" + +namespace soundtouch +{ + +/// Sample buffer working in FIFO (first-in-first-out) principle. The class takes +/// care of storage size adjustment and data moving during input/output operations. +/// +/// Notice that in case of stereo audio, one sample is considered to consist of +/// both channel data. +class FIFOSampleBuffer : public FIFOSamplePipe +{ +private: + /// Sample buffer. + SAMPLETYPE *buffer; + + // Raw unaligned buffer memory. 'buffer' is made aligned by pointing it to first + // 16-byte aligned location of this buffer + SAMPLETYPE *bufferUnaligned; + + /// Sample buffer size in bytes + uint sizeInBytes; + + /// How many samples are currently in buffer. + uint samplesInBuffer; + + /// Channels, 1=mono, 2=stereo. + uint channels; + + /// Current position pointer to the buffer. This pointer is increased when samples are + /// removed from the pipe so that it's necessary to actually rewind buffer (move data) + /// only new data when is put to the pipe. + uint bufferPos; + + /// Rewind the buffer by moving data from position pointed by 'bufferPos' to real + /// beginning of the buffer. + void rewind(); + + /// Ensures that the buffer has capacity for at least this many samples. + void ensureCapacity(uint capacityRequirement); + + /// Returns current capacity. + uint getCapacity() const; + +public: + + /// Constructor + FIFOSampleBuffer(int numChannels = 2 ///< Number of channels, 1=mono, 2=stereo. + ///< Default is stereo. + ); + + /// destructor + ~FIFOSampleBuffer(); + + /// Returns a pointer to the beginning of the output samples. + /// This function is provided for accessing the output samples directly. + /// Please be careful for not to corrupt the book-keeping! + /// + /// 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(); + + /// 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 + /// inserting new samples into the sample buffer directly. Please be careful + /// not corrupt the book-keeping! + /// + /// When using this function as means for inserting new samples, also remember + /// to increase the sample count afterwards, by calling the + /// 'putSamples(numSamples)' function. + SAMPLETYPE *ptrEnd( + uint slackCapacity ///< How much free capacity (in samples) there _at least_ + ///< should be so that the caller can succesfully insert the + ///< desired samples to the buffer. If necessary, the function + ///< grows the buffer size to comply with this requirement. + ); + + /// Adds 'numSamples' pcs of samples from the 'samples' memory position to + /// the sample buffer. + virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples. + uint numSamples ///< Number of samples to insert. + ); + + /// Adjusts the book-keeping to increase number of samples in the buffer without + /// copying any actual samples. + /// + /// This function is used to update the number of samples in the sample buffer + /// when accessing the buffer directly with 'ptrEnd' function. Please be + /// careful though! + virtual void putSamples(uint numSamples ///< Number of samples been inserted. + ); + + /// 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 + /// 'numsample' samples in the buffer, returns all that available. + /// + /// \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. + ); + + /// 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. + virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe. + ); + + /// Returns number of samples currently available. + virtual uint numSamples() const; + + /// Sets number of channels, 1 = mono, 2 = stereo. + void setChannels(int numChannels); + + /// Returns nonzero if there aren't any samples available for outputting. + virtual int isEmpty() const; + + /// Clears all the samples. + virtual void clear(); +}; + +} + +#endif diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/FIFOSamplePipe.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/FIFOSamplePipe.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/FIFOSamplePipe.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/FIFOSamplePipe.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,221 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// 'FIFOSamplePipe' : An abstract base class for classes that manipulate sound +/// samples by operating like a first-in-first-out pipe: New samples are fed +/// into one end of the pipe with the 'putSamples' function, and the processed +/// samples are received from the other end with the 'receiveSamples' function. +/// +/// 'FIFOProcessor' : A base class for classes the do signal processing with +/// the samples while operating like a first-in-first-out pipe. When samples +/// are input with the 'putSamples' function, the class processes them +/// and moves the processed samples to the given 'output' pipe object, which +/// may be either another processing stage, or a fifo sample buffer object. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2009-04-13 16:18:48 +0300 (Mon, 13 Apr 2009) $ +// File revision : $Revision: 4 $ +// +// $Id: FIFOSamplePipe.h 69 2009-04-13 13:18:48Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 FIFOSamplePipe_H +#define FIFOSamplePipe_H + +#include +#include +#include "STTypes.h" + +namespace soundtouch +{ + +/// Abstract base class for FIFO (first-in-first-out) sample processing classes. +class FIFOSamplePipe +{ +public: + // virtual default destructor + virtual ~FIFOSamplePipe() {} + + + /// Returns a pointer to the beginning of the output samples. + /// This function is provided for accessing the output samples directly. + /// Please be careful for not to corrupt the book-keeping! + /// + /// 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() = 0; + + /// Adds 'numSamples' pcs of samples from the 'samples' memory position to + /// the sample buffer. + virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples. + uint numSamples ///< Number of samples to insert. + ) = 0; + + + // Moves samples from the 'other' pipe instance to this instance. + void moveSamples(FIFOSamplePipe &other ///< Other pipe instance where from the receive the data. + ) + { + int 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 + /// 'numsample' samples in the buffer, returns all that available. + /// + /// \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. + ) = 0; + + /// 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. + virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe. + ) = 0; + + /// Returns number of samples currently available. + virtual uint numSamples() const = 0; + + // Returns nonzero if there aren't any samples available for outputting. + virtual int isEmpty() const = 0; + + /// Clears all the samples. + virtual void clear() = 0; +}; + + + +/// Base-class for sound processing routines working in FIFO principle. With this base +/// class it's easy to implement sound processing stages that can be chained together, +/// so that samples that are fed into beginning of the pipe automatically go through +/// all the processing stages. +/// +/// When samples are input to this class, they're first processed and then put to +/// the FIFO pipe that's defined as output of this class. This output pipe can be +/// either other processing stage or a FIFO sample buffer. +class FIFOProcessor :public FIFOSamplePipe +{ +protected: + /// Internal pipe where processed samples are put. + FIFOSamplePipe *output; + + /// Sets output pipe. + void setOutPipe(FIFOSamplePipe *pOutput) + { + assert(output == NULL); + assert(pOutput != NULL); + output = pOutput; + } + + + /// Constructor. Doesn't define output pipe; it has to be set be + /// 'setOutPipe' function. + FIFOProcessor() + { + output = NULL; + } + + + /// Constructor. Configures output pipe. + FIFOProcessor(FIFOSamplePipe *pOutput ///< Output pipe. + ) + { + output = pOutput; + } + + + /// Destructor. + virtual ~FIFOProcessor() + { + } + + + /// Returns a pointer to the beginning of the output samples. + /// This function is provided for accessing the output samples directly. + /// Please be careful for not to corrupt the book-keeping! + /// + /// 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() + { + return output->ptrBegin(); + } + +public: + + /// 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 + /// 'numsample' samples in the buffer, returns all that available. + /// + /// \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. + ) + { + return output->receiveSamples(outBuffer, maxSamples); + } + + + /// 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. + virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe. + ) + { + return output->receiveSamples(maxSamples); + } + + + /// Returns number of samples currently available. + virtual uint numSamples() const + { + return output->numSamples(); + } + + + /// Returns nonzero if there aren't any samples available for outputting. + virtual int isEmpty() const + { + return output->isEmpty(); + } +}; + +} + +#endif diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/FIRFilter.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/FIRFilter.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/FIRFilter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/FIRFilter.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,260 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// General FIR digital filter routines with MMX optimization. +/// +/// Note : MMX optimized functions reside in a separate, platform-specific file, +/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp' +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: FIRFilter.cpp 104 2011-02-13 19:13:57Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "FIRFilter.h" +#include "cpu_detect.h" + +using namespace soundtouch; + +/***************************************************************************** + * + * Implementation of the class 'FIRFilter' + * + *****************************************************************************/ + +FIRFilter::FIRFilter() +{ + resultDivFactor = 0; + resultDivider = 0; + length = 0; + lengthDiv8 = 0; + filterCoeffs = NULL; +} + + +FIRFilter::~FIRFilter() +{ + delete[] filterCoeffs; +} + +// Usual C-version of the filter routine for stereo sound +uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const +{ + uint i, j, end; + LONG_SAMPLETYPE suml, sumr; +#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); + + end = 2 * (numSamples - length); + + for (j = 0; j < end; j += 2) + { + const SAMPLETYPE *ptr; + + suml = sumr = 0; + ptr = src + j; + + for (i = 0; i < length; i += 4) + { + // 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]; + } + +#ifdef SOUNDTOUCH_INTEGER_SAMPLES + suml >>= resultDivFactor; + sumr >>= resultDivFactor; + // saturate to 16 bit integer limits + 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; +} + + + + +// Usual C-version of the filter routine for mono sound +uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const +{ + uint i, j, end; + LONG_SAMPLETYPE sum; +#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); + + end = numSamples - length; + for (j = 0; j < end; j ++) + { + sum = 0; + for (i = 0; i < length; i += 4) + { + // loop is unrolled by factor of 4 here for efficiency + sum += src[i + 0] * filterCoeffs[i + 0] + + src[i + 1] * filterCoeffs[i + 1] + + src[i + 2] * filterCoeffs[i + 2] + + src[i + 3] * filterCoeffs[i + 3]; + } +#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; + src ++; + } + return end; +} + + +// Set filter coeffiecients and length. +// +// Throws an exception if filter length isn't divisible by 8 +void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor) +{ + assert(newLength > 0); + if (newLength % 8) throw std::runtime_error("FIR filter length not divisible by 8"); + + lengthDiv8 = newLength / 8; + length = lengthDiv8 * 8; + assert(length == newLength); + + resultDivFactor = uResultDivFactor; + resultDivider = (SAMPLETYPE)::pow(2.0, (int)resultDivFactor); + + delete[] filterCoeffs; + filterCoeffs = new SAMPLETYPE[length]; + memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE)); +} + + +uint FIRFilter::getLength() const +{ + return length; +} + + + +// Applies the filter to the given sequence of samples. +// +// Note : The amount of outputted samples is by value of 'filter_length' +// smaller than the amount of input samples. +uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const +{ + assert(numChannels == 1 || numChannels == 2); + + assert(length > 0); + assert(lengthDiv8 * 8 == length); + if (numSamples < length) return 0; + if (numChannels == 2) + { + return evaluateFilterStereo(dest, src, numSamples); + } else { + return evaluateFilterMono(dest, src, numSamples); + } +} + + + +// 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) +{ + // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead! + throw std::runtime_error("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!"); + return NULL; +} + + +FIRFilter * FIRFilter::newInstance() +{ + uint uExtensions; + + uExtensions = detectCPUextensions(); + + // Check if MMX/SSE instruction set extensions supported by CPU + +#ifdef SOUNDTOUCH_ALLOW_MMX + // MMX routines available only with integer sample types + if (uExtensions & SUPPORT_MMX) + { + return ::new FIRFilterMMX; + } + else +#endif // SOUNDTOUCH_ALLOW_MMX + +#ifdef SOUNDTOUCH_ALLOW_SSE + if (uExtensions & SUPPORT_SSE) + { + // SSE support + return ::new FIRFilterSSE; + } + else +#endif // SOUNDTOUCH_ALLOW_SSE + + { + // ISA optimizations not supported, use plain C version + return ::new FIRFilter; + } +} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/FIRFilter.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/FIRFilter.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/FIRFilter.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/FIRFilter.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,145 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// General FIR digital filter routines with MMX optimization. +/// +/// Note : MMX optimized functions reside in a separate, platform-specific file, +/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp' +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: FIRFilter.h 104 2011-02-13 19:13:57Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 FIRFilter_H +#define FIRFilter_H + +#include +#include "STTypes.h" + +namespace soundtouch +{ + +class FIRFilter +{ +protected: + // Number of FIR filter taps + uint length; + // Number of FIR filter taps divided by 8 + uint lengthDiv8; + + // Result divider factor in 2^k format + uint resultDivFactor; + + // Result divider value. + SAMPLETYPE resultDivider; + + // Memory for filter coefficients + SAMPLETYPE *filterCoeffs; + + virtual uint evaluateFilterStereo(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples) const; + virtual uint evaluateFilterMono(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples) const; + +public: + FIRFilter(); + virtual ~FIRFilter(); + + /// Operator 'new' is overloaded so that it automatically creates a suitable instance + /// depending on if we've a MMX-capable CPU available or not. + static void * operator new(size_t s); + + static FIRFilter *newInstance(); + + /// Applies the filter to the given sequence of samples. + /// Note : The amount of outputted samples is by value of 'filter_length' + /// smaller than the amount of input samples. + /// + /// \return Number of samples copied to 'dest'. + uint evaluate(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples, + uint numChannels) const; + + uint getLength() const; + + virtual void setCoefficients(const SAMPLETYPE *coeffs, + uint newLength, + uint uResultDivFactor); +}; + + +// Optional subclasses that implement CPU-specific optimizations: + +#ifdef SOUNDTOUCH_ALLOW_MMX + +/// Class that implements MMX optimized functions exclusive for 16bit integer samples type. + class FIRFilterMMX : public FIRFilter + { + protected: + short *filterCoeffsUnalign; + short *filterCoeffsAlign; + + virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const; + public: + FIRFilterMMX(); + ~FIRFilterMMX(); + + virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor); + }; + +#endif // SOUNDTOUCH_ALLOW_MMX + + +#ifdef SOUNDTOUCH_ALLOW_SSE + /// Class that implements SSE optimized functions exclusive for floating point samples type. + class FIRFilterSSE : public FIRFilter + { + protected: + float *filterCoeffsUnalign; + float *filterCoeffsAlign; + + virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const; + public: + FIRFilterSSE(); + ~FIRFilterSSE(); + + virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor); + }; + +#endif // SOUNDTOUCH_ALLOW_SSE + +} + +#endif // FIRFilter_H diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/PeakFinder.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/PeakFinder.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/PeakFinder.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/PeakFinder.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,239 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Peak detection routine. +/// +/// The routine detects highest value on an array of values and calculates the +/// precise peak location as a mass-center of the 'hump' around the peak value. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2010-08-24 18:53:56 +0300 (Tue, 24 Aug 2010) $ +// File revision : $Revision: 4 $ +// +// $Id: PeakFinder.cpp 91 2010-08-24 15:53:56Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "PeakFinder.h" + +using namespace soundtouch; + +#define max(x, y) (((x) > (y)) ? (x) : (y)) + + +PeakFinder::PeakFinder() +{ + minPos = maxPos = 0; +} + + +// Finds 'ground level' of a peak hump by starting from 'peakpos' and proceeding +// to direction defined by 'direction' until next 'hump' after minimum value will +// begin +int PeakFinder::findGround(const float *data, int peakpos, int direction) const +{ + float refvalue; + int lowpos; + int pos; + int climb_count; + float delta; + + climb_count = 0; + refvalue = data[peakpos]; + lowpos = peakpos; + + pos = peakpos; + + while ((pos > minPos) && (pos < maxPos)) + { + int prevpos; + + prevpos = pos; + pos += direction; + + // calculate derivate + delta = data[pos] - data[prevpos]; + if (delta <= 0) + { + // going downhill, ok + if (climb_count) + { + climb_count --; // decrease climb count + } + + // check if new minimum found + if (data[pos] < refvalue) + { + // new minimum found + lowpos = pos; + refvalue = data[pos]; + } + } + else + { + // going uphill, increase climbing counter + climb_count ++; + if (climb_count > 5) break; // we've been climbing too long => it's next uphill => quit + } + } + return lowpos; +} + + +// Find offset where the value crosses the given level, when starting from 'peakpos' and +// proceeds to direction defined in 'direction' +int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, int direction) const +{ + float peaklevel; + int pos; + + peaklevel = data[peakpos]; + assert(peaklevel >= level); + pos = peakpos; + while ((pos >= minPos) && (pos < maxPos)) + { + if (data[pos + direction] < level) return pos; // crossing found + pos += direction; + } + return -1; // not found +} + + +// Calculates the center of mass location of 'data' array items between 'firstPos' and 'lastPos' +double PeakFinder::calcMassCenter(const float *data, int firstPos, int lastPos) const +{ + int i; + float sum; + float wsum; + + sum = 0; + wsum = 0; + for (i = firstPos; i <= lastPos; i ++) + { + sum += (float)i * data[i]; + wsum += data[i]; + } + + if (wsum < 1e-6) return 0; + return sum / wsum; +} + + + +/// get exact center of peak near given position by calculating local mass of center +double PeakFinder::getPeakCenter(const float *data, int peakpos) const +{ + float peakLevel; // peak level + int crosspos1, crosspos2; // position where the peak 'hump' crosses cutting level + float cutLevel; // cutting value + float groundLevel; // ground level of the peak + int gp1, gp2; // bottom positions of the peak 'hump' + + // find ground positions. + gp1 = findGround(data, peakpos, -1); + gp2 = findGround(data, peakpos, 1); + + groundLevel = max(data[gp1], data[gp2]); + peakLevel = data[peakpos]; + + if (groundLevel < 1e-9) return 0; // ground level too small => detection failed + if ((peakLevel / groundLevel) < 1.3) return 0; // peak less than 30% of the ground level => no good peak detected + + // calculate 70%-level of the peak + cutLevel = 0.70f * peakLevel + 0.30f * groundLevel; + // find mid-level crossings + crosspos1 = findCrossingLevel(data, cutLevel, peakpos, -1); + crosspos2 = findCrossingLevel(data, cutLevel, peakpos, 1); + + if ((crosspos1 < 0) || (crosspos2 < 0)) return 0; // no crossing, no peak.. + + // calculate mass center of the peak surroundings + return calcMassCenter(data, crosspos1, crosspos2); +} + + + +double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos) +{ + + int i; + int peakpos; // position of peak level + double highPeak, peak; + + this->minPos = aminPos; + this->maxPos = amaxPos; + + // find absolute peak + peakpos = minPos; + peak = data[minPos]; + for (i = minPos + 1; i < maxPos; i ++) + { + if (data[i] > peak) + { + peak = data[i]; + peakpos = i; + } + } + + // Calculate exact location of the highest peak mass center + highPeak = getPeakCenter(data, peakpos); + peak = highPeak; + + // Now check if the highest peak were in fact harmonic of the true base beat peak + // - sometimes the highest peak can be Nth harmonic of the true base peak yet + // just a slightly higher than the true base + for (i = 2; i < 10; i ++) + { + double peaktmp, tmp; + int i1,i2; + + peakpos = (int)(highPeak / (double)i + 0.5f); + if (peakpos < minPos) break; + + // calculate mass-center of possible base peak + peaktmp = getPeakCenter(data, peakpos); + + // now compare to highest detected peak + i1 = (int)(highPeak + 0.5); + i2 = (int)(peaktmp + 0.5); + tmp = 2 * (data[i2] - data[i1]) / (data[i2] + data[i1]); + if (fabs(tmp) < 0.1) + { + // The highest peak is harmonic of almost as high base peak, + // thus use the base peak instead + peak = peaktmp; + } + } + + return peak; +} + + diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/PeakFinder.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/PeakFinder.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/PeakFinder.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/PeakFinder.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// The routine detects highest value on an array of values and calculates the +/// precise peak location as a mass-center of the 'hump' around the peak value. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// File revision : $Revision: 4 $ +// +// $Id: PeakFinder.h 63 2009-02-21 16:00:14Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 _PeakFinder_H_ +#define _PeakFinder_H_ + +namespace soundtouch +{ + +class PeakFinder +{ +protected: + /// Min, max allowed peak positions within the data vector + int minPos, maxPos; + + /// Calculates the mass center between given vector items. + double calcMassCenter(const float *data, ///< Data vector. + int firstPos, ///< Index of first vector item beloging to the peak. + int lastPos ///< Index of last vector item beloging to the peak. + ) const; + + /// Finds the data vector index where the monotoniously decreasing signal crosses the + /// given level. + int findCrossingLevel(const float *data, ///< Data vector. + float level, ///< Goal crossing level. + int peakpos, ///< Peak position index within the data vector. + int direction /// Direction where to proceed from the peak: 1 = right, -1 = left. + ) const; + + /// Finds the 'ground' level, i.e. smallest level between two neighbouring peaks, to right- + /// or left-hand side of the given peak position. + int findGround(const float *data, /// Data vector. + int peakpos, /// Peak position index within the data vector. + int direction /// Direction where to proceed from the peak: 1 = right, -1 = left. + ) const; + + /// get exact center of peak near given position by calculating local mass of center + double getPeakCenter(const float *data, int peakpos) const; + +public: + /// Constructor. + PeakFinder(); + + /// Detect exact peak position of the data vector by finding the largest peak 'hump' + /// and calculating the mass-center location of the peak hump. + /// + /// \return The location of the largest base harmonic peak hump. + double detectPeak(const float *data, /// Data vector to be analyzed. The data vector has + /// to be at least 'maxPos' items long. + int minPos, ///< Min allowed peak location within the vector data. + int maxPos ///< Max allowed peak location within the vector data. + ); +}; + +} + +#endif // _PeakFinder_H_ diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/RateTransposer.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/RateTransposer.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/RateTransposer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/RateTransposer.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,628 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Sample rate transposer. Changes sample rate by using linear interpolation +/// together with anti-alias filtering (first order interpolation with anti- +/// alias filtering should be quite adequate for this application) +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: RateTransposer.cpp 104 2011-02-13 19:13:57Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "RateTransposer.h" +#include "AAFilter.h" + +using namespace std; +using namespace soundtouch; + + +/// A linear samplerate transposer class that uses integer arithmetics. +/// for the transposing. +class RateTransposerInteger : public RateTransposer +{ +protected: + int iSlopeCount; + int iRate; + SAMPLETYPE sPrevSampleL, sPrevSampleR; + + virtual void resetRegisters(); + + virtual uint transposeStereo(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples); + virtual uint transposeMono(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples); + +public: + RateTransposerInteger(); + virtual ~RateTransposerInteger(); + + /// Sets new target rate. Normal rate = 1.0, smaller values represent slower + /// rate, larger faster rates. + virtual void setRate(float newRate); + +}; + + +/// A linear samplerate transposer class that uses floating point arithmetics +/// for the transposing. +class RateTransposerFloat : public RateTransposer +{ +protected: + float fSlopeCount; + SAMPLETYPE sPrevSampleL, sPrevSampleR; + + virtual void resetRegisters(); + + virtual uint transposeStereo(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples); + virtual uint transposeMono(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples); + +public: + RateTransposerFloat(); + virtual ~RateTransposerFloat(); +}; + + + + +// 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 * RateTransposer::operator new(size_t s) +{ + throw runtime_error("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!"); + return NULL; +} + + +RateTransposer *RateTransposer::newInstance() +{ +#ifdef SOUNDTOUCH_INTEGER_SAMPLES + return ::new RateTransposerInteger; +#else + return ::new RateTransposerFloat; +#endif +} + + +// Constructor +RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer) +{ + numChannels = 2; + bUseAAFilter = TRUE; + fRate = 0; + + // Instantiates the anti-alias filter with default tap length + // of 32 + pAAFilter = new AAFilter(32); +} + + + +RateTransposer::~RateTransposer() +{ + delete pAAFilter; +} + + + +/// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable +void RateTransposer::enableAAFilter(BOOL newMode) +{ + bUseAAFilter = newMode; +} + + +/// Returns nonzero if anti-alias filter is enabled. +BOOL RateTransposer::isAAFilterEnabled() const +{ + return bUseAAFilter; +} + + +AAFilter *RateTransposer::getAAFilter() +{ + return pAAFilter; +} + + + +// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower +// iRate, larger faster iRates. +void RateTransposer::setRate(float newRate) +{ + double fCutoff; + + fRate = newRate; + + // design a new anti-alias filter + if (newRate > 1.0f) + { + fCutoff = 0.5f / newRate; + } + else + { + fCutoff = 0.5f * newRate; + } + pAAFilter->setCutoffFreq(fCutoff); +} + + +// Outputs as many samples of the 'outputBuffer' as possible, and if there's +// any room left, outputs also as many of the incoming samples as possible. +// The goal is to drive the outputBuffer empty. +// +// It's allowed for 'output' and 'input' parameters to point to the same +// memory position. +/* +void RateTransposer::flushStoreBuffer() +{ + if (storeBuffer.isEmpty()) return; + + outputBuffer.moveSamples(storeBuffer); +} +*/ + + +// Adds 'nSamples' pcs of samples from the 'samples' memory position into +// the input of the object. +void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples) +{ + processSamples(samples, nSamples); +} + + + +// Transposes up the sample rate, causing the observed playback 'rate' of the +// sound to decrease +void RateTransposer::upsample(const SAMPLETYPE *src, uint nSamples) +{ + uint count, sizeTemp, num; + + // If the parameter 'uRate' value is smaller than 'SCALE', first transpose + // the samples and then apply the anti-alias filter to remove aliasing. + + // First check that there's enough room in 'storeBuffer' + // (+16 is to reserve some slack in the destination buffer) + sizeTemp = (uint)((float)nSamples / fRate + 16.0f); + + // Transpose the samples, store the result into the end of "storeBuffer" + count = transpose(storeBuffer.ptrEnd(sizeTemp), src, nSamples); + storeBuffer.putSamples(count); + + // Apply the anti-alias filter to samples in "store output", output the + // result to "dest" + num = storeBuffer.numSamples(); + count = pAAFilter->evaluate(outputBuffer.ptrEnd(num), + storeBuffer.ptrBegin(), num, (uint)numChannels); + outputBuffer.putSamples(count); + + // Remove the processed samples from "storeBuffer" + storeBuffer.receiveSamples(count); +} + + +// Transposes down the sample rate, causing the observed playback 'rate' of the +// sound to increase +void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples) +{ + uint count, sizeTemp; + + // If the parameter 'uRate' value is larger than 'SCALE', first apply the + // anti-alias filter to remove high frequencies (prevent them from folding + // over the lover frequencies), then transpose. + + // Add the new samples to the end of the storeBuffer + storeBuffer.putSamples(src, nSamples); + + // Anti-alias filter the samples to prevent folding and output the filtered + // data to tempBuffer. Note : because of the FIR filter length, the + // filtering routine takes in 'filter_length' more samples than it outputs. + assert(tempBuffer.isEmpty()); + sizeTemp = storeBuffer.numSamples(); + + count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp), + storeBuffer.ptrBegin(), sizeTemp, (uint)numChannels); + + if (count == 0) return; + + // Remove the filtered samples from 'storeBuffer' + storeBuffer.receiveSamples(count); + + // Transpose the samples (+16 is to reserve some slack in the destination buffer) + sizeTemp = (uint)((float)nSamples / fRate + 16.0f); + count = transpose(outputBuffer.ptrEnd(sizeTemp), tempBuffer.ptrBegin(), count); + outputBuffer.putSamples(count); +} + + +// Transposes sample rate by applying anti-alias filter to prevent folding. +// Returns amount of samples returned in the "dest" buffer. +// The maximum amount of samples that can be returned at a time is set by +// the 'set_returnBuffer_size' function. +void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples) +{ + uint count; + uint sizeReq; + + if (nSamples == 0) return; + assert(pAAFilter); + + // If anti-alias filter is turned off, simply transpose without applying + // the filter + if (bUseAAFilter == FALSE) + { + sizeReq = (uint)((float)nSamples / fRate + 1.0f); + count = transpose(outputBuffer.ptrEnd(sizeReq), src, nSamples); + outputBuffer.putSamples(count); + return; + } + + // Transpose with anti-alias filter + if (fRate < 1.0f) + { + upsample(src, nSamples); + } + else + { + downsample(src, nSamples); + } +} + + +// Transposes the sample rate of the given samples using linear interpolation. +// Returns the number of samples returned in the "dest" buffer +inline uint RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) +{ + if (numChannels == 2) + { + return transposeStereo(dest, src, nSamples); + } + else + { + return transposeMono(dest, src, nSamples); + } +} + + +// Sets the number of channels, 1 = mono, 2 = stereo +void RateTransposer::setChannels(int nChannels) +{ + assert(nChannels > 0); + if (numChannels == nChannels) return; + + assert(nChannels == 1 || nChannels == 2); + numChannels = nChannels; + + storeBuffer.setChannels(numChannels); + tempBuffer.setChannels(numChannels); + outputBuffer.setChannels(numChannels); + + // Inits the linear interpolation registers + resetRegisters(); +} + + +// Clears all the samples in the object +void RateTransposer::clear() +{ + outputBuffer.clear(); + storeBuffer.clear(); +} + + +// Returns nonzero if there aren't any samples available for outputting. +int RateTransposer::isEmpty() const +{ + int res; + + res = FIFOProcessor::isEmpty(); + if (res == 0) return 0; + return storeBuffer.isEmpty(); +} + + +////////////////////////////////////////////////////////////////////////////// +// +// RateTransposerInteger - integer arithmetic implementation +// + +/// fixed-point interpolation routine precision +#define SCALE 65536 + +// Constructor +RateTransposerInteger::RateTransposerInteger() : RateTransposer() +{ + // Notice: use local function calling syntax for sake of clarity, + // to indicate the fact that C++ constructor can't call virtual functions. + RateTransposerInteger::resetRegisters(); + RateTransposerInteger::setRate(1.0f); +} + + +RateTransposerInteger::~RateTransposerInteger() +{ +} + + +void RateTransposerInteger::resetRegisters() +{ + iSlopeCount = 0; + sPrevSampleL = + sPrevSampleR = 0; +} + + + +// Transposes the sample rate of the given samples using linear interpolation. +// 'Mono' version of the routine. Returns the number of samples returned in +// the "dest" buffer +uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) +{ + unsigned int i, used; + LONG_SAMPLETYPE temp, vol1; + + if (nSamples == 0) return 0; // no samples, no work + + used = 0; + i = 0; + + // Process the last sample saved from the previous call first... + while (iSlopeCount <= SCALE) + { + vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount); + temp = vol1 * sPrevSampleL + iSlopeCount * src[0]; + dest[i] = (SAMPLETYPE)(temp / SCALE); + i++; + iSlopeCount += iRate; + } + // now always (iSlopeCount > SCALE) + iSlopeCount -= SCALE; + + while (1) + { + while (iSlopeCount > SCALE) + { + iSlopeCount -= SCALE; + used ++; + if (used >= nSamples - 1) goto end; + } + vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount); + temp = src[used] * vol1 + iSlopeCount * src[used + 1]; + dest[i] = (SAMPLETYPE)(temp / SCALE); + + i++; + iSlopeCount += iRate; + } +end: + // Store the last sample for the next round + sPrevSampleL = src[nSamples - 1]; + + return i; +} + + +// Transposes the sample rate of the given samples using linear interpolation. +// 'Stereo' version of the routine. Returns the number of samples returned in +// the "dest" buffer +uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) +{ + unsigned int srcPos, i, used; + LONG_SAMPLETYPE temp, vol1; + + if (nSamples == 0) return 0; // no samples, no work + + used = 0; + i = 0; + + // Process the last sample saved from the sPrevSampleLious call first... + while (iSlopeCount <= SCALE) + { + vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount); + temp = vol1 * sPrevSampleL + iSlopeCount * src[0]; + dest[2 * i] = (SAMPLETYPE)(temp / SCALE); + temp = vol1 * sPrevSampleR + iSlopeCount * src[1]; + dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE); + i++; + iSlopeCount += iRate; + } + // now always (iSlopeCount > SCALE) + iSlopeCount -= SCALE; + + while (1) + { + while (iSlopeCount > SCALE) + { + iSlopeCount -= SCALE; + used ++; + if (used >= nSamples - 1) goto end; + } + srcPos = 2 * used; + vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount); + temp = src[srcPos] * vol1 + iSlopeCount * src[srcPos + 2]; + dest[2 * i] = (SAMPLETYPE)(temp / SCALE); + temp = src[srcPos + 1] * vol1 + iSlopeCount * src[srcPos + 3]; + dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE); + + i++; + iSlopeCount += iRate; + } +end: + // Store the last sample for the next round + sPrevSampleL = src[2 * nSamples - 2]; + sPrevSampleR = src[2 * nSamples - 1]; + + return i; +} + + +// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower +// iRate, larger faster iRates. +void RateTransposerInteger::setRate(float newRate) +{ + iRate = (int)(newRate * SCALE + 0.5f); + RateTransposer::setRate(newRate); +} + + +////////////////////////////////////////////////////////////////////////////// +// +// RateTransposerFloat - floating point arithmetic implementation +// +////////////////////////////////////////////////////////////////////////////// + +// Constructor +RateTransposerFloat::RateTransposerFloat() : RateTransposer() +{ + // Notice: use local function calling syntax for sake of clarity, + // to indicate the fact that C++ constructor can't call virtual functions. + RateTransposerFloat::resetRegisters(); + RateTransposerFloat::setRate(1.0f); +} + + +RateTransposerFloat::~RateTransposerFloat() +{ +} + + +void RateTransposerFloat::resetRegisters() +{ + fSlopeCount = 0; + sPrevSampleL = + sPrevSampleR = 0; +} + + + +// Transposes the sample rate of the given samples using linear interpolation. +// 'Mono' version of the routine. Returns the number of samples returned in +// the "dest" buffer +uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) +{ + unsigned int i, used; + + used = 0; + i = 0; + + // Process the last sample saved from the previous call first... + while (fSlopeCount <= 1.0f) + { + dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]); + i++; + fSlopeCount += fRate; + } + fSlopeCount -= 1.0f; + + if (nSamples > 1) + { + while (1) + { + while (fSlopeCount > 1.0f) + { + fSlopeCount -= 1.0f; + used ++; + if (used >= nSamples - 1) goto end; + } + dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[used] + fSlopeCount * src[used + 1]); + i++; + fSlopeCount += fRate; + } + } +end: + // Store the last sample for the next round + sPrevSampleL = src[nSamples - 1]; + + return i; +} + + +// Transposes the sample rate of the given samples using linear interpolation. +// 'Mono' version of the routine. Returns the number of samples returned in +// the "dest" buffer +uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) +{ + unsigned int srcPos, i, used; + + if (nSamples == 0) return 0; // no samples, no work + + used = 0; + i = 0; + + // Process the last sample saved from the sPrevSampleLious call first... + while (fSlopeCount <= 1.0f) + { + dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]); + dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * src[1]); + i++; + fSlopeCount += fRate; + } + // now always (iSlopeCount > 1.0f) + fSlopeCount -= 1.0f; + + if (nSamples > 1) + { + while (1) + { + while (fSlopeCount > 1.0f) + { + fSlopeCount -= 1.0f; + used ++; + if (used >= nSamples - 1) goto end; + } + srcPos = 2 * used; + + dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos] + + fSlopeCount * src[srcPos + 2]); + dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1] + + fSlopeCount * src[srcPos + 3]); + + i++; + fSlopeCount += fRate; + } + } +end: + // Store the last sample for the next round + sPrevSampleL = src[2 * nSamples - 2]; + sPrevSampleR = src[2 * nSamples - 1]; + + return i; +} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/RateTransposer.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/RateTransposer.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/RateTransposer.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/RateTransposer.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,159 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Sample rate transposer. Changes sample rate by using linear interpolation +/// together with anti-alias filtering (first order interpolation with anti- +/// alias filtering should be quite adequate for this application). +/// +/// Use either of the derived classes of 'RateTransposerInteger' or +/// 'RateTransposerFloat' for corresponding integer/floating point tranposing +/// algorithm implementation. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// File revision : $Revision: 4 $ +// +// $Id: RateTransposer.h 63 2009-02-21 16:00:14Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 RateTransposer_H +#define RateTransposer_H + +#include +#include "AAFilter.h" +#include "FIFOSamplePipe.h" +#include "FIFOSampleBuffer.h" + +#include "STTypes.h" + +namespace soundtouch +{ + +/// A common linear samplerate transposer class. +/// +/// Note: Use function "RateTransposer::newInstance()" to create a new class +/// instance instead of the "new" operator; that function automatically +/// chooses a correct implementation depending on if integer or floating +/// arithmetics are to be used. +class RateTransposer : public FIFOProcessor +{ +protected: + /// Anti-alias filter object + AAFilter *pAAFilter; + + float fRate; + + int numChannels; + + /// Buffer for collecting samples to feed the anti-alias filter between + /// two batches + FIFOSampleBuffer storeBuffer; + + /// Buffer for keeping samples between transposing & anti-alias filter + FIFOSampleBuffer tempBuffer; + + /// Output sample buffer + FIFOSampleBuffer outputBuffer; + + BOOL bUseAAFilter; + + virtual void resetRegisters() = 0; + + virtual uint transposeStereo(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples) = 0; + virtual uint transposeMono(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples) = 0; + inline uint transpose(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples); + + void downsample(const SAMPLETYPE *src, + uint numSamples); + void upsample(const SAMPLETYPE *src, + uint numSamples); + + /// Transposes sample rate by applying anti-alias filter to prevent folding. + /// Returns amount of samples returned in the "dest" buffer. + /// The maximum amount of samples that can be returned at a time is set by + /// the 'set_returnBuffer_size' function. + void processSamples(const SAMPLETYPE *src, + uint numSamples); + + +public: + RateTransposer(); + virtual ~RateTransposer(); + + /// Operator 'new' is overloaded so that it automatically creates a suitable instance + /// depending on if we're to use integer or floating point arithmetics. + static void *operator new(size_t s); + + /// Use this function instead of "new" operator to create a new instance of this class. + /// This function automatically chooses a correct implementation, depending on if + /// integer ot floating point arithmetics are to be used. + static RateTransposer *newInstance(); + + /// Returns the output buffer object + FIFOSamplePipe *getOutput() { return &outputBuffer; }; + + /// Returns the store buffer object + FIFOSamplePipe *getStore() { return &storeBuffer; }; + + /// Return anti-alias filter object + AAFilter *getAAFilter(); + + /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable + void enableAAFilter(BOOL newMode); + + /// Returns nonzero if anti-alias filter is enabled. + BOOL isAAFilterEnabled() const; + + /// Sets new target rate. Normal rate = 1.0, smaller values represent slower + /// rate, larger faster rates. + virtual void setRate(float newRate); + + /// Sets the number of channels, 1 = mono, 2 = stereo + void setChannels(int channels); + + /// Adds 'numSamples' pcs of samples from the 'samples' memory position into + /// the input of the object. + void putSamples(const SAMPLETYPE *samples, uint numSamples); + + /// Clears all the samples in the object + void clear(); + + /// Returns nonzero if there aren't any samples available for outputting. + int isEmpty() const; +}; + +} + +#endif diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/STTypes.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/STTypes.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/STTypes.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/STTypes.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,146 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Common type definitions for SoundTouch audio processing library. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-07-16 11:45:37 +0300 (Sat, 16 Jul 2011) $ +// File revision : $Revision: 3 $ +// +// $Id: STTypes.h 119 2011-07-16 08:45:37Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 STTypes_H +#define STTypes_H + +typedef unsigned int uint; +typedef unsigned long ulong; + +/* +#ifdef __GNUC__ + // In GCC, include soundtouch_config.h made by config scritps + #include "soundtouch_config.h" +#endif +*/ + +#ifndef _WINDEF_ + // if these aren't defined already by Windows headers, define now + + typedef int BOOL; + + #define FALSE 0 + #define TRUE 1 + +#endif // _WINDEF_ + + +namespace soundtouch +{ + /// Activate these undef's to overrule the possible sampletype + /// setting inherited from some other header file: + //#undef SOUNDTOUCH_INTEGER_SAMPLES + //#undef SOUNDTOUCH_FLOAT_SAMPLES + + #if !(SOUNDTOUCH_INTEGER_SAMPLES || SOUNDTOUCH_FLOAT_SAMPLES) + + /// Choose either 32bit floating point or 16bit integer sampletype + /// by choosing one of the following defines, unless this selection + /// has already been done in some other file. + //// + /// Notes: + /// - In Windows environment, choose the sample format with the + /// following defines. + /// - In GNU environment, the floating point samples are used by + /// default, but integer samples can be chosen by giving the + /// following switch to the configure script: + /// ./configure --enable-integer-samples + /// However, if you still prefer to select the sample format here + /// also in GNU environment, then please #undef the INTEGER_SAMPLE + /// and FLOAT_SAMPLE defines first as in comments above. + //#define SOUNDTOUCH_INTEGER_SAMPLES 1 //< 16bit integer samples + #define SOUNDTOUCH_FLOAT_SAMPLES 1 //< 32bit float samples + + #endif + + #if (WIN32 || __i386__ || __x86_64__) + /// Define this to allow X86-specific assembler/intrinsic optimizations. + /// Notice that library contains also usual C++ versions of each of these + /// these routines, so if you're having difficulties getting the optimized + /// routines compiled for whatever reason, you may disable these optimizations + /// to make the library compile. + + // #define SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS 1 + + #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 + + + #ifdef SOUNDTOUCH_INTEGER_SAMPLES + // 16bit integer sample type + typedef short SAMPLETYPE; + // data type for sample accumulation: Use 32bit integer to prevent overflows + typedef long LONG_SAMPLETYPE; + + #ifdef SOUNDTOUCH_FLOAT_SAMPLES + // check that only one sample type is defined + #error "conflicting sample types defined" + #endif // SOUNDTOUCH_FLOAT_SAMPLES + + #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS + // Allow MMX optimizations + #define SOUNDTOUCH_ALLOW_MMX 1 + #endif + + #else + + // floating point samples + typedef float SAMPLETYPE; + // data type for sample accumulation: Use double to utilize full precision. + typedef double LONG_SAMPLETYPE; + + #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS + // Allow SSE optimizations + #define SOUNDTOUCH_ALLOW_SSE 1 + #endif + + #endif // SOUNDTOUCH_INTEGER_SAMPLES +}; + + +// When this #define is active, eliminates a clicking sound when the "rate" or "pitch" +// parameter setting crosses from value <1 to >=1 or vice versa during processing. +// Default is off as such crossover is untypical case and involves a slight sound +// quality compromise. +//#define SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER 1 + +#endif diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/SoundTouch.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/SoundTouch.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/SoundTouch.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/SoundTouch.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,486 @@ +////////////////////////////////////////////////////////////////////////////// +/// +/// SoundTouch - main class for tempo/pitch/rate adjusting routines. +/// +/// Notes: +/// - Initialize the SoundTouch object instance by setting up the sound stream +/// parameters with functions 'setSampleRate' and 'setChannels', then set +/// desired tempo/pitch/rate settings with the corresponding functions. +/// +/// - The SoundTouch class behaves like a first-in-first-out pipeline: The +/// samples that are to be processed are fed into one of the pipe by calling +/// function 'putSamples', while the ready processed samples can be read +/// from the other end of the pipeline with function 'receiveSamples'. +/// +/// - The SoundTouch processing classes require certain sized 'batches' of +/// samples in order to process the sound. For this reason the classes buffer +/// incoming samples until there are enough of samples available for +/// processing, then they carry out the processing step and consequently +/// make the processed samples available for outputting. +/// +/// - For the above reason, the processing routines introduce a certain +/// 'latency' between the input and output, so that the samples input to +/// SoundTouch may not be immediately available in the output, and neither +/// the amount of outputtable samples may not immediately be in direct +/// relationship with the amount of previously input samples. +/// +/// - The tempo/pitch/rate control parameters can be altered during processing. +/// Please notice though that they aren't currently protected by semaphores, +/// so in multi-thread application external semaphore protection may be +/// required. +/// +/// - This class utilizes classes 'TDStretch' for tempo change (without modifying +/// pitch) and 'RateTransposer' for changing the playback rate (that is, both +/// tempo and pitch in the same ratio) of the sound. The third available control +/// 'pitch' (change pitch but maintain tempo) is produced by a combination of +/// combining the two other controls. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: SoundTouch.cpp 104 2011-02-13 19:13:57Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#include "SoundTouch.h" +#include "TDStretch.h" +#include "RateTransposer.h" +#include "cpu_detect.h" + +using namespace soundtouch; + +/// test if two floating point numbers are equal +#define TEST_FLOAT_EQUAL(a, b) (fabs(a - b) < 1e-10) + + +/// Print library version string for autoconf +extern "C" void soundtouch_ac_test() +{ + printf("SoundTouch Version: %s\n",SOUNDTOUCH_VERSION); +} + + +SoundTouch::SoundTouch() +{ + // Initialize rate transposer and tempo changer instances + + pRateTransposer = RateTransposer::newInstance(); + pTDStretch = TDStretch::newInstance(); + + setOutPipe(pTDStretch); + + rate = tempo = 0; + + virtualPitch = + virtualRate = + virtualTempo = 1.0; + + calcEffectiveRateAndTempo(); + + channels = 0; + bSrateSet = FALSE; +} + + + +SoundTouch::~SoundTouch() +{ + delete pRateTransposer; + delete pTDStretch; +} + + + +/// Get SoundTouch library version string +const char *SoundTouch::getVersionString() +{ + static const char *_version = SOUNDTOUCH_VERSION; + + return _version; +} + + +/// Get SoundTouch library version Id +uint SoundTouch::getVersionId() +{ + return SOUNDTOUCH_VERSION_ID; +} + + +// Sets the number of channels, 1 = mono, 2 = stereo +void SoundTouch::setChannels(uint numChannels) +{ + if (numChannels != 1 && numChannels != 2) + { + throw std::runtime_error("Illegal number of channels"); + } + channels = numChannels; + pRateTransposer->setChannels((int)numChannels); + pTDStretch->setChannels((int)numChannels); +} + + + +// Sets new rate control value. Normal rate = 1.0, smaller values +// represent slower rate, larger faster rates. +void SoundTouch::setRate(float newRate) +{ + virtualRate = newRate; + calcEffectiveRateAndTempo(); +} + + + +// Sets new rate control value as a difference in percents compared +// to the original rate (-50 .. +100 %) +void SoundTouch::setRateChange(float newRate) +{ + virtualRate = 1.0f + 0.01f * newRate; + calcEffectiveRateAndTempo(); +} + + + +// Sets new tempo control value. Normal tempo = 1.0, smaller values +// represent slower tempo, larger faster tempo. +void SoundTouch::setTempo(float newTempo) +{ + virtualTempo = newTempo; + calcEffectiveRateAndTempo(); +} + + + +// Sets new tempo control value as a difference in percents compared +// to the original tempo (-50 .. +100 %) +void SoundTouch::setTempoChange(float newTempo) +{ + virtualTempo = 1.0f + 0.01f * newTempo; + calcEffectiveRateAndTempo(); +} + + + +// Sets new pitch control value. Original pitch = 1.0, smaller values +// represent lower pitches, larger values higher pitch. +void SoundTouch::setPitch(float newPitch) +{ + virtualPitch = newPitch; + calcEffectiveRateAndTempo(); +} + + + +// Sets pitch change in octaves compared to the original pitch +// (-1.00 .. +1.00) +void SoundTouch::setPitchOctaves(float newPitch) +{ + virtualPitch = (float)exp(0.69314718056f * newPitch); + calcEffectiveRateAndTempo(); +} + + + +// Sets pitch change in semi-tones compared to the original pitch +// (-12 .. +12) +void SoundTouch::setPitchSemiTones(int newPitch) +{ + setPitchOctaves((float)newPitch / 12.0f); +} + + + +void SoundTouch::setPitchSemiTones(float newPitch) +{ + setPitchOctaves(newPitch / 12.0f); +} + + +// Calculates 'effective' rate and tempo values from the +// nominal control values. +void SoundTouch::calcEffectiveRateAndTempo() +{ + float oldTempo = tempo; + float oldRate = rate; + + tempo = virtualTempo / virtualPitch; + rate = virtualPitch * virtualRate; + + if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate); + if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo); + +#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER + if (rate <= 1.0f) + { + if (output != pTDStretch) + { + FIFOSamplePipe *tempoOut; + + assert(output == pRateTransposer); + // move samples in the current output buffer to the output of pTDStretch + tempoOut = pTDStretch->getOutput(); + tempoOut->moveSamples(*output); + // move samples in pitch transposer's store buffer to tempo changer's input + pTDStretch->moveSamples(*pRateTransposer->getStore()); + + output = pTDStretch; + } + } + else +#endif + { + if (output != pRateTransposer) + { + FIFOSamplePipe *transOut; + + assert(output == pTDStretch); + // move samples in the current output buffer to the output of pRateTransposer + transOut = pRateTransposer->getOutput(); + transOut->moveSamples(*output); + // move samples in tempo changer's input to pitch transposer's input + pRateTransposer->moveSamples(*pTDStretch->getInput()); + + output = pRateTransposer; + } + } +} + + +// Sets sample rate. +void SoundTouch::setSampleRate(uint srate) +{ + bSrateSet = TRUE; + // set sample rate, leave other tempo changer parameters as they are. + pTDStretch->setParameters((int)srate); +} + + +// Adds 'numSamples' pcs of samples from the 'samples' memory position into +// the input of the object. +void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples) +{ + if (bSrateSet == FALSE) + { + throw std::runtime_error("SoundTouch : Sample rate not defined"); + } + else if (channels == 0) + { + throw std::runtime_error("SoundTouch : Number of channels not defined"); + } + + // Transpose the rate of the new samples if necessary + /* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value... + if (rate == 1.0f) + { + // The rate value is same as the original, simply evaluate the tempo changer. + assert(output == pTDStretch); + if (pRateTransposer->isEmpty() == 0) + { + // yet flush the last samples in the pitch transposer buffer + // (may happen if 'rate' changes from a non-zero value to zero) + pTDStretch->moveSamples(*pRateTransposer); + } + pTDStretch->putSamples(samples, nSamples); + } + */ +#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER + else if (rate <= 1.0f) + { + // transpose the rate down, output the transposed sound to tempo changer buffer + assert(output == pTDStretch); + pRateTransposer->putSamples(samples, nSamples); + pTDStretch->moveSamples(*pRateTransposer); + } + else +#endif + { + // evaluate the tempo changer, then transpose the rate up, + assert(output == pRateTransposer); + pTDStretch->putSamples(samples, nSamples); + pRateTransposer->moveSamples(*pTDStretch); + } +} + + +// Flushes the last samples from the processing pipeline to the output. +// Clears also the internal processing buffers. +// +// Note: This function is meant for extracting the last samples of a sound +// 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. +void SoundTouch::flush() +{ + int i; + uint nOut; + SAMPLETYPE buff[128]; + + nOut = numSamples(); + + memset(buff, 0, 128 * sizeof(SAMPLETYPE)); + // "Push" the last active samples out from the processing pipeline by + // feeding blank samples into the processing pipeline until new, + // processed samples appear in the output (not however, more than + // 8ksamples in any case) + for (i = 0; i < 128; i ++) + { + putSamples(buff, 64); + if (numSamples() != nOut) break; // new samples have appeared in the output! + } + + // Clear working buffers + pRateTransposer->clear(); + pTDStretch->clearInput(); + // yet leave the 'tempoChanger' output intouched as that's where the + // flushed samples are! +} + + +// Changes a setting controlling the processing system behaviour. See the +// 'SETTING_...' defines for available setting ID's. +BOOL SoundTouch::setSetting(int settingId, int value) +{ + int sampleRate, sequenceMs, seekWindowMs, overlapMs; + + // read current tdstretch routine parameters + pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs); + + switch (settingId) + { + case SETTING_USE_AA_FILTER : + // enables / disabless anti-alias filter + pRateTransposer->enableAAFilter((value != 0) ? TRUE : FALSE); + return TRUE; + + case SETTING_AA_FILTER_LENGTH : + // sets anti-alias filter length + pRateTransposer->getAAFilter()->setLength(value); + return TRUE; + + case SETTING_USE_QUICKSEEK : + // enables / disables tempo routine quick seeking algorithm + pTDStretch->enableQuickSeek((value != 0) ? TRUE : FALSE); + return TRUE; + + case SETTING_SEQUENCE_MS: + // change time-stretch sequence duration parameter + pTDStretch->setParameters(sampleRate, value, seekWindowMs, overlapMs); + return TRUE; + + case SETTING_SEEKWINDOW_MS: + // change time-stretch seek window length parameter + pTDStretch->setParameters(sampleRate, sequenceMs, value, overlapMs); + return TRUE; + + case SETTING_OVERLAP_MS: + // change time-stretch overlap length parameter + pTDStretch->setParameters(sampleRate, sequenceMs, seekWindowMs, value); + return TRUE; + + default : + return FALSE; + } +} + + +// Reads a setting controlling the processing system behaviour. See the +// 'SETTING_...' defines for available setting ID's. +// +// Returns the setting value. +int SoundTouch::getSetting(int settingId) const +{ + int temp; + + switch (settingId) + { + case SETTING_USE_AA_FILTER : + return (uint)pRateTransposer->isAAFilterEnabled(); + + case SETTING_AA_FILTER_LENGTH : + return pRateTransposer->getAAFilter()->getLength(); + + case SETTING_USE_QUICKSEEK : + return (uint) pTDStretch->isQuickSeekEnabled(); + + case SETTING_SEQUENCE_MS: + pTDStretch->getParameters(NULL, &temp, NULL, NULL); + return temp; + + case SETTING_SEEKWINDOW_MS: + pTDStretch->getParameters(NULL, NULL, &temp, NULL); + return temp; + + case SETTING_OVERLAP_MS: + pTDStretch->getParameters(NULL, NULL, NULL, &temp); + return temp; + + case SETTING_NOMINAL_INPUT_SEQUENCE : + return pTDStretch->getInputSampleReq(); + + case SETTING_NOMINAL_OUTPUT_SEQUENCE : + return pTDStretch->getOutputBatchSize(); + + default : + return 0; + } +} + + +// Clears all the samples in the object's output and internal processing +// buffers. +void SoundTouch::clear() +{ + pRateTransposer->clear(); + pTDStretch->clear(); +} + + + +/// Returns number of samples currently unprocessed. +uint SoundTouch::numUnprocessedSamples() const +{ + FIFOSamplePipe * psp; + if (pTDStretch) + { + psp = pTDStretch->getInput(); + if (psp) + { + return psp->numSamples(); + } + } + return 0; +} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/SoundTouch.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/SoundTouch.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/SoundTouch.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/SoundTouch.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,277 @@ +////////////////////////////////////////////////////////////////////////////// +/// +/// SoundTouch - main class for tempo/pitch/rate adjusting routines. +/// +/// Notes: +/// - Initialize the SoundTouch object instance by setting up the sound stream +/// parameters with functions 'setSampleRate' and 'setChannels', then set +/// desired tempo/pitch/rate settings with the corresponding functions. +/// +/// - The SoundTouch class behaves like a first-in-first-out pipeline: The +/// samples that are to be processed are fed into one of the pipe by calling +/// function 'putSamples', while the ready processed samples can be read +/// from the other end of the pipeline with function 'receiveSamples'. +/// +/// - The SoundTouch processing classes require certain sized 'batches' of +/// samples in order to process the sound. For this reason the classes buffer +/// incoming samples until there are enough of samples available for +/// processing, then they carry out the processing step and consequently +/// make the processed samples available for outputting. +/// +/// - For the above reason, the processing routines introduce a certain +/// 'latency' between the input and output, so that the samples input to +/// SoundTouch may not be immediately available in the output, and neither +/// the amount of outputtable samples may not immediately be in direct +/// relationship with the amount of previously input samples. +/// +/// - The tempo/pitch/rate control parameters can be altered during processing. +/// Please notice though that they aren't currently protected by semaphores, +/// so in multi-thread application external semaphore protection may be +/// required. +/// +/// - This class utilizes classes 'TDStretch' for tempo change (without modifying +/// pitch) and 'RateTransposer' for changing the playback rate (that is, both +/// tempo and pitch in the same ratio) of the sound. The third available control +/// 'pitch' (change pitch but maintain tempo) is produced by a combination of +/// combining the two other controls. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-07-15 22:27:10 +0300 (Fri, 15 Jul 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: SoundTouch.h 107 2011-07-15 19:27:10Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 SoundTouch_H +#define SoundTouch_H + +#include "FIFOSamplePipe.h" +#include "STTypes.h" + +namespace soundtouch +{ + +/// Soundtouch library version string +#define SOUNDTOUCH_VERSION "1.6.0" + +/// SoundTouch library version id +#define SOUNDTOUCH_VERSION_ID (10600) + +// +// Available setting IDs for the 'setSetting' & 'get_setting' functions: + +/// Enable/disable anti-alias filter in pitch transposer (0 = disable) +#define SETTING_USE_AA_FILTER 0 + +/// Pitch transposer anti-alias filter length (8 .. 128 taps, default = 32) +#define SETTING_AA_FILTER_LENGTH 1 + +/// Enable/disable quick seeking algorithm in tempo changer routine +/// (enabling quick seeking lowers CPU utilization but causes a minor sound +/// quality compromising) +#define SETTING_USE_QUICKSEEK 2 + +/// Time-stretch algorithm single processing sequence length in milliseconds. This determines +/// to how long sequences the original sound is chopped in the time-stretch algorithm. +/// See "STTypes.h" or README for more information. +#define SETTING_SEQUENCE_MS 3 + +/// Time-stretch algorithm seeking window length in milliseconds for algorithm that finds the +/// best possible overlapping location. This determines from how wide window the algorithm +/// may look for an optimal joining location when mixing the sound sequences back together. +/// See "STTypes.h" or README for more information. +#define SETTING_SEEKWINDOW_MS 4 + +/// Time-stretch algorithm overlap length in milliseconds. When the chopped sound sequences +/// are mixed back together, to form a continuous sound stream, this parameter defines over +/// how long period the two consecutive sequences are let to overlap each other. +/// See "STTypes.h" or README for more information. +#define SETTING_OVERLAP_MS 5 + + +/// Call "getSetting" with this ID to query nominal average processing sequence +/// size in samples. This value tells approcimate value how many input samples +/// SoundTouch needs to gather before it does DSP processing run for the sample batch. +/// +/// Notices: +/// - This is read-only parameter, i.e. setSetting ignores this parameter +/// - Returned value is approximate average value, exact processing batch +/// size may wary from time to time +/// - This parameter value is not constant but may change depending on +/// tempo/pitch/rate/samplerate settings. +#define SETTING_NOMINAL_INPUT_SEQUENCE 6 + + +/// Call "getSetting" with this ID to query nominal average processing output +/// size in samples. This value tells approcimate value how many output samples +/// SoundTouch outputs once it does DSP processing run for a batch of input samples. +/// +/// Notices: +/// - This is read-only parameter, i.e. setSetting ignores this parameter +/// - Returned value is approximate average value, exact processing batch +/// size may wary from time to time +/// - This parameter value is not constant but may change depending on +/// tempo/pitch/rate/samplerate settings. +#define SETTING_NOMINAL_OUTPUT_SEQUENCE 7 + +class SoundTouch : public FIFOProcessor +{ +private: + /// Rate transposer class instance + class RateTransposer *pRateTransposer; + + /// Time-stretch class instance + class TDStretch *pTDStretch; + + /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters. + float virtualRate; + + /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters. + float virtualTempo; + + /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters. + float virtualPitch; + + /// Flag: Has sample rate been set? + BOOL bSrateSet; + + /// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and + /// 'virtualPitch' parameters. + void calcEffectiveRateAndTempo(); + +protected : + /// Number of channels + uint channels; + + /// Effective 'rate' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch' + float rate; + + /// Effective 'tempo' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch' + float tempo; + +public: + SoundTouch(); + virtual ~SoundTouch(); + + /// Get SoundTouch library version string + static const char *getVersionString(); + + /// Get SoundTouch library version Id + static uint getVersionId(); + + /// Sets new rate control value. Normal rate = 1.0, smaller values + /// represent slower rate, larger faster rates. + void setRate(float newRate); + + /// Sets new tempo control value. Normal tempo = 1.0, smaller values + /// represent slower tempo, larger faster tempo. + void setTempo(float newTempo); + + /// Sets new rate control value as a difference in percents compared + /// to the original rate (-50 .. +100 %) + void setRateChange(float newRate); + + /// Sets new tempo control value as a difference in percents compared + /// to the original tempo (-50 .. +100 %) + void setTempoChange(float newTempo); + + /// Sets new pitch control value. Original pitch = 1.0, smaller values + /// represent lower pitches, larger values higher pitch. + void setPitch(float newPitch); + + /// Sets pitch change in octaves compared to the original pitch + /// (-1.00 .. +1.00) + void setPitchOctaves(float newPitch); + + /// Sets pitch change in semi-tones compared to the original pitch + /// (-12 .. +12) + void setPitchSemiTones(int newPitch); + void setPitchSemiTones(float newPitch); + + /// Sets the number of channels, 1 = mono, 2 = stereo + void setChannels(uint numChannels); + + /// Sets sample rate. + void setSampleRate(uint srate); + + /// Flushes the last samples from the processing pipeline to the output. + /// Clears also the internal processing buffers. + // + /// Note: This function is meant for extracting the last samples of a sound + /// 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. + void flush(); + + /// 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. + virtual void putSamples( + const SAMPLETYPE *samples, ///< Pointer to sample buffer. + uint numSamples ///< Number of samples in buffer. Notice + ///< that in case of stereo-sound a single sample + ///< contains data for both channels. + ); + + /// Clears all the samples in the object's output and internal processing + /// buffers. + virtual void clear(); + + /// Changes a setting controlling the processing system behaviour. See the + /// 'SETTING_...' defines for available setting ID's. + /// + /// \return 'TRUE' if the setting was succesfully changed + BOOL setSetting(int settingId, ///< Setting ID number. see SETTING_... defines. + int value ///< New setting value. + ); + + /// Reads a setting controlling the processing system behaviour. See the + /// 'SETTING_...' defines for available setting ID's. + /// + /// \return the setting value. + int getSetting(int settingId ///< Setting ID number, see SETTING_... defines. + ) const; + + /// Returns number of samples currently unprocessed. + virtual uint numUnprocessedSamples() const; + + + /// Other handy functions that are implemented in the ancestor classes (see + /// classes 'FIFOProcessor' and 'FIFOSamplePipe') + /// + /// - receiveSamples() : Use this function to receive 'ready' processed samples from SoundTouch. + /// - numSamples() : Get number of 'ready' samples that can be received with + /// function 'receiveSamples()' + /// - isEmpty() : Returns nonzero if there aren't any 'ready' samples. + /// - clear() : Clears all samples from ready/processing buffers. +}; + +} +#endif diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/TDStretch.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/TDStretch.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/TDStretch.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/TDStretch.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,1026 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo +/// while maintaining the original pitch by using a time domain WSOLA-like +/// method with several performance-increasing tweaks. +/// +/// Note : MMX optimized functions reside in a separate, platform-specific +/// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp' +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $ +// File revision : $Revision: 1.12 $ +// +// $Id: TDStretch.cpp 104 2011-02-13 19:13:57Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#include "STTypes.h" +#include "cpu_detect.h" +#include "TDStretch.h" + +#include + +using namespace soundtouch; + +#define max(x, y) (((x) > (y)) ? (x) : (y)) + + +/***************************************************************************** + * + * Constant definitions + * + *****************************************************************************/ + +// Table for the hierarchical mixing position seeking algorithm +static 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' + * + *****************************************************************************/ + + +TDStretch::TDStretch() : FIFOProcessor(&outputBuffer) +{ + bQuickSeek = FALSE; + channels = 2; + + pMidBuffer = NULL; + pRefMidBufferUnaligned = NULL; + overlapLength = 0; + + bAutoSeqSetting = TRUE; + bAutoSeekSetting = TRUE; + +// outDebt = 0; + skipFract = 0; + + tempo = 1.0f; + setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS); + setTempo(1.0f); + + clear(); +} + + + +TDStretch::~TDStretch() +{ + delete[] pMidBuffer; + delete[] pRefMidBufferUnaligned; +} + + + +// Sets routine control parameters. These control are certain time constants +// defining how the sound is stretched to the desired duration. +// +// 'sampleRate' = sample rate of the sound +// 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms) +// 'seekwindowMS' = seeking window length for scanning the best overlapping +// position (default = 28 ms) +// 'overlapMS' = overlapping length (default = 12 ms) + +void TDStretch::setParameters(int aSampleRate, int aSequenceMS, + int aSeekWindowMS, int aOverlapMS) +{ + // accept only positive parameter values - if zero or negative, use old values instead + if (aSampleRate > 0) this->sampleRate = aSampleRate; + if (aOverlapMS > 0) this->overlapMs = aOverlapMS; + + if (aSequenceMS > 0) + { + this->sequenceMs = aSequenceMS; + bAutoSeqSetting = FALSE; + } + else if (aSequenceMS == 0) + { + // if zero, use automatic setting + bAutoSeqSetting = TRUE; + } + + if (aSeekWindowMS > 0) + { + this->seekWindowMs = aSeekWindowMS; + bAutoSeekSetting = FALSE; + } + else if (aSeekWindowMS == 0) + { + // if zero, use automatic setting + bAutoSeekSetting = TRUE; + } + + calcSeqParameters(); + + calculateOverlapLength(overlapMs); + + // set tempo to recalculate 'sampleReq' + setTempo(tempo); + +} + + + +/// Get routine control parameters, see setParameters() function. +/// Any of the parameters to this function can be NULL, in such case corresponding parameter +/// value isn't returned. +void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const +{ + if (pSampleRate) + { + *pSampleRate = sampleRate; + } + + if (pSequenceMs) + { + *pSequenceMs = (bAutoSeqSetting) ? (USE_AUTO_SEQUENCE_LEN) : sequenceMs; + } + + if (pSeekWindowMs) + { + *pSeekWindowMs = (bAutoSeekSetting) ? (USE_AUTO_SEEKWINDOW_LEN) : seekWindowMs; + } + + if (pOverlapMs) + { + *pOverlapMs = overlapMs; + } +} + + +// Overlaps samples in 'midBuffer' with the samples in 'pInput' +void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const +{ + int i, itemp; + + for (i = 0; i < overlapLength ; i ++) + { + itemp = overlapLength - i; + pOutput[i] = (pInput[i] * i + pMidBuffer[i] * itemp ) / overlapLength; // >> overlapDividerBits; + } +} + + + +void TDStretch::clearMidBuffer() +{ + memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength); +} + + +void TDStretch::clearInput() +{ + inputBuffer.clear(); + clearMidBuffer(); +} + + +// Clears the sample buffers +void TDStretch::clear() +{ + outputBuffer.clear(); + clearInput(); +} + + + +// Enables/disables the quick position seeking algorithm. Zero to disable, nonzero +// to enable +void TDStretch::enableQuickSeek(BOOL enable) +{ + bQuickSeek = enable; +} + + +// Returns nonzero if the quick seeking algorithm is enabled. +BOOL TDStretch::isQuickSeekEnabled() const +{ + return bQuickSeek; +} + + +// Seeks for the optimal overlap-mixing position. +int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos) +{ + if (channels == 2) + { + // stereo sound + if (bQuickSeek) + { + return seekBestOverlapPositionStereoQuick(refPos); + } + else + { + return seekBestOverlapPositionStereo(refPos); + } + } + else + { + // mono sound + if (bQuickSeek) + { + return seekBestOverlapPositionMonoQuick(refPos); + } + else + { + return seekBestOverlapPositionMono(refPos); + } + } +} + + + + +// Overlaps samples in 'midBuffer' with the samples in 'pInputBuffer' at position +// of 'ovlPos'. +inline void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, uint ovlPos) const +{ + if (channels == 2) + { + // stereo sound + overlapStereo(pOutput, pInput + 2 * ovlPos); + } else { + // mono sound. + overlapMono(pOutput, pInput + ovlPos); + } +} + + + + +// Seeks for the optimal overlap-mixing position. The 'stereo' version of the +// routine +// +// The best position is determined as the position where the two overlapped +// sample sequences are 'most alike', in terms of the highest cross-correlation +// value over the overlapping period +int TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos) +{ + int bestOffs; + double bestCorr, corr; + int i; + + // Slopes the amplitudes of the 'midBuffer' samples + precalcCorrReferenceStereo(); + + bestCorr = FLT_MIN; + bestOffs = 0; + + // Scans for the best correlation value by testing each possible position + // over the permitted range. + for (i = 0; i < seekLength; i ++) + { + // Calculates correlation value for the mixing position corresponding + // to 'i' + corr = (double)calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer); + // heuristic rule to slightly favour values close to mid of the range + double tmp = (double)(2 * i - seekLength) / (double)seekLength; + corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); + + // Checks for the highest correlation value + if (corr > bestCorr) + { + bestCorr = corr; + bestOffs = i; + } + } + // clear cross correlation routine state if necessary (is so e.g. in MMX routines). + clearCrossCorrState(); + + return bestOffs; +} + + +// Seeks for the optimal overlap-mixing position. The 'stereo' version of the +// routine +// +// The best position is determined as the position where the two overlapped +// sample sequences are 'most alike', in terms of the highest cross-correlation +// value over the overlapping period +int TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos) +{ + int j; + int bestOffs; + double bestCorr, corr; + int scanCount, corrOffset, tempOffset; + + // Slopes the amplitude of the 'midBuffer' samples + precalcCorrReferenceStereo(); + + bestCorr = FLT_MIN; + bestOffs = _scanOffsets[0][0]; + corrOffset = 0; + tempOffset = 0; + + // Scans for the best correlation value using four-pass hierarchical search. + // + // The look-up table 'scans' has hierarchical position adjusting steps. + // In first pass the routine searhes for the highest correlation with + // relatively coarse steps, then rescans the neighbourhood of the highest + // correlation with better resolution and so on. + for (scanCount = 0;scanCount < 4; scanCount ++) + { + j = 0; + while (_scanOffsets[scanCount][j]) + { + tempOffset = corrOffset + _scanOffsets[scanCount][j]; + if (tempOffset >= seekLength) break; + + // Calculates correlation value for the mixing position corresponding + // to 'tempOffset' + corr = (double)calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer); + // heuristic rule to slightly favour values close to mid of the range + double tmp = (double)(2 * tempOffset - seekLength) / seekLength; + corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); + + // Checks for the highest correlation value + if (corr > bestCorr) + { + bestCorr = corr; + bestOffs = tempOffset; + } + j ++; + } + corrOffset = bestOffs; + } + // clear cross correlation routine state if necessary (is so e.g. in MMX routines). + clearCrossCorrState(); + + return bestOffs; +} + + + +// Seeks for the optimal overlap-mixing position. The 'mono' version of the +// routine +// +// The best position is determined as the position where the two overlapped +// sample sequences are 'most alike', in terms of the highest cross-correlation +// value over the overlapping period +int TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos) +{ + int bestOffs; + double bestCorr, corr; + int tempOffset; + const SAMPLETYPE *compare; + + // Slopes the amplitude of the 'midBuffer' samples + precalcCorrReferenceMono(); + + bestCorr = FLT_MIN; + bestOffs = 0; + + // Scans for the best correlation value by testing each possible position + // over the permitted range. + for (tempOffset = 0; tempOffset < seekLength; tempOffset ++) + { + compare = refPos + tempOffset; + + // Calculates correlation value for the mixing position corresponding + // to 'tempOffset' + corr = (double)calcCrossCorrMono(pRefMidBuffer, compare); + // heuristic rule to slightly favour values close to mid of the range + double tmp = (double)(2 * tempOffset - seekLength) / seekLength; + corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); + + // Checks for the highest correlation value + if (corr > bestCorr) + { + bestCorr = corr; + bestOffs = tempOffset; + } + } + // clear cross correlation routine state if necessary (is so e.g. in MMX routines). + clearCrossCorrState(); + + return bestOffs; +} + + +// Seeks for the optimal overlap-mixing position. The 'mono' version of the +// routine +// +// The best position is determined as the position where the two overlapped +// sample sequences are 'most alike', in terms of the highest cross-correlation +// value over the overlapping period +int TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos) +{ + int j; + int bestOffs; + double bestCorr, corr; + int scanCount, corrOffset, tempOffset; + + // Slopes the amplitude of the 'midBuffer' samples + precalcCorrReferenceMono(); + + bestCorr = FLT_MIN; + bestOffs = _scanOffsets[0][0]; + corrOffset = 0; + tempOffset = 0; + + // Scans for the best correlation value using four-pass hierarchical search. + // + // The look-up table 'scans' has hierarchical position adjusting steps. + // In first pass the routine searhes for the highest correlation with + // relatively coarse steps, then rescans the neighbourhood of the highest + // correlation with better resolution and so on. + for (scanCount = 0;scanCount < 4; scanCount ++) + { + j = 0; + while (_scanOffsets[scanCount][j]) + { + tempOffset = corrOffset + _scanOffsets[scanCount][j]; + if (tempOffset >= seekLength) break; + + // Calculates correlation value for the mixing position corresponding + // to 'tempOffset' + corr = (double)calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer); + // heuristic rule to slightly favour values close to mid of the range + double tmp = (double)(2 * tempOffset - seekLength) / seekLength; + corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); + + // Checks for the highest correlation value + if (corr > bestCorr) + { + bestCorr = corr; + bestOffs = tempOffset; + } + j ++; + } + corrOffset = bestOffs; + } + // clear cross correlation routine state if necessary (is so e.g. in MMX routines). + clearCrossCorrState(); + + return bestOffs; +} + + +/// clear cross correlation routine state if necessary +void TDStretch::clearCrossCorrState() +{ + // default implementation is empty. +} + + +/// Calculates processing sequence length according to tempo setting +void TDStretch::calcSeqParameters() +{ + // Adjust tempo param according to tempo, so that variating processing sequence length is used + // at varius tempo settings, between the given low...top limits + #define AUTOSEQ_TEMPO_LOW 0.5 // auto setting low tempo range (-50%) + #define AUTOSEQ_TEMPO_TOP 2.0 // auto setting top tempo range (+100%) + + // sequence-ms setting values at above low & top tempo + #define AUTOSEQ_AT_MIN 125.0 + #define AUTOSEQ_AT_MAX 50.0 + #define AUTOSEQ_K ((AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW)) + #define AUTOSEQ_C (AUTOSEQ_AT_MIN - (AUTOSEQ_K) * (AUTOSEQ_TEMPO_LOW)) + + // seek-window-ms setting values at above low & top tempo + #define AUTOSEEK_AT_MIN 25.0 + #define AUTOSEEK_AT_MAX 15.0 + #define AUTOSEEK_K ((AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW)) + #define AUTOSEEK_C (AUTOSEEK_AT_MIN - (AUTOSEEK_K) * (AUTOSEQ_TEMPO_LOW)) + + #define CHECK_LIMITS(x, mi, ma) (((x) < (mi)) ? (mi) : (((x) > (ma)) ? (ma) : (x))) + + double seq, seek; + + if (bAutoSeqSetting) + { + seq = AUTOSEQ_C + AUTOSEQ_K * tempo; + seq = CHECK_LIMITS(seq, AUTOSEQ_AT_MAX, AUTOSEQ_AT_MIN); + sequenceMs = (int)(seq + 0.5); + } + + if (bAutoSeekSetting) + { + seek = AUTOSEEK_C + AUTOSEEK_K * tempo; + seek = CHECK_LIMITS(seek, AUTOSEEK_AT_MAX, AUTOSEEK_AT_MIN); + seekWindowMs = (int)(seek + 0.5); + } + + // Update seek window lengths + seekWindowLength = (sampleRate * sequenceMs) / 1000; + if (seekWindowLength < 2 * overlapLength) + { + seekWindowLength = 2 * overlapLength; + } + seekLength = (sampleRate * seekWindowMs) / 1000; +} + + + +// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower +// tempo, larger faster tempo. +void TDStretch::setTempo(float newTempo) +{ + int intskip; + + tempo = newTempo; + + // Calculate new sequence duration + calcSeqParameters(); + + // Calculate ideal skip length (according to tempo value) + nominalSkip = tempo * (seekWindowLength - overlapLength); + intskip = (int)(nominalSkip + 0.5f); + + // Calculate how many samples are needed in the 'inputBuffer' to + // process another batch of samples + //sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength / 2; + sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength; +} + + + +// Sets the number of channels, 1 = mono, 2 = stereo +void TDStretch::setChannels(int numChannels) +{ + assert(numChannels > 0); + if (channels == numChannels) return; + assert(numChannels == 1 || numChannels == 2); + + channels = numChannels; + inputBuffer.setChannels(channels); + outputBuffer.setChannels(channels); +} + + +// nominal tempo, no need for processing, just pass the samples through +// to outputBuffer +/* +void TDStretch::processNominalTempo() +{ + assert(tempo == 1.0f); + + if (bMidBufferDirty) + { + // If there are samples in pMidBuffer waiting for overlapping, + // do a single sliding overlapping with them in order to prevent a + // clicking distortion in the output sound + if (inputBuffer.numSamples() < overlapLength) + { + // wait until we've got overlapLength input samples + return; + } + // Mix the samples in the beginning of 'inputBuffer' with the + // samples in 'midBuffer' using sliding overlapping + overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0); + outputBuffer.putSamples(overlapLength); + inputBuffer.receiveSamples(overlapLength); + clearMidBuffer(); + // now we've caught the nominal sample flow and may switch to + // bypass mode + } + + // Simply bypass samples from input to output + outputBuffer.moveSamples(inputBuffer); +} +*/ + +#include + +// Processes as many processing frames of the samples 'inputBuffer', store +// the result into 'outputBuffer' +void TDStretch::processSamples() +{ + int ovlSkip, offset; + int temp; + + /* Removed this small optimization - can introduce a click to sound when tempo setting + crosses the nominal value + if (tempo == 1.0f) + { + // tempo not changed from the original, so bypass the processing + processNominalTempo(); + return; + } + */ + + // Process samples as long as there are enough samples in 'inputBuffer' + // to form a processing frame. + while ((int)inputBuffer.numSamples() >= sampleReq) + { + // If tempo differs from the normal ('SCALE'), scan for the best overlapping + // position + offset = seekBestOverlapPosition(inputBuffer.ptrBegin()); + + // Mix the samples in the 'inputBuffer' at position of 'offset' with the + // samples in 'midBuffer' using sliding overlapping + // ... first partially overlap with the end of the previous sequence + // (that's in 'midBuffer') + overlap(outputBuffer.ptrEnd((uint)overlapLength), inputBuffer.ptrBegin(), (uint)offset); + outputBuffer.putSamples((uint)overlapLength); + + // ... then copy sequence samples from 'inputBuffer' to output: + + // length of sequence + temp = (seekWindowLength - 2 * overlapLength); + + // crosscheck that we don't have buffer overflow... + if ((int)inputBuffer.numSamples() < (offset + temp + overlapLength * 2)) + { + continue; // just in case, shouldn't really happen + } + + outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), (uint)temp); + + // Copies the end of the current sequence from 'inputBuffer' to + // 'midBuffer' for being mixed with the beginning of the next + // processing sequence and so on + assert((offset + temp + overlapLength * 2) <= (int)inputBuffer.numSamples()); + memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + temp + overlapLength), + channels * sizeof(SAMPLETYPE) * overlapLength); + + // Remove the processed samples from the input buffer. Update + // the difference between integer & nominal skip step to 'skipFract' + // in order to prevent the error from accumulating over time. + skipFract += nominalSkip; // real skip size + ovlSkip = (int)skipFract; // rounded to integer skip + skipFract -= ovlSkip; // maintain the fraction part, i.e. real vs. integer skip + inputBuffer.receiveSamples((uint)ovlSkip); + } +} + + +// Adds 'numsamples' pcs of samples from the 'samples' memory position into +// the input of the object. +void TDStretch::putSamples(const SAMPLETYPE *samples, uint nSamples) +{ + // Add the samples into the input buffer + inputBuffer.putSamples(samples, nSamples); + // Process the samples in input buffer + processSamples(); +} + + + +/// Set new overlap length parameter & reallocate RefMidBuffer if necessary. +void TDStretch::acceptNewOverlapLength(int newOverlapLength) +{ + int prevOvl; + + assert(newOverlapLength >= 0); + prevOvl = overlapLength; + overlapLength = newOverlapLength; + + if (overlapLength > prevOvl) + { + delete[] pMidBuffer; + delete[] pRefMidBufferUnaligned; + + pMidBuffer = new SAMPLETYPE[overlapLength * 2]; + clearMidBuffer(); + + pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)]; + // ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency + pRefMidBuffer = (SAMPLETYPE *)((((ulong)pRefMidBufferUnaligned) + 15) & (ulong)-16); + } +} + + +// 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) +{ + // Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead! + throw std::runtime_error("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!"); + return NULL; +} + + +TDStretch * TDStretch::newInstance() +{ + uint uExtensions; + + uExtensions = detectCPUextensions(); + + // Check if MMX/SSE instruction set extensions supported by CPU + +#ifdef SOUNDTOUCH_ALLOW_MMX + // MMX routines available only with integer sample types + if (uExtensions & SUPPORT_MMX) + { + return ::new TDStretchMMX; + } + else +#endif // SOUNDTOUCH_ALLOW_MMX + + +#ifdef SOUNDTOUCH_ALLOW_SSE + if (uExtensions & SUPPORT_SSE) + { + // SSE support + return ::new TDStretchSSE; + } + else +#endif // SOUNDTOUCH_ALLOW_SSE + + { + // ISA optimizations not supported, use plain C version + return ::new TDStretch; + } +} + + +////////////////////////////////////////////////////////////////////////////// +// +// Integer arithmetics specific algorithm implementations. +// +////////////////////////////////////////////////////////////////////////////// + +#ifdef SOUNDTOUCH_INTEGER_SAMPLES + +// Slopes the amplitude of the 'midBuffer' samples so that cross correlation +// is faster to calculate +void TDStretch::precalcCorrReferenceStereo() +{ + int i, cnt2; + int temp, temp2; + + for (i=0 ; i < (int)overlapLength ;i ++) + { + temp = i * (overlapLength - i); + cnt2 = i * 2; + + temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider; + pRefMidBuffer[cnt2] = (short)(temp2); + temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider; + pRefMidBuffer[cnt2 + 1] = (short)(temp2); + } +} + + +// Slopes the amplitude of the 'midBuffer' samples so that cross correlation +// is faster to calculate +void TDStretch::precalcCorrReferenceMono() +{ + int i; + long temp; + long temp2; + + for (i=0 ; i < (int)overlapLength ;i ++) + { + temp = i * (overlapLength - i); + temp2 = (pMidBuffer[i] * temp) / slopingDivider; + pRefMidBuffer[i] = (short)temp2; + } +} + + +// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo' +// version of the routine. +void TDStretch::overlapStereo(short *poutput, const short *input) const +{ + int i; + short temp; + int cnt2; + + for (i = 0; i < overlapLength ; i ++) + { + temp = (short)(overlapLength - i); + cnt2 = 2 * i; + poutput[cnt2] = (input[cnt2] * i + pMidBuffer[cnt2] * temp ) / overlapLength; + poutput[cnt2 + 1] = (input[cnt2 + 1] * i + pMidBuffer[cnt2 + 1] * temp ) / overlapLength; + } +} + +// Calculates the x having the closest 2^x value for the given value +static int _getClosest2Power(double value) +{ + return (int)(log(value) / log(2.0) + 0.5); +} + + +/// Calculates overlap period length in samples. +/// Integer version rounds overlap length to closest power of 2 +/// for a divide scaling operation. +void TDStretch::calculateOverlapLength(int aoverlapMs) +{ + int newOvl; + + assert(aoverlapMs >= 0); + + // calculate overlap length so that it's power of 2 - thus it's easy to do + // integer division by right-shifting. Term "-1" at end is to account for + // the extra most significatnt bit left unused in result by signed multiplication + overlapDividerBits = _getClosest2Power((sampleRate * aoverlapMs) / 1000.0) - 1; + if (overlapDividerBits > 9) overlapDividerBits = 9; + if (overlapDividerBits < 3) overlapDividerBits = 3; + newOvl = (int)pow(2.0, (int)overlapDividerBits + 1); // +1 => account for -1 above + + acceptNewOverlapLength(newOvl); + + // calculate sloping divider so that crosscorrelation operation won't + // overflow 32-bit register. Max. sum of the crosscorrelation sum without + // divider would be 2^30*(N^3-N)/3, where N = overlap length + slopingDivider = (newOvl * newOvl - 1) / 3; +} + + +long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const +{ + long corr; + long norm; + int i; + + corr = norm = 0; + for (i = 1; i < overlapLength; i ++) + { + corr += (mixingPos[i] * compare[i]) >> overlapDividerBits; + norm += (mixingPos[i] * mixingPos[i]) >> overlapDividerBits; + } + + // Normalize result by dividing by sqrt(norm) - this step is easiest + // done using floating point operation + if (norm == 0) norm = 1; // to avoid div by zero + return (long)((double)corr * SHRT_MAX / sqrt((double)norm)); +} + + +long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const +{ + long corr; + long norm; + int i; + + corr = norm = 0; + for (i = 2; i < 2 * overlapLength; i += 2) + { + corr += (mixingPos[i] * compare[i] + + mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits; + norm += (mixingPos[i] * mixingPos[i] + mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBits; + } + + // Normalize result by dividing by sqrt(norm) - this step is easiest + // done using floating point operation + if (norm == 0) norm = 1; // to avoid div by zero + return (long)((double)corr * SHRT_MAX / sqrt((double)norm)); +} + +#endif // SOUNDTOUCH_INTEGER_SAMPLES + +////////////////////////////////////////////////////////////////////////////// +// +// Floating point arithmetics specific algorithm implementations. +// + +#ifdef SOUNDTOUCH_FLOAT_SAMPLES + + +// Slopes the amplitude of the 'midBuffer' samples so that cross correlation +// is faster to calculate +void TDStretch::precalcCorrReferenceStereo() +{ + int i, cnt2; + float temp; + + for (i=0 ; i < (int)overlapLength ;i ++) + { + temp = (float)i * (float)(overlapLength - i); + cnt2 = i * 2; + pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp); + pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp); + } +} + + +// Slopes the amplitude of the 'midBuffer' samples so that cross correlation +// is faster to calculate +void TDStretch::precalcCorrReferenceMono() +{ + int i; + float temp; + + for (i=0 ; i < (int)overlapLength ;i ++) + { + temp = (float)i * (float)(overlapLength - i); + pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp); + } +} + + +// Overlaps samples in 'midBuffer' with the samples in 'pInput' +void TDStretch::overlapStereo(float *pOutput, const float *pInput) const +{ + int i; + int cnt2; + float fTemp; + float fScale; + float fi; + + fScale = 1.0f / (float)overlapLength; + + for (i = 0; i < (int)overlapLength ; i ++) + { + fTemp = (float)(overlapLength - i) * fScale; + fi = (float)i * fScale; + cnt2 = 2 * i; + pOutput[cnt2 + 0] = pInput[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp; + pOutput[cnt2 + 1] = pInput[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp; + } +} + + +/// Calculates overlapInMsec period length in samples. +void TDStretch::calculateOverlapLength(int overlapInMsec) +{ + int newOvl; + + assert(overlapInMsec >= 0); + newOvl = (sampleRate * overlapInMsec) / 1000; + if (newOvl < 16) newOvl = 16; + + // must be divisible by 8 + newOvl -= newOvl % 8; + + acceptNewOverlapLength(newOvl); +} + + + +double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const +{ + double corr; + double norm; + int i; + + corr = norm = 0; + for (i = 1; i < overlapLength; i ++) + { + corr += mixingPos[i] * compare[i]; + norm += mixingPos[i] * mixingPos[i]; + } + + if (norm < 1e-9) norm = 1.0; // to avoid div by zero + return corr / sqrt(norm); +} + + +double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const +{ + double corr; + double norm; + int i; + + corr = norm = 0; + for (i = 2; i < 2 * overlapLength; i += 2) + { + corr += mixingPos[i] * compare[i] + + mixingPos[i + 1] * compare[i + 1]; + norm += mixingPos[i] * mixingPos[i] + + mixingPos[i + 1] * mixingPos[i + 1]; + } + + if (norm < 1e-9) norm = 1.0; // to avoid div by zero + return corr / sqrt(norm); +} + +#endif // SOUNDTOUCH_FLOAT_SAMPLES diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/TDStretch.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/TDStretch.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/TDStretch.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/TDStretch.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,277 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo +/// while maintaining the original pitch by using a time domain WSOLA-like method +/// with several performance-increasing tweaks. +/// +/// Note : MMX/SSE optimized functions reside in separate, platform-specific files +/// 'mmx_optimized.cpp' and 'sse_optimized.cpp' +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: TDStretch.h 104 2011-02-13 19:13:57Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 TDStretch_H +#define TDStretch_H + +#include +#include "STTypes.h" +#include "RateTransposer.h" +#include "FIFOSamplePipe.h" + +namespace soundtouch +{ + +/// Default values for sound processing parameters: +/// Notice that the default parameters are tuned for contemporary popular music +/// processing. For speech processing applications these parameters suit better: +/// #define DEFAULT_SEQUENCE_MS 40 +/// #define DEFAULT_SEEKWINDOW_MS 15 +/// #define DEFAULT_OVERLAP_MS 8 +/// + +/// Default length of a single processing sequence, in milliseconds. This determines to how +/// long sequences the original sound is chopped in the time-stretch algorithm. +/// +/// The larger this value is, the lesser sequences are used in processing. In principle +/// a bigger value sounds better when slowing down tempo, but worse when increasing tempo +/// and vice versa. +/// +/// Increasing this value reduces computational burden & vice versa. +//#define DEFAULT_SEQUENCE_MS 40 +#define DEFAULT_SEQUENCE_MS USE_AUTO_SEQUENCE_LEN + +/// Giving this value for the sequence length sets automatic parameter value +/// according to tempo setting (recommended) +#define USE_AUTO_SEQUENCE_LEN 0 + +/// Seeking window default length in milliseconds for algorithm that finds the best possible +/// overlapping location. This determines from how wide window the algorithm may look for an +/// optimal joining location when mixing the sound sequences back together. +/// +/// The bigger this window setting is, the higher the possibility to find a better mixing +/// position will become, but at the same time large values may cause a "drifting" artifact +/// because consequent sequences will be taken at more uneven intervals. +/// +/// If there's a disturbing artifact that sounds as if a constant frequency was drifting +/// around, try reducing this setting. +/// +/// Increasing this value increases computational burden & vice versa. +//#define DEFAULT_SEEKWINDOW_MS 15 +#define DEFAULT_SEEKWINDOW_MS USE_AUTO_SEEKWINDOW_LEN + +/// Giving this value for the seek window length sets automatic parameter value +/// according to tempo setting (recommended) +#define USE_AUTO_SEEKWINDOW_LEN 0 + +/// Overlap length in milliseconds. When the chopped sound sequences are mixed back together, +/// to form a continuous sound stream, this parameter defines over how long period the two +/// consecutive sequences are let to overlap each other. +/// +/// 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. +/// +/// Increasing this value increases computational burden & vice versa. +#define DEFAULT_OVERLAP_MS 8 + + +/// Class that does the time-stretch (tempo change) effect for the processed +/// sound. +class TDStretch : public FIFOProcessor +{ +protected: + int channels; + int sampleReq; + float tempo; + + SAMPLETYPE *pMidBuffer; + SAMPLETYPE *pRefMidBuffer; + SAMPLETYPE *pRefMidBufferUnaligned; + int overlapLength; + int seekLength; + int seekWindowLength; + int overlapDividerBits; + int slopingDivider; + float nominalSkip; + float skipFract; + FIFOSampleBuffer outputBuffer; + FIFOSampleBuffer inputBuffer; + BOOL bQuickSeek; +// int outDebt; +// BOOL bMidBufferDirty; + + int sampleRate; + int sequenceMs; + int seekWindowMs; + int overlapMs; + BOOL bAutoSeqSetting; + BOOL bAutoSeekSetting; + + void acceptNewOverlapLength(int newOverlapLength); + + virtual void clearCrossCorrState(); + void calculateOverlapLength(int overlapMs); + + virtual LONG_SAMPLETYPE calcCrossCorrStereo(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const; + virtual LONG_SAMPLETYPE calcCrossCorrMono(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const; + + virtual int seekBestOverlapPositionStereo(const SAMPLETYPE *refPos); + virtual int seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos); + virtual int seekBestOverlapPositionMono(const SAMPLETYPE *refPos); + virtual int seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos); + int seekBestOverlapPosition(const SAMPLETYPE *refPos); + + virtual void overlapStereo(SAMPLETYPE *output, const SAMPLETYPE *input) const; + virtual void overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const; + + void clearMidBuffer(); + void overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const; + + void precalcCorrReferenceMono(); + void precalcCorrReferenceStereo(); + + void calcSeqParameters(); + + /// Changes the tempo of the given sound samples. + /// Returns amount of samples returned in the "output" buffer. + /// The maximum amount of samples that can be returned at a time is set by + /// the 'set_returnBuffer_size' function. + void processSamples(); + +public: + TDStretch(); + virtual ~TDStretch(); + + /// 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. + static void *operator new(size_t s); + + /// Use this function instead of "new" operator to create a new instance of this class. + /// This function automatically chooses a correct feature set depending on if the CPU + /// supports MMX/SSE/etc extensions. + static TDStretch *newInstance(); + + /// Returns the output buffer object + FIFOSamplePipe *getOutput() { return &outputBuffer; }; + + /// Returns the input buffer object + FIFOSamplePipe *getInput() { return &inputBuffer; }; + + /// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower + /// tempo, larger faster tempo. + void setTempo(float newTempo); + + /// Returns nonzero if there aren't any samples available for outputting. + virtual void clear(); + + /// Clears the input buffer + void clearInput(); + + /// Sets the number of channels, 1 = mono, 2 = stereo + void setChannels(int numChannels); + + /// Enables/disables the quick position seeking algorithm. Zero to disable, + /// nonzero to enable + void enableQuickSeek(BOOL enable); + + /// Returns nonzero if the quick seeking algorithm is enabled. + BOOL isQuickSeekEnabled() const; + + /// Sets routine control parameters. These control are certain time constants + /// defining how the sound is stretched to the desired duration. + // + /// 'sampleRate' = sample rate of the sound + /// 'sequenceMS' = one processing sequence length in milliseconds + /// 'seekwindowMS' = seeking window length for scanning the best overlapping + /// position + /// 'overlapMS' = overlapping length + void setParameters(int sampleRate, ///< Samplerate of sound being processed (Hz) + int sequenceMS = -1, ///< Single processing sequence length (ms) + int seekwindowMS = -1, ///< Offset seeking window length (ms) + int overlapMS = -1 ///< Sequence overlapping length (ms) + ); + + /// Get routine control parameters, see setParameters() function. + /// Any of the parameters to this function can be NULL, in such case corresponding parameter + /// value isn't returned. + void getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const; + + /// Adds 'numsamples' pcs of samples from the 'samples' memory position into + /// the input of the object. + virtual void putSamples( + const SAMPLETYPE *samples, ///< Input sample data + uint numSamples ///< Number of samples in 'samples' so that one sample + ///< contains both channels if stereo + ); + + /// return nominal input sample requirement for triggering a processing batch + int getInputSampleReq() const + { + return (int)(nominalSkip + 0.5); + } + + /// return nominal output sample amount when running a processing batch + int getOutputBatchSize() const + { + return seekWindowLength - overlapLength; + } +}; + + + +// Implementation-specific class declarations: + +#ifdef SOUNDTOUCH_ALLOW_MMX + /// Class that implements MMX optimized routines for 16bit integer samples type. + class TDStretchMMX : public TDStretch + { + protected: + long calcCrossCorrStereo(const short *mixingPos, const short *compare) const; + virtual void overlapStereo(short *output, const short *input) const; + virtual void clearCrossCorrState(); + }; +#endif /// SOUNDTOUCH_ALLOW_MMX + + +#ifdef SOUNDTOUCH_ALLOW_SSE + /// Class that implements SSE optimized routines for floating point samples type. + class TDStretchSSE : public TDStretch + { + protected: + double calcCrossCorrStereo(const float *mixingPos, const float *compare) const; + }; + +#endif /// SOUNDTOUCH_ALLOW_SSE + +} +#endif /// TDStretch_H diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/cpu_detect.h mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/cpu_detect.h --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/cpu_detect.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/cpu_detect.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,62 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// A header file for detecting the Intel MMX instructions set extension. +/// +/// Please see 'mmx_win.cpp', 'mmx_cpp.cpp' and 'mmx_non_x86.cpp' for the +/// routine implementations for x86 Windows, x86 gnu version and non-x86 +/// platforms, respectively. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// File revision : $Revision: 4 $ +// +// $Id: cpu_detect.h 11 2008-02-10 16:26:55Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 _CPU_DETECT_H_ +#define _CPU_DETECT_H_ + +#include "STTypes.h" + +#define SUPPORT_MMX 0x0001 +#define SUPPORT_3DNOW 0x0002 +#define SUPPORT_ALTIVEC 0x0004 +#define SUPPORT_SSE 0x0008 +#define SUPPORT_SSE2 0x0010 + +/// Checks which instruction set extensions are supported by the CPU. +/// +/// \return A bitmask of supported extensions, see SUPPORT_... defines. +uint detectCPUextensions(void); + +/// Disables given set of instruction extensions. See SUPPORT_... defines. +void disableExtensions(uint wDisableMask); + +#endif // _CPU_DETECT_H_ diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/cpu_detect_x86_gcc.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/cpu_detect_x86_gcc.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/cpu_detect_x86_gcc.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/cpu_detect_x86_gcc.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,140 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Generic version of the x86 CPU extension detection routine. +/// +/// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp' +/// for the Microsoft compiler version. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-07-16 15:27:51 +0300 (Sat, 16 Jul 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: cpu_detect_x86_gcc.cpp 123 2011-07-16 12:27:51Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "cpu_detect.h" +#include "STTypes.h" + +using namespace std; + +#include + +////////////////////////////////////////////////////////////////////////////// +// +// processor instructions extension detection routines +// +////////////////////////////////////////////////////////////////////////////// + +// Flag variable indicating whick ISA extensions are disabled (for debugging) +static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions + +// Disables given set of instruction extensions. See SUPPORT_... defines. +void disableExtensions(uint dwDisableMask) +{ + _dwDisabledISA = dwDisableMask; +} + + + +/// Checks which instruction set extensions are supported by the CPU. +uint detectCPUextensions(void) +{ +#if (!(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS) || !(__GNUC__)) + + return 0; // always disable extensions on non-x86 platforms. + +#else + uint res = 0; + + if (_dwDisabledISA == 0xffffffff) return 0; + + asm volatile( +#ifndef __x86_64__ + // Check if 'cpuid' instructions is available by toggling eflags bit 21. + // Skip this for x86-64 as they always have cpuid while stack manipulation + // differs from 16/32bit ISA. + "\n\txor %%esi, %%esi" // clear %%esi = result register + + "\n\tpushf" // save eflags to stack + "\n\tmovl (%%esp), %%eax" // load eax from stack (with eflags) + "\n\tmovl %%eax, %%ecx" // save the original eflags values to ecx + "\n\txor $0x00200000, %%eax" // toggle bit 21 + "\n\tmovl %%eax, (%%esp)" // store toggled eflags to stack + "\n\tpopf" // load eflags from stack + "\n\tpushf" // save updated eflags to stack + "\n\tmovl (%%esp), %%eax" // load eax from stack + "\n\tpopf" // pop stack to restore esp + "\n\txor %%edx, %%edx" // clear edx for defaulting no mmx + "\n\tcmp %%ecx, %%eax" // compare to original eflags values + "\n\tjz end" // jumps to 'end' if cpuid not present +#endif // __x86_64__ + + // cpuid instruction available, test for presence of mmx instructions + + "\n\tmovl $1, %%eax" + "\n\tcpuid" + "\n\ttest $0x00800000, %%edx" + "\n\tjz end" // branch if MMX not available + + "\n\tor $0x01, %%esi" // otherwise add MMX support bit + + "\n\ttest $0x02000000, %%edx" + "\n\tjz test3DNow" // branch if SSE not available + + "\n\tor $0x08, %%esi" // otherwise add SSE support bit + + "\n\ttest3DNow:" + // test for precense of AMD extensions + "\n\tmov $0x80000000, %%eax" + "\n\tcpuid" + "\n\tcmp $0x80000000, %%eax" + "\n\tjbe end" // branch if no AMD extensions detected + + // test for precense of 3DNow! extension + "\n\tmov $0x80000001, %%eax" + "\n\tcpuid" + "\n\ttest $0x80000000, %%edx" + "\n\tjz end" // branch if 3DNow! not detected + + "\n\tor $0x02, %%esi" // otherwise add 3DNow support bit + + "\n\tend:" + + "\n\tmov %%esi, %0" + + : "=r" (res) + : /* no inputs */ + : "%edx", "%eax", "%ecx", "%esi" ); + + return res & ~_dwDisabledISA; +#endif +} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/cpu_detect_x86_win.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/cpu_detect_x86_win.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/cpu_detect_x86_win.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/cpu_detect_x86_win.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,139 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Win32 version of the x86 CPU detect routine. +/// +/// This file is to be compiled in Windows platform with Microsoft Visual C++ +/// Compiler. Please see 'cpu_detect_x86_gcc.cpp' for the gcc compiler version +/// for all GNU platforms. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-07-16 11:46:37 +0300 (Sat, 16 Jul 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: cpu_detect_x86_win.cpp 120 2011-07-16 08:46:37Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include "cpu_detect.h" + +#ifndef WIN32 +#error wrong platform - this source code file is exclusively for Win32 platform +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// processor instructions extension detection routines +// +////////////////////////////////////////////////////////////////////////////// + +// Flag variable indicating whick ISA extensions are disabled (for debugging) +static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions + + +// Disables given set of instruction extensions. See SUPPORT_... defines. +void disableExtensions(uint dwDisableMask) +{ + _dwDisabledISA = dwDisableMask; +} + + + +/// Checks which instruction set extensions are supported by the CPU. +uint detectCPUextensions(void) +{ + uint res = 0; + + if (_dwDisabledISA == 0xffffffff) return 0; + +#ifndef _M_X64 + // 32bit compilation, detect CPU capabilities with inline assembler. + __asm + { + ; check if 'cpuid' instructions is available by toggling eflags bit 21 + ; + xor esi, esi ; clear esi = result register + + pushfd ; save eflags to stack + mov eax,dword ptr [esp] ; load eax from stack (with eflags) + mov ecx, eax ; save the original eflags values to ecx + xor eax, 0x00200000 ; toggle bit 21 + mov dword ptr [esp],eax ; store toggled eflags to stack + popfd ; load eflags from stack + + pushfd ; save updated eflags to stack + mov eax,dword ptr [esp] ; load eax from stack + popfd ; pop stack to restore stack pointer + + xor edx, edx ; clear edx for defaulting no mmx + cmp eax, ecx ; compare to original eflags values + jz end ; jumps to 'end' if cpuid not present + + ; cpuid instruction available, test for presence of mmx instructions + mov eax, 1 + cpuid + test edx, 0x00800000 + jz end ; branch if MMX not available + + or esi, SUPPORT_MMX ; otherwise add MMX support bit + + test edx, 0x02000000 + jz test3DNow ; branch if SSE not available + + or esi, SUPPORT_SSE ; otherwise add SSE support bit + + test3DNow: + ; test for precense of AMD extensions + mov eax, 0x80000000 + cpuid + cmp eax, 0x80000000 + jbe end ; branch if no AMD extensions detected + + ; test for precense of 3DNow! extension + mov eax, 0x80000001 + cpuid + test edx, 0x80000000 + jz end ; branch if 3DNow! not detected + + or esi, SUPPORT_3DNOW ; otherwise add 3DNow support bit + + end: + + mov res, esi + } + +#else + + // Visual C++ 64bit compilation doesn't support inline assembler. However, + // all x64 compatible CPUs support MMX & SSE extensions. + res = SUPPORT_MMX | SUPPORT_SSE | SUPPORT_SSE2; + +#endif + + return res & ~_dwDisabledISA; +} diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/mmx_optimized.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/mmx_optimized.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/mmx_optimized.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/mmx_optimized.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,320 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// MMX optimized routines. All MMX optimized functions have been gathered into +/// this single source code file, regardless to their class or original source +/// code file, in order to ease porting the library to other compiler and +/// processor platforms. +/// +/// The MMX-optimizations are programmed using MMX compiler intrinsics that +/// are supported both by Microsoft Visual C++ and GCC compilers, so this file +/// should compile with both toolsets. +/// +/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++ +/// 6.0 processor pack" update to support compiler intrinsic syntax. The update +/// is available for download at Microsoft Developers Network, see here: +/// http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: mmx_optimized.cpp 104 2011-02-13 19:13:57Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include "STTypes.h" + +#ifdef SOUNDTOUCH_ALLOW_MMX +// MMX routines available only with integer sample type + +#if !(WIN32 || __i386__ || __x86_64__) +#error "wrong platform - this source code file is exclusively for x86 platforms" +#endif + +using namespace soundtouch; + +////////////////////////////////////////////////////////////////////////////// +// +// implementation of MMX optimized functions of class 'TDStretchMMX' +// +////////////////////////////////////////////////////////////////////////////// + +#include "TDStretch.h" +#include +#include +#include + + +// Calculates cross correlation of two buffers +long TDStretchMMX::calcCrossCorrStereo(const short *pV1, const short *pV2) const +{ + const __m64 *pVec1, *pVec2; + __m64 shifter; + __m64 accu, normaccu; + long corr, norm; + int i; + + pVec1 = (__m64*)pV1; + pVec2 = (__m64*)pV2; + + shifter = _m_from_int(overlapDividerBits); + normaccu = accu = _mm_setzero_si64(); + + // Process 4 parallel sets of 2 * stereo samples each during each + // round to improve CPU-level parallellization. + for (i = 0; i < overlapLength / 8; i ++) + { + __m64 temp, temp2; + + // dictionary of instructions: + // _m_pmaddwd : 4*16bit multiply-add, resulting two 32bits = [a0*b0+a1*b1 ; a2*b2+a3*b3] + // _mm_add_pi32 : 2*32bit add + // _m_psrad : 32bit right-shift + + temp = _mm_add_pi32(_mm_madd_pi16(pVec1[0], pVec2[0]), + _mm_madd_pi16(pVec1[1], pVec2[1])); + temp2 = _mm_add_pi32(_mm_madd_pi16(pVec1[0], pVec1[0]), + _mm_madd_pi16(pVec1[1], pVec1[1])); + accu = _mm_add_pi32(accu, _mm_sra_pi32(temp, shifter)); + normaccu = _mm_add_pi32(normaccu, _mm_sra_pi32(temp2, shifter)); + + temp = _mm_add_pi32(_mm_madd_pi16(pVec1[2], pVec2[2]), + _mm_madd_pi16(pVec1[3], pVec2[3])); + temp2 = _mm_add_pi32(_mm_madd_pi16(pVec1[2], pVec1[2]), + _mm_madd_pi16(pVec1[3], pVec1[3])); + accu = _mm_add_pi32(accu, _mm_sra_pi32(temp, shifter)); + normaccu = _mm_add_pi32(normaccu, _mm_sra_pi32(temp2, shifter)); + + pVec1 += 4; + pVec2 += 4; + } + + // copy hi-dword of mm0 to lo-dword of mm1, then sum mmo+mm1 + // and finally store the result into the variable "corr" + + accu = _mm_add_pi32(accu, _mm_srli_si64(accu, 32)); + corr = _m_to_int(accu); + + normaccu = _mm_add_pi32(normaccu, _mm_srli_si64(normaccu, 32)); + norm = _m_to_int(normaccu); + + // Clear MMS state + _m_empty(); + + // Normalize result by dividing by sqrt(norm) - this step is easiest + // done using floating point operation + if (norm == 0) norm = 1; // to avoid div by zero + return (long)((double)corr * USHRT_MAX / sqrt((double)norm)); + // Note: Warning about the missing EMMS instruction is harmless + // as it'll be called elsewhere. +} + + + +void TDStretchMMX::clearCrossCorrState() +{ + // Clear MMS state + _m_empty(); + //_asm EMMS; +} + + + +// MMX-optimized version of the function overlapStereo +void TDStretchMMX::overlapStereo(short *output, const short *input) const +{ + const __m64 *pVinput, *pVMidBuf; + __m64 *pVdest; + __m64 mix1, mix2, adder, shifter; + int i; + + pVinput = (const __m64*)input; + pVMidBuf = (const __m64*)pMidBuffer; + pVdest = (__m64*)output; + + // mix1 = mixer values for 1st stereo sample + // mix1 = mixer values for 2nd stereo sample + // adder = adder for updating mixer values after each round + + mix1 = _mm_set_pi16(0, overlapLength, 0, overlapLength); + adder = _mm_set_pi16(1, -1, 1, -1); + mix2 = _mm_add_pi16(mix1, adder); + adder = _mm_add_pi16(adder, adder); + + // Overlaplength-division by shifter. "+1" is to account for "-1" deduced in + // overlapDividerBits calculation earlier. + shifter = _m_from_int(overlapDividerBits + 1); + + for (i = 0; i < overlapLength / 4; i ++) + { + __m64 temp1, temp2; + + // load & shuffle data so that input & mixbuffer data samples are paired + temp1 = _mm_unpacklo_pi16(pVMidBuf[0], pVinput[0]); // = i0l m0l i0r m0r + temp2 = _mm_unpackhi_pi16(pVMidBuf[0], pVinput[0]); // = i1l m1l i1r m1r + + // temp = (temp .* mix) >> shifter + temp1 = _mm_sra_pi32(_mm_madd_pi16(temp1, mix1), shifter); + temp2 = _mm_sra_pi32(_mm_madd_pi16(temp2, mix2), shifter); + pVdest[0] = _mm_packs_pi32(temp1, temp2); // pack 2*2*32bit => 4*16bit + + // update mix += adder + mix1 = _mm_add_pi16(mix1, adder); + mix2 = _mm_add_pi16(mix2, adder); + + // --- second round begins here --- + + // load & shuffle data so that input & mixbuffer data samples are paired + temp1 = _mm_unpacklo_pi16(pVMidBuf[1], pVinput[1]); // = i2l m2l i2r m2r + temp2 = _mm_unpackhi_pi16(pVMidBuf[1], pVinput[1]); // = i3l m3l i3r m3r + + // temp = (temp .* mix) >> shifter + temp1 = _mm_sra_pi32(_mm_madd_pi16(temp1, mix1), shifter); + temp2 = _mm_sra_pi32(_mm_madd_pi16(temp2, mix2), shifter); + pVdest[1] = _mm_packs_pi32(temp1, temp2); // pack 2*2*32bit => 4*16bit + + // update mix += adder + mix1 = _mm_add_pi16(mix1, adder); + mix2 = _mm_add_pi16(mix2, adder); + + pVinput += 2; + pVMidBuf += 2; + pVdest += 2; + } + + _m_empty(); // clear MMS state +} + + +////////////////////////////////////////////////////////////////////////////// +// +// implementation of MMX optimized functions of class 'FIRFilter' +// +////////////////////////////////////////////////////////////////////////////// + +#include "FIRFilter.h" + + +FIRFilterMMX::FIRFilterMMX() : FIRFilter() +{ + filterCoeffsUnalign = NULL; +} + + +FIRFilterMMX::~FIRFilterMMX() +{ + delete[] filterCoeffsUnalign; +} + + +// (overloaded) Calculates filter coefficients for MMX routine +void FIRFilterMMX::setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor) +{ + uint i; + FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor); + + // Ensure that filter coeffs array is aligned to 16-byte boundary + delete[] filterCoeffsUnalign; + filterCoeffsUnalign = new short[2 * newLength + 8]; + filterCoeffsAlign = (short *)(((ulong)filterCoeffsUnalign + 15) & -16); + + // rearrange the filter coefficients for mmx routines + for (i = 0;i < length; i += 4) + { + filterCoeffsAlign[2 * i + 0] = coeffs[i + 0]; + filterCoeffsAlign[2 * i + 1] = coeffs[i + 2]; + filterCoeffsAlign[2 * i + 2] = coeffs[i + 0]; + filterCoeffsAlign[2 * i + 3] = coeffs[i + 2]; + + filterCoeffsAlign[2 * i + 4] = coeffs[i + 1]; + filterCoeffsAlign[2 * i + 5] = coeffs[i + 3]; + filterCoeffsAlign[2 * i + 6] = coeffs[i + 1]; + filterCoeffsAlign[2 * i + 7] = coeffs[i + 3]; + } +} + + + +// mmx-optimized version of the filter routine for stereo sound +uint FIRFilterMMX::evaluateFilterStereo(short *dest, const short *src, uint numSamples) const +{ + // Create stack copies of the needed member variables for asm routines : + uint i, j; + __m64 *pVdest = (__m64*)dest; + + if (length < 2) return 0; + + for (i = 0; i < (numSamples - length) / 2; i ++) + { + __m64 accu1; + __m64 accu2; + const __m64 *pVsrc = (const __m64*)src; + const __m64 *pVfilter = (const __m64*)filterCoeffsAlign; + + accu1 = accu2 = _mm_setzero_si64(); + for (j = 0; j < lengthDiv8 * 2; j ++) + { + __m64 temp1, temp2; + + temp1 = _mm_unpacklo_pi16(pVsrc[0], pVsrc[1]); // = l2 l0 r2 r0 + temp2 = _mm_unpackhi_pi16(pVsrc[0], pVsrc[1]); // = l3 l1 r3 r1 + + accu1 = _mm_add_pi32(accu1, _mm_madd_pi16(temp1, pVfilter[0])); // += l2*f2+l0*f0 r2*f2+r0*f0 + accu1 = _mm_add_pi32(accu1, _mm_madd_pi16(temp2, pVfilter[1])); // += l3*f3+l1*f1 r3*f3+r1*f1 + + temp1 = _mm_unpacklo_pi16(pVsrc[1], pVsrc[2]); // = l4 l2 r4 r2 + + accu2 = _mm_add_pi32(accu2, _mm_madd_pi16(temp2, pVfilter[0])); // += l3*f2+l1*f0 r3*f2+r1*f0 + accu2 = _mm_add_pi32(accu2, _mm_madd_pi16(temp1, pVfilter[1])); // += l4*f3+l2*f1 r4*f3+r2*f1 + + // accu1 += l2*f2+l0*f0 r2*f2+r0*f0 + // += l3*f3+l1*f1 r3*f3+r1*f1 + + // accu2 += l3*f2+l1*f0 r3*f2+r1*f0 + // l4*f3+l2*f1 r4*f3+r2*f1 + + pVfilter += 2; + pVsrc += 2; + } + // accu >>= resultDivFactor + accu1 = _mm_srai_pi32(accu1, resultDivFactor); + accu2 = _mm_srai_pi32(accu2, resultDivFactor); + + // pack 2*2*32bits => 4*16 bits + pVdest[0] = _mm_packs_pi32(accu1, accu2); + src += 4; + pVdest ++; + } + + _m_empty(); // clear emms state + + return (numSamples & 0xfffffffe) - length; +} + +#endif // SOUNDTOUCH_ALLOW_MMX diff -Nru mixxx-1.10.1-1/lib/soundtouch-1.6.0/sse_optimized.cpp mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/sse_optimized.cpp --- mixxx-1.10.1-1/lib/soundtouch-1.6.0/sse_optimized.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/soundtouch-1.6.0/sse_optimized.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,428 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// SSE optimized routines for Pentium-III, Athlon-XP and later CPUs. All SSE +/// optimized functions have been gathered into this single source +/// code file, regardless to their class or original source code file, in order +/// to ease porting the library to other compiler and processor platforms. +/// +/// The SSE-optimizations are programmed using SSE compiler intrinsics that +/// are supported both by Microsoft Visual C++ and GCC compilers, so this file +/// should compile with both toolsets. +/// +/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++ +/// 6.0 processor pack" update to support SSE instruction set. The update is +/// available for download at Microsoft Developers Network, see here: +/// http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx +/// +/// If the above URL is expired or removed, go to "http://msdn.microsoft.com" and +/// perform a search with keywords "processor pack". +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-07-16 15:27:28 +0300 (Sat, 16 Jul 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: sse_optimized.cpp 122 2011-07-16 12:27:28Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#include "cpu_detect.h" +#include "STTypes.h" + +using namespace soundtouch; + +#ifdef SOUNDTOUCH_ALLOW_SSE + +// SSE routines available only with float sample type + +////////////////////////////////////////////////////////////////////////////// +// +// implementation of SSE optimized functions of class 'TDStretchSSE' +// +////////////////////////////////////////////////////////////////////////////// + +#include "TDStretch.h" +#include +#include + +// Calculates cross correlation of two buffers +double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) const +{ + int i; + const float *pVec1; + const __m128 *pVec2; + __m128 vSum, vNorm; + + // Note. It means a major slow-down if the routine needs to tolerate + // unaligned __m128 memory accesses. It's way faster if we can skip + // unaligned slots and use _mm_load_ps instruction instead of _mm_loadu_ps. + // This can mean up to ~ 10-fold difference (incl. part of which is + // due to skipping every second round for stereo sound though). + // + // Compile-time define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided + // for choosing if this little cheating is allowed. + +#ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION + // Little cheating allowed, return valid correlation only for + // aligned locations, meaning every second round for stereo sound. + + #define _MM_LOAD _mm_load_ps + + if (((ulong)pV1) & 15) return -1e50; // skip unaligned locations + +#else + // No cheating allowed, use unaligned load & take the resulting + // performance hit. + #define _MM_LOAD _mm_loadu_ps +#endif + + // ensure overlapLength is divisible by 8 + assert((overlapLength % 8) == 0); + + // Calculates the cross-correlation value between 'pV1' and 'pV2' vectors + // Note: pV2 _must_ be aligned to 16-bit boundary, pV1 need not. + pVec1 = (const float*)pV1; + pVec2 = (const __m128*)pV2; + vSum = vNorm = _mm_setzero_ps(); + + // Unroll the loop by factor of 4 * 4 operations + for (i = 0; i < overlapLength / 8; i ++) + { + __m128 vTemp; + // vSum += pV1[0..3] * pV2[0..3] + vTemp = _MM_LOAD(pVec1); + vSum = _mm_add_ps(vSum, _mm_mul_ps(vTemp ,pVec2[0])); + vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp ,vTemp)); + + // vSum += pV1[4..7] * pV2[4..7] + vTemp = _MM_LOAD(pVec1 + 4); + vSum = _mm_add_ps(vSum, _mm_mul_ps(vTemp, pVec2[1])); + vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp ,vTemp)); + + // vSum += pV1[8..11] * pV2[8..11] + vTemp = _MM_LOAD(pVec1 + 8); + vSum = _mm_add_ps(vSum, _mm_mul_ps(vTemp, pVec2[2])); + vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp ,vTemp)); + + // vSum += pV1[12..15] * pV2[12..15] + vTemp = _MM_LOAD(pVec1 + 12); + vSum = _mm_add_ps(vSum, _mm_mul_ps(vTemp, pVec2[3])); + vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp ,vTemp)); + + pVec1 += 16; + pVec2 += 4; + } + + // return value = vSum[0] + vSum[1] + vSum[2] + vSum[3] + float *pvNorm = (float*)&vNorm; + double norm = sqrt(pvNorm[0] + pvNorm[1] + pvNorm[2] + pvNorm[3]); + if (norm < 1e-9) norm = 1.0; // to avoid div by zero + + float *pvSum = (float*)&vSum; + return (double)(pvSum[0] + pvSum[1] + pvSum[2] + pvSum[3]) / norm; + + /* This is approximately corresponding routine in C-language yet without normalization: + double corr, norm; + uint i; + + // Calculates the cross-correlation value between 'pV1' and 'pV2' vectors + corr = norm = 0.0; + for (i = 0; i < overlapLength / 8; i ++) + { + corr += pV1[0] * pV2[0] + + pV1[1] * pV2[1] + + pV1[2] * pV2[2] + + pV1[3] * pV2[3] + + pV1[4] * pV2[4] + + pV1[5] * pV2[5] + + pV1[6] * pV2[6] + + pV1[7] * pV2[7] + + pV1[8] * pV2[8] + + pV1[9] * pV2[9] + + pV1[10] * pV2[10] + + pV1[11] * pV2[11] + + pV1[12] * pV2[12] + + pV1[13] * pV2[13] + + pV1[14] * pV2[14] + + pV1[15] * pV2[15]; + + for (j = 0; j < 15; j ++) norm += pV1[j] * pV1[j]; + + pV1 += 16; + pV2 += 16; + } + return corr / sqrt(norm); + */ + + /* This is a bit outdated, corresponding routine in assembler. This may be teeny-weeny bit + faster than intrinsic version, but more difficult to maintain & get compiled on multiple + platforms. + + uint overlapLengthLocal = overlapLength; + float corr; + + _asm + { + // Very important note: data in 'pV2' _must_ be aligned to + // 16-byte boundary! + + // give prefetch hints to CPU of what data are to be needed soonish + // give more aggressive hints on pV1 as that changes while pV2 stays + // same between runs + prefetcht0 [pV1] + prefetcht0 [pV2] + prefetcht0 [pV1 + 32] + + mov eax, dword ptr pV1 + mov ebx, dword ptr pV2 + + xorps xmm0, xmm0 + + mov ecx, overlapLengthLocal + shr ecx, 3 // div by eight + + loop1: + prefetcht0 [eax + 64] // give a prefetch hint to CPU what data are to be needed soonish + prefetcht0 [ebx + 32] // give a prefetch hint to CPU what data are to be needed soonish + movups xmm1, [eax] + mulps xmm1, [ebx] + addps xmm0, xmm1 + + movups xmm2, [eax + 16] + mulps xmm2, [ebx + 16] + addps xmm0, xmm2 + + prefetcht0 [eax + 96] // give a prefetch hint to CPU what data are to be needed soonish + prefetcht0 [ebx + 64] // give a prefetch hint to CPU what data are to be needed soonish + + movups xmm3, [eax + 32] + mulps xmm3, [ebx + 32] + addps xmm0, xmm3 + + movups xmm4, [eax + 48] + mulps xmm4, [ebx + 48] + addps xmm0, xmm4 + + add eax, 64 + add ebx, 64 + + dec ecx + jnz loop1 + + // add the four floats of xmm0 together and return the result. + + movhlps xmm1, xmm0 // move 3 & 4 of xmm0 to 1 & 2 of xmm1 + addps xmm1, xmm0 + movaps xmm2, xmm1 + shufps xmm2, xmm2, 0x01 // move 2 of xmm2 as 1 of xmm2 + addss xmm2, xmm1 + movss corr, xmm2 + } + + return (double)corr; + */ +} + + +////////////////////////////////////////////////////////////////////////////// +// +// implementation of SSE optimized functions of class 'FIRFilter' +// +////////////////////////////////////////////////////////////////////////////// + +#include "FIRFilter.h" + +FIRFilterSSE::FIRFilterSSE() : FIRFilter() +{ + filterCoeffsAlign = NULL; + filterCoeffsUnalign = NULL; +} + + +FIRFilterSSE::~FIRFilterSSE() +{ + delete[] filterCoeffsUnalign; + filterCoeffsAlign = NULL; + filterCoeffsUnalign = NULL; +} + + +// (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 + // also rearrange coefficients suitably for SSE + // Ensure that filter coeffs array is aligned to 16-byte boundary + delete[] filterCoeffsUnalign; + filterCoeffsUnalign = new float[2 * newLength + 4]; + filterCoeffsAlign = (float *)(((unsigned long)filterCoeffsUnalign + 15) & (ulong)-16); + + fDivider = (float)resultDivider; + + // rearrange the filter coefficients for mmx routines + for (i = 0; i < newLength; i ++) + { + filterCoeffsAlign[2 * i + 0] = + filterCoeffsAlign[2 * i + 1] = coeffs[i + 0] / fDivider; + } +} + + + +// SSE-optimized version of the filter routine for stereo sound +uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint numSamples) const +{ + int count = (int)((numSamples - length) & (uint)-2); + int j; + + assert(count % 2 == 0); + + if (count < 2) return 0; + + assert(source != NULL); + assert(dest != NULL); + assert((length % 8) == 0); + assert(filterCoeffsAlign != NULL); + assert(((ulong)filterCoeffsAlign) % 16 == 0); + + // filter is evaluated for two stereo samples with each iteration, thus use of 'j += 2' + for (j = 0; j < count; j += 2) + { + const float *pSrc; + const __m128 *pFil; + __m128 sum1, sum2; + uint i; + + pSrc = (const float*)source; // source audio data + pFil = (const __m128*)filterCoeffsAlign; // filter coefficients. NOTE: Assumes coefficients + // are aligned to 16-byte boundary + sum1 = sum2 = _mm_setzero_ps(); + + for (i = 0; i < length / 8; i ++) + { + // Unroll loop for efficiency & calculate filter for 2*2 stereo samples + // at each pass + + // sum1 is accu for 2*2 filtered stereo sound data at the primary sound data offset + // sum2 is accu for 2*2 filtered stereo sound data for the next sound sample offset. + + sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc) , pFil[0])); + sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 2), pFil[0])); + + sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc + 4), pFil[1])); + sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 6), pFil[1])); + + sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc + 8) , pFil[2])); + sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 10), pFil[2])); + + sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc + 12), pFil[3])); + sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 14), pFil[3])); + + pSrc += 16; + pFil += 4; + } + + // Now sum1 and sum2 both have a filtered 2-channel sample each, but we still need + // to sum the two hi- and lo-floats of these registers together. + + // post-shuffle & add the filtered values and store to dest. + _mm_storeu_ps(dest, _mm_add_ps( + _mm_shuffle_ps(sum1, sum2, _MM_SHUFFLE(1,0,3,2)), // s2_1 s2_0 s1_3 s1_2 + _mm_shuffle_ps(sum1, sum2, _MM_SHUFFLE(3,2,1,0)) // s2_3 s2_2 s1_1 s1_0 + )); + source += 4; + dest += 4; + } + + // Ideas for further improvement: + // 1. If it could be guaranteed that 'source' were always aligned to 16-byte + // boundary, a faster aligned '_mm_load_ps' instruction could be used. + // 2. If it could be guaranteed that 'dest' were always aligned to 16-byte + // boundary, a faster '_mm_store_ps' instruction could be used. + + return (uint)count; + + /* original routine in C-language. please notice the C-version has differently + organized coefficients though. + double suml1, suml2; + double sumr1, sumr2; + uint i, j; + + for (j = 0; j < count; j += 2) + { + const float *ptr; + const float *pFil; + + suml1 = sumr1 = 0.0; + suml2 = sumr2 = 0.0; + ptr = src; + pFil = filterCoeffs; + for (i = 0; i < lengthLocal; i ++) + { + // unroll loop for efficiency. + + suml1 += ptr[0] * pFil[0] + + ptr[2] * pFil[2] + + ptr[4] * pFil[4] + + ptr[6] * pFil[6]; + + sumr1 += ptr[1] * pFil[1] + + ptr[3] * pFil[3] + + ptr[5] * pFil[5] + + ptr[7] * pFil[7]; + + suml2 += ptr[8] * pFil[0] + + ptr[10] * pFil[2] + + ptr[12] * pFil[4] + + ptr[14] * pFil[6]; + + sumr2 += ptr[9] * pFil[1] + + ptr[11] * pFil[3] + + ptr[13] * pFil[5] + + ptr[15] * pFil[7]; + + ptr += 16; + pFil += 8; + } + dest[0] = (float)suml1; + dest[1] = (float)sumr1; + dest[2] = (float)suml2; + dest[3] = (float)sumr2; + + src += 4; + dest += 4; + } + */ +} + +#endif // SOUNDTOUCH_ALLOW_SSE diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginBufferingAdapter.cpp mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginBufferingAdapter.cpp --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginBufferingAdapter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginBufferingAdapter.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,721 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + This file by Mark Levy and Chris Cannam, Copyright 2007-2009 QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#include +#include + +#include +#include + +using std::vector; +using std::map; + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginBufferingAdapter.cpp) + +namespace Vamp { + +namespace HostExt { + +class PluginBufferingAdapter::Impl +{ +public: + Impl(Plugin *plugin, float inputSampleRate); + ~Impl(); + + void setPluginStepSize(size_t stepSize); + void setPluginBlockSize(size_t blockSize); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + + void getActualStepAndBlockSizes(size_t &stepSize, size_t &blockSize); + + OutputList getOutputDescriptors() const; + + void setParameter(std::string, float); + void selectProgram(std::string); + + void reset(); + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + class RingBuffer + { + public: + RingBuffer(int n) : + m_buffer(new float[n+1]), m_writer(0), m_reader(0), m_size(n+1) { } + virtual ~RingBuffer() { delete[] m_buffer; } + + int getSize() const { return m_size-1; } + void reset() { m_writer = 0; m_reader = 0; } + + int getReadSpace() const { + int writer = m_writer, reader = m_reader, space; + if (writer > reader) space = writer - reader; + else if (writer < reader) space = (writer + m_size) - reader; + else space = 0; + return space; + } + + int getWriteSpace() const { + int writer = m_writer; + int reader = m_reader; + int space = (reader + m_size - writer - 1); + if (space >= m_size) space -= m_size; + return space; + } + + int peek(float *destination, int n) const { + + int available = getReadSpace(); + + if (n > available) { + for (int i = available; i < n; ++i) { + destination[i] = 0.f; + } + n = available; + } + if (n == 0) return n; + + int reader = m_reader; + int here = m_size - reader; + const float *const bufbase = m_buffer + reader; + + if (here >= n) { + for (int i = 0; i < n; ++i) { + destination[i] = bufbase[i]; + } + } else { + for (int i = 0; i < here; ++i) { + destination[i] = bufbase[i]; + } + float *const destbase = destination + here; + const int nh = n - here; + for (int i = 0; i < nh; ++i) { + destbase[i] = m_buffer[i]; + } + } + + return n; + } + + int skip(int n) { + + int available = getReadSpace(); + if (n > available) { + n = available; + } + if (n == 0) return n; + + int reader = m_reader; + reader += n; + while (reader >= m_size) reader -= m_size; + m_reader = reader; + return n; + } + + int write(const float *source, int n) { + + int available = getWriteSpace(); + if (n > available) { + n = available; + } + if (n == 0) return n; + + int writer = m_writer; + int here = m_size - writer; + float *const bufbase = m_buffer + writer; + + if (here >= n) { + for (int i = 0; i < n; ++i) { + bufbase[i] = source[i]; + } + } else { + for (int i = 0; i < here; ++i) { + bufbase[i] = source[i]; + } + const int nh = n - here; + const float *const srcbase = source + here; + float *const buf = m_buffer; + for (int i = 0; i < nh; ++i) { + buf[i] = srcbase[i]; + } + } + + writer += n; + while (writer >= m_size) writer -= m_size; + m_writer = writer; + + return n; + } + + int zero(int n) { + + int available = getWriteSpace(); + if (n > available) { + n = available; + } + if (n == 0) return n; + + int writer = m_writer; + int here = m_size - writer; + float *const bufbase = m_buffer + writer; + + if (here >= n) { + for (int i = 0; i < n; ++i) { + bufbase[i] = 0.f; + } + } else { + for (int i = 0; i < here; ++i) { + bufbase[i] = 0.f; + } + const int nh = n - here; + for (int i = 0; i < nh; ++i) { + m_buffer[i] = 0.f; + } + } + + writer += n; + while (writer >= m_size) writer -= m_size; + m_writer = writer; + + return n; + } + + protected: + float *m_buffer; + int m_writer; + int m_reader; + int m_size; + + private: + RingBuffer(const RingBuffer &); // not provided + RingBuffer &operator=(const RingBuffer &); // not provided + }; + + Plugin *m_plugin; + size_t m_inputStepSize; // value passed to wrapper initialise() + size_t m_inputBlockSize; // value passed to wrapper initialise() + size_t m_setStepSize; // value passed to setPluginStepSize() + size_t m_setBlockSize; // value passed to setPluginBlockSize() + size_t m_stepSize; // value actually used to initialise plugin + size_t m_blockSize; // value actually used to initialise plugin + size_t m_channels; + vector m_queue; + float **m_buffers; + float m_inputSampleRate; + long m_frame; + bool m_unrun; + mutable OutputList m_outputs; + mutable std::map m_rewriteOutputTimes; + + void processBlock(FeatureSet& allFeatureSets); +}; + +PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) : + PluginWrapper(plugin) +{ + m_impl = new Impl(plugin, m_inputSampleRate); +} + +PluginBufferingAdapter::~PluginBufferingAdapter() +{ + delete m_impl; +} + +size_t +PluginBufferingAdapter::getPreferredStepSize() const +{ + return getPreferredBlockSize(); +} + +size_t +PluginBufferingAdapter::getPreferredBlockSize() const +{ + return PluginWrapper::getPreferredBlockSize(); +} + +size_t +PluginBufferingAdapter::getPluginPreferredStepSize() const +{ + return PluginWrapper::getPreferredStepSize(); +} + +size_t +PluginBufferingAdapter::getPluginPreferredBlockSize() const +{ + return PluginWrapper::getPreferredBlockSize(); +} + +void +PluginBufferingAdapter::setPluginStepSize(size_t stepSize) +{ + m_impl->setPluginStepSize(stepSize); +} + +void +PluginBufferingAdapter::setPluginBlockSize(size_t blockSize) +{ + m_impl->setPluginBlockSize(blockSize); +} + +void +PluginBufferingAdapter::getActualStepAndBlockSizes(size_t &stepSize, + size_t &blockSize) +{ + m_impl->getActualStepAndBlockSizes(stepSize, blockSize); +} + +bool +PluginBufferingAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + return m_impl->initialise(channels, stepSize, blockSize); +} + +PluginBufferingAdapter::OutputList +PluginBufferingAdapter::getOutputDescriptors() const +{ + return m_impl->getOutputDescriptors(); +} + +void +PluginBufferingAdapter::setParameter(std::string name, float value) +{ + m_impl->setParameter(name, value); +} + +void +PluginBufferingAdapter::selectProgram(std::string name) +{ + m_impl->selectProgram(name); +} + +void +PluginBufferingAdapter::reset() +{ + m_impl->reset(); +} + +PluginBufferingAdapter::FeatureSet +PluginBufferingAdapter::process(const float *const *inputBuffers, + RealTime timestamp) +{ + return m_impl->process(inputBuffers, timestamp); +} + +PluginBufferingAdapter::FeatureSet +PluginBufferingAdapter::getRemainingFeatures() +{ + return m_impl->getRemainingFeatures(); +} + +PluginBufferingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) : + m_plugin(plugin), + m_inputStepSize(0), + m_inputBlockSize(0), + m_setStepSize(0), + m_setBlockSize(0), + m_stepSize(0), + m_blockSize(0), + m_channels(0), + m_queue(0), + m_buffers(0), + m_inputSampleRate(inputSampleRate), + m_frame(0), + m_unrun(true) +{ + (void)getOutputDescriptors(); // set up m_outputs and m_rewriteOutputTimes +} + +PluginBufferingAdapter::Impl::~Impl() +{ + // the adapter will delete the plugin + + for (size_t i = 0; i < m_channels; ++i) { + delete m_queue[i]; + delete[] m_buffers[i]; + } + delete[] m_buffers; +} + +void +PluginBufferingAdapter::Impl::setPluginStepSize(size_t stepSize) +{ + if (m_inputStepSize != 0) { + std::cerr << "PluginBufferingAdapter::setPluginStepSize: ERROR: Cannot be called after initialise()" << std::endl; + return; + } + m_setStepSize = stepSize; +} + +void +PluginBufferingAdapter::Impl::setPluginBlockSize(size_t blockSize) +{ + if (m_inputBlockSize != 0) { + std::cerr << "PluginBufferingAdapter::setPluginBlockSize: ERROR: Cannot be called after initialise()" << std::endl; + return; + } + m_setBlockSize = blockSize; +} + +void +PluginBufferingAdapter::Impl::getActualStepAndBlockSizes(size_t &stepSize, + size_t &blockSize) +{ + stepSize = m_stepSize; + blockSize = m_blockSize; +} + +bool +PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (stepSize != blockSize) { + std::cerr << "PluginBufferingAdapter::initialise: input stepSize must be equal to blockSize for this adapter (stepSize = " << stepSize << ", blockSize = " << blockSize << ")" << std::endl; + return false; + } + + m_channels = channels; + m_inputStepSize = stepSize; + m_inputBlockSize = blockSize; + + // if the user has requested particular step or block sizes, use + // those; otherwise use the step and block sizes which the plugin + // prefers + + m_stepSize = 0; + m_blockSize = 0; + + if (m_setStepSize > 0) { + m_stepSize = m_setStepSize; + } + if (m_setBlockSize > 0) { + m_blockSize = m_setBlockSize; + } + + if (m_stepSize == 0 && m_blockSize == 0) { + m_stepSize = m_plugin->getPreferredStepSize(); + m_blockSize = m_plugin->getPreferredBlockSize(); + } + + bool freq = (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain); + + // or sensible defaults if it has no preference + if (m_blockSize == 0) { + if (m_stepSize == 0) { + m_blockSize = 1024; + if (freq) { + m_stepSize = m_blockSize / 2; + } else { + m_stepSize = m_blockSize; + } + } else if (freq) { + m_blockSize = m_stepSize * 2; + } else { + m_blockSize = m_stepSize; + } + } else if (m_stepSize == 0) { // m_blockSize != 0 (that was handled above) + if (freq) { + m_stepSize = m_blockSize/2; + } else { + m_stepSize = m_blockSize; + } + } + + // current implementation breaks if step is greater than block + if (m_stepSize > m_blockSize) { + size_t newBlockSize; + if (freq) { + newBlockSize = m_stepSize * 2; + } else { + newBlockSize = m_stepSize; + } + std::cerr << "PluginBufferingAdapter::initialise: WARNING: step size " << m_stepSize << " is greater than block size " << m_blockSize << ": cannot handle this in adapter; adjusting block size to " << newBlockSize << std::endl; + m_blockSize = newBlockSize; + } + +// std::cerr << "PluginBufferingAdapter::initialise: NOTE: stepSize " << m_inputStepSize << " -> " << m_stepSize +// << ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl; + + m_buffers = new float *[m_channels]; + + for (size_t i = 0; i < m_channels; ++i) { + m_queue.push_back(new RingBuffer(m_blockSize + m_inputBlockSize)); + m_buffers[i] = new float[m_blockSize]; + } + + bool success = m_plugin->initialise(m_channels, m_stepSize, m_blockSize); + +// std::cerr << "PluginBufferingAdapter::initialise: success = " << success << std::endl; + + if (success) { + // Re-query outputs; properties such as bin count may have + // changed on initialise + m_outputs.clear(); + (void)getOutputDescriptors(); + } + + return success; +} + +PluginBufferingAdapter::OutputList +PluginBufferingAdapter::Impl::getOutputDescriptors() const +{ + if (m_outputs.empty()) { +// std::cerr << "PluginBufferingAdapter::getOutputDescriptors: querying anew" << std::endl; + + m_outputs = m_plugin->getOutputDescriptors(); + } + + PluginBufferingAdapter::OutputList outs = m_outputs; + + for (size_t i = 0; i < outs.size(); ++i) { + + switch (outs[i].sampleType) { + + case OutputDescriptor::OneSamplePerStep: + outs[i].sampleType = OutputDescriptor::FixedSampleRate; + outs[i].sampleRate = (1.f / m_inputSampleRate) * m_stepSize; + m_rewriteOutputTimes[i] = true; + break; + + case OutputDescriptor::FixedSampleRate: + if (outs[i].sampleRate == 0.f) { + outs[i].sampleRate = (1.f / m_inputSampleRate) * m_stepSize; + } + // We actually only need to rewrite output times for + // features that don't have timestamps already, but we + // can't tell from here whether our features will have + // timestamps or not + m_rewriteOutputTimes[i] = true; + break; + + case OutputDescriptor::VariableSampleRate: + m_rewriteOutputTimes[i] = false; + break; + } + } + + return outs; +} + +void +PluginBufferingAdapter::Impl::setParameter(std::string name, float value) +{ + m_plugin->setParameter(name, value); + + // Re-query outputs; properties such as bin count may have changed + m_outputs.clear(); + (void)getOutputDescriptors(); +} + +void +PluginBufferingAdapter::Impl::selectProgram(std::string name) +{ + m_plugin->selectProgram(name); + + // Re-query outputs; properties such as bin count may have changed + m_outputs.clear(); + (void)getOutputDescriptors(); +} + +void +PluginBufferingAdapter::Impl::reset() +{ + m_frame = 0; + m_unrun = true; + + for (size_t i = 0; i < m_queue.size(); ++i) { + m_queue[i]->reset(); + } + + m_plugin->reset(); +} + +PluginBufferingAdapter::FeatureSet +PluginBufferingAdapter::Impl::process(const float *const *inputBuffers, + RealTime timestamp) +{ + if (m_inputStepSize == 0) { + std::cerr << "PluginBufferingAdapter::process: ERROR: Plugin has not been initialised" << std::endl; + return FeatureSet(); + } + + FeatureSet allFeatureSets; + + if (m_unrun) { + m_frame = RealTime::realTime2Frame(timestamp, + int(m_inputSampleRate + 0.5)); + m_unrun = false; + } + + // queue the new input + + for (size_t i = 0; i < m_channels; ++i) { + int written = m_queue[i]->write(inputBuffers[i], m_inputBlockSize); + if (written < int(m_inputBlockSize) && i == 0) { + std::cerr << "WARNING: PluginBufferingAdapter::Impl::process: " + << "Buffer overflow: wrote " << written + << " of " << m_inputBlockSize + << " input samples (for plugin step size " + << m_stepSize << ", block size " << m_blockSize << ")" + << std::endl; + } + } + + // process as much as we can + + while (m_queue[0]->getReadSpace() >= int(m_blockSize)) { + processBlock(allFeatureSets); + } + + return allFeatureSets; +} + +PluginBufferingAdapter::FeatureSet +PluginBufferingAdapter::Impl::getRemainingFeatures() +{ + FeatureSet allFeatureSets; + + // process remaining samples in queue + while (m_queue[0]->getReadSpace() >= int(m_blockSize)) { + processBlock(allFeatureSets); + } + + // pad any last samples remaining and process + if (m_queue[0]->getReadSpace() > 0) { + for (size_t i = 0; i < m_channels; ++i) { + m_queue[i]->zero(m_blockSize - m_queue[i]->getReadSpace()); + } + processBlock(allFeatureSets); + } + + // get remaining features + + FeatureSet featureSet = m_plugin->getRemainingFeatures(); + + for (map::iterator iter = featureSet.begin(); + iter != featureSet.end(); ++iter) { + FeatureList featureList = iter->second; + for (size_t i = 0; i < featureList.size(); ++i) { + allFeatureSets[iter->first].push_back(featureList[i]); + } + } + + return allFeatureSets; +} + +void +PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets) +{ + for (size_t i = 0; i < m_channels; ++i) { + m_queue[i]->peek(m_buffers[i], m_blockSize); + } + + long frame = m_frame; + RealTime timestamp = RealTime::frame2RealTime + (frame, int(m_inputSampleRate + 0.5)); + + FeatureSet featureSet = m_plugin->process(m_buffers, timestamp); + + PluginWrapper *wrapper = dynamic_cast(m_plugin); + RealTime adjustment; + if (wrapper) { + PluginInputDomainAdapter *ida = + wrapper->getWrapper(); + if (ida) adjustment = ida->getTimestampAdjustment(); + } + + for (FeatureSet::iterator iter = featureSet.begin(); + iter != featureSet.end(); ++iter) { + + int outputNo = iter->first; + + if (m_rewriteOutputTimes[outputNo]) { + + FeatureList featureList = iter->second; + + for (size_t i = 0; i < featureList.size(); ++i) { + + switch (m_outputs[outputNo].sampleType) { + + case OutputDescriptor::OneSamplePerStep: + // use our internal timestamp, always + featureList[i].timestamp = timestamp + adjustment; + featureList[i].hasTimestamp = true; + break; + + case OutputDescriptor::FixedSampleRate: + // use our internal timestamp if feature lacks one + if (!featureList[i].hasTimestamp) { + featureList[i].timestamp = timestamp + adjustment; + featureList[i].hasTimestamp = true; + } + break; + + case OutputDescriptor::VariableSampleRate: + break; // plugin must set timestamp + + default: + break; + } + + allFeatureSets[outputNo].push_back(featureList[i]); + } + } else { + for (size_t i = 0; i < iter->second.size(); ++i) { + allFeatureSets[outputNo].push_back(iter->second[i]); + } + } + } + + // step forward + + for (size_t i = 0; i < m_channels; ++i) { + m_queue[i]->skip(m_stepSize); + } + + // increment internal frame counter each time we step forward + m_frame += m_stepSize; +} + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginBufferingAdapter.cpp) diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginChannelAdapter.cpp mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginChannelAdapter.cpp --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginChannelAdapter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginChannelAdapter.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,270 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#include + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginChannelAdapter.cpp) + +namespace Vamp { + +namespace HostExt { + +class PluginChannelAdapter::Impl +{ +public: + Impl(Plugin *plugin); + ~Impl(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + FeatureSet processInterleaved(const float *inputBuffers, RealTime timestamp); + +protected: + Plugin *m_plugin; + size_t m_blockSize; + size_t m_inputChannels; + size_t m_pluginChannels; + float **m_buffer; + float **m_deinterleave; + const float **m_forwardPtrs; +}; + +PluginChannelAdapter::PluginChannelAdapter(Plugin *plugin) : + PluginWrapper(plugin) +{ + m_impl = new Impl(plugin); +} + +PluginChannelAdapter::~PluginChannelAdapter() +{ + delete m_impl; +} + +bool +PluginChannelAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + return m_impl->initialise(channels, stepSize, blockSize); +} + +PluginChannelAdapter::FeatureSet +PluginChannelAdapter::process(const float *const *inputBuffers, + RealTime timestamp) +{ + return m_impl->process(inputBuffers, timestamp); +} + +PluginChannelAdapter::FeatureSet +PluginChannelAdapter::processInterleaved(const float *inputBuffers, + RealTime timestamp) +{ + return m_impl->processInterleaved(inputBuffers, timestamp); +} + +PluginChannelAdapter::Impl::Impl(Plugin *plugin) : + m_plugin(plugin), + m_blockSize(0), + m_inputChannels(0), + m_pluginChannels(0), + m_buffer(0), + m_deinterleave(0), + m_forwardPtrs(0) +{ +} + +PluginChannelAdapter::Impl::~Impl() +{ + // the adapter will delete the plugin + + if (m_buffer) { + if (m_inputChannels > m_pluginChannels) { + delete[] m_buffer[0]; + } else { + for (size_t i = 0; i < m_pluginChannels - m_inputChannels; ++i) { + delete[] m_buffer[i]; + } + } + delete[] m_buffer; + m_buffer = 0; + } + + if (m_deinterleave) { + for (size_t i = 0; i < m_inputChannels; ++i) { + delete[] m_deinterleave[i]; + } + delete[] m_deinterleave; + m_deinterleave = 0; + } + + if (m_forwardPtrs) { + delete[] m_forwardPtrs; + m_forwardPtrs = 0; + } +} + +bool +PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + m_blockSize = blockSize; + + size_t minch = m_plugin->getMinChannelCount(); + size_t maxch = m_plugin->getMaxChannelCount(); + + m_inputChannels = channels; + + if (m_inputChannels < minch) { + + m_forwardPtrs = new const float *[minch]; + + if (m_inputChannels > 1) { + // We need a set of zero-valued buffers to add to the + // forwarded pointers + m_buffer = new float*[minch - channels]; + for (size_t i = 0; i < minch; ++i) { + m_buffer[i] = new float[blockSize]; + for (size_t j = 0; j < blockSize; ++j) { + m_buffer[i][j] = 0.f; + } + } + } + + m_pluginChannels = minch; + +// std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl; + + } else if (m_inputChannels > maxch) { + + // We only need m_buffer if we are mixing down to a single + // channel -- otherwise we can just forward the same float* as + // passed in to process(), expecting the excess to be ignored + + if (maxch == 1) { + m_buffer = new float *[1]; + m_buffer[0] = new float[blockSize]; + +// std::cerr << "PluginChannelAdapter::initialise: mixing " << m_inputChannels << " to mono for plugin" << std::endl; + + } else { + +// std::cerr << "PluginChannelAdapter::initialise: reducing " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl; + } + + m_pluginChannels = maxch; + + } else { + +// std::cerr << "PluginChannelAdapter::initialise: accepting given number of channels (" << m_inputChannels << ")" << std::endl; + m_pluginChannels = m_inputChannels; + } + + return m_plugin->initialise(m_pluginChannels, stepSize, blockSize); +} + +PluginChannelAdapter::FeatureSet +PluginChannelAdapter::Impl::processInterleaved(const float *inputBuffers, + RealTime timestamp) +{ + if (!m_deinterleave) { + m_deinterleave = new float *[m_inputChannels]; + for (size_t i = 0; i < m_inputChannels; ++i) { + m_deinterleave[i] = new float[m_blockSize]; + } + } + + for (size_t i = 0; i < m_inputChannels; ++i) { + for (size_t j = 0; j < m_blockSize; ++j) { + m_deinterleave[i][j] = inputBuffers[j * m_inputChannels + i]; + } + } + + return process(m_deinterleave, timestamp); +} + +PluginChannelAdapter::FeatureSet +PluginChannelAdapter::Impl::process(const float *const *inputBuffers, + RealTime timestamp) +{ +// std::cerr << "PluginChannelAdapter::process: " << m_inputChannels << " -> " << m_pluginChannels << " channels" << std::endl; + + if (m_inputChannels < m_pluginChannels) { + + if (m_inputChannels == 1) { + for (size_t i = 0; i < m_pluginChannels; ++i) { + m_forwardPtrs[i] = inputBuffers[0]; + } + } else { + for (size_t i = 0; i < m_inputChannels; ++i) { + m_forwardPtrs[i] = inputBuffers[i]; + } + for (size_t i = m_inputChannels; i < m_pluginChannels; ++i) { + m_forwardPtrs[i] = m_buffer[i - m_inputChannels]; + } + } + + return m_plugin->process(m_forwardPtrs, timestamp); + + } else if (m_inputChannels > m_pluginChannels) { + + if (m_pluginChannels == 1) { + for (size_t j = 0; j < m_blockSize; ++j) { + m_buffer[0][j] = inputBuffers[0][j]; + } + for (size_t i = 1; i < m_inputChannels; ++i) { + for (size_t j = 0; j < m_blockSize; ++j) { + m_buffer[0][j] += inputBuffers[i][j]; + } + } + for (size_t j = 0; j < m_blockSize; ++j) { + m_buffer[0][j] /= m_inputChannels; + } + return m_plugin->process(m_buffer, timestamp); + } else { + return m_plugin->process(inputBuffers, timestamp); + } + + } else { + + return m_plugin->process(inputBuffers, timestamp); + } +} + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginChannelAdapter.cpp) + + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginHostAdapter.cpp mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginHostAdapter.cpp --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginHostAdapter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginHostAdapter.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,456 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#include +#include + +#if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 3 ) +#error Unexpected version of Vamp SDK header included +#endif + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginHostAdapter.cpp) + +namespace Vamp +{ + +PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor, + float inputSampleRate) : + Plugin(inputSampleRate), + m_descriptor(descriptor) +{ +// std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl; + m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate); + if (!m_handle) { +// std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl; + } +} + +PluginHostAdapter::~PluginHostAdapter() +{ +// std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl; + if (m_handle) m_descriptor->cleanup(m_handle); +} + +std::vector +PluginHostAdapter::getPluginPath() +{ + std::vector path; + std::string envPath; + + char *cpath = getenv("VAMP_PATH"); + if (cpath) envPath = cpath; + +#ifdef _WIN32 +#define PATH_SEPARATOR ';' +#define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins" +#else +#define PATH_SEPARATOR ':' +#ifdef __APPLE__ +#define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp" +#else +#define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp" +#endif +#endif + + if (envPath == "") { + envPath = DEFAULT_VAMP_PATH; + char *chome = getenv("HOME"); + if (chome) { + std::string home(chome); + std::string::size_type f; + while ((f = envPath.find("$HOME")) != std::string::npos && + f < envPath.length()) { + envPath.replace(f, 5, home); + } + } +#ifdef _WIN32 + char *cpfiles = getenv("ProgramFiles"); + if (!cpfiles) cpfiles = (char *)"C:\\Program Files"; + std::string pfiles(cpfiles); + std::string::size_type f; + while ((f = envPath.find("%ProgramFiles%")) != std::string::npos && + f < envPath.length()) { + envPath.replace(f, 14, pfiles); + } +#endif + } + + std::string::size_type index = 0, newindex = 0; + + while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) { + path.push_back(envPath.substr(index, newindex - index)); + index = newindex + 1; + } + + path.push_back(envPath.substr(index)); + + return path; +} + +bool +PluginHostAdapter::initialise(size_t channels, + size_t stepSize, + size_t blockSize) +{ + if (!m_handle) return false; + return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ? + true : false; +} + +void +PluginHostAdapter::reset() +{ + if (!m_handle) { +// std::cerr << "PluginHostAdapter::reset: no handle" << std::endl; + return; + } +// std::cerr << "PluginHostAdapter::reset(" << m_handle << ")" << std::endl; + m_descriptor->reset(m_handle); +} + +PluginHostAdapter::InputDomain +PluginHostAdapter::getInputDomain() const +{ + if (m_descriptor->inputDomain == vampFrequencyDomain) { + return FrequencyDomain; + } else { + return TimeDomain; + } +} + +unsigned int +PluginHostAdapter::getVampApiVersion() const +{ + return m_descriptor->vampApiVersion; +} + +std::string +PluginHostAdapter::getIdentifier() const +{ + return m_descriptor->identifier; +} + +std::string +PluginHostAdapter::getName() const +{ + return m_descriptor->name; +} + +std::string +PluginHostAdapter::getDescription() const +{ + return m_descriptor->description; +} + +std::string +PluginHostAdapter::getMaker() const +{ + return m_descriptor->maker; +} + +int +PluginHostAdapter::getPluginVersion() const +{ + return m_descriptor->pluginVersion; +} + +std::string +PluginHostAdapter::getCopyright() const +{ + return m_descriptor->copyright; +} + +PluginHostAdapter::ParameterList +PluginHostAdapter::getParameterDescriptors() const +{ + ParameterList list; + for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) { + const VampParameterDescriptor *spd = m_descriptor->parameters[i]; + ParameterDescriptor pd; + pd.identifier = spd->identifier; + pd.name = spd->name; + pd.description = spd->description; + pd.unit = spd->unit; + pd.minValue = spd->minValue; + pd.maxValue = spd->maxValue; + pd.defaultValue = spd->defaultValue; + pd.isQuantized = spd->isQuantized; + pd.quantizeStep = spd->quantizeStep; + if (pd.isQuantized && spd->valueNames) { + for (unsigned int j = 0; spd->valueNames[j]; ++j) { + pd.valueNames.push_back(spd->valueNames[j]); + } + } + list.push_back(pd); + } + return list; +} + +float +PluginHostAdapter::getParameter(std::string param) const +{ + if (!m_handle) return 0.0; + + for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) { + if (param == m_descriptor->parameters[i]->identifier) { + return m_descriptor->getParameter(m_handle, i); + } + } + + return 0.0; +} + +void +PluginHostAdapter::setParameter(std::string param, + float value) +{ + if (!m_handle) return; + + for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) { + if (param == m_descriptor->parameters[i]->identifier) { + m_descriptor->setParameter(m_handle, i, value); + return; + } + } +} + +PluginHostAdapter::ProgramList +PluginHostAdapter::getPrograms() const +{ + ProgramList list; + + for (unsigned int i = 0; i < m_descriptor->programCount; ++i) { + list.push_back(m_descriptor->programs[i]); + } + + return list; +} + +std::string +PluginHostAdapter::getCurrentProgram() const +{ + if (!m_handle) return ""; + + int pn = m_descriptor->getCurrentProgram(m_handle); + return m_descriptor->programs[pn]; +} + +void +PluginHostAdapter::selectProgram(std::string program) +{ + if (!m_handle) return; + + for (unsigned int i = 0; i < m_descriptor->programCount; ++i) { + if (program == m_descriptor->programs[i]) { + m_descriptor->selectProgram(m_handle, i); + return; + } + } +} + +size_t +PluginHostAdapter::getPreferredStepSize() const +{ + if (!m_handle) return 0; + return m_descriptor->getPreferredStepSize(m_handle); +} + +size_t +PluginHostAdapter::getPreferredBlockSize() const +{ + if (!m_handle) return 0; + return m_descriptor->getPreferredBlockSize(m_handle); +} + +size_t +PluginHostAdapter::getMinChannelCount() const +{ + if (!m_handle) return 0; + return m_descriptor->getMinChannelCount(m_handle); +} + +size_t +PluginHostAdapter::getMaxChannelCount() const +{ + if (!m_handle) return 0; + return m_descriptor->getMaxChannelCount(m_handle); +} + +PluginHostAdapter::OutputList +PluginHostAdapter::getOutputDescriptors() const +{ + OutputList list; + if (!m_handle) { +// std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl; + return list; + } + + unsigned int count = m_descriptor->getOutputCount(m_handle); + + for (unsigned int i = 0; i < count; ++i) { + VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i); + OutputDescriptor d; + d.identifier = sd->identifier; + d.name = sd->name; + d.description = sd->description; + d.unit = sd->unit; + d.hasFixedBinCount = sd->hasFixedBinCount; + d.binCount = sd->binCount; + if (d.hasFixedBinCount && sd->binNames) { + for (unsigned int j = 0; j < sd->binCount; ++j) { + d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : ""); + } + } + d.hasKnownExtents = sd->hasKnownExtents; + d.minValue = sd->minValue; + d.maxValue = sd->maxValue; + d.isQuantized = sd->isQuantized; + d.quantizeStep = sd->quantizeStep; + + switch (sd->sampleType) { + case vampOneSamplePerStep: + d.sampleType = OutputDescriptor::OneSamplePerStep; break; + case vampFixedSampleRate: + d.sampleType = OutputDescriptor::FixedSampleRate; break; + case vampVariableSampleRate: + d.sampleType = OutputDescriptor::VariableSampleRate; break; + } + + d.sampleRate = sd->sampleRate; + + if (m_descriptor->vampApiVersion >= 2) { + d.hasDuration = sd->hasDuration; + } else { + d.hasDuration = false; + } + + list.push_back(d); + + m_descriptor->releaseOutputDescriptor(sd); + } + + return list; +} + +PluginHostAdapter::FeatureSet +PluginHostAdapter::process(const float *const *inputBuffers, + RealTime timestamp) +{ + FeatureSet fs; + if (!m_handle) return fs; + + int sec = timestamp.sec; + int nsec = timestamp.nsec; + + VampFeatureList *features = m_descriptor->process(m_handle, + inputBuffers, + sec, nsec); + + convertFeatures(features, fs); + m_descriptor->releaseFeatureSet(features); + return fs; +} + +PluginHostAdapter::FeatureSet +PluginHostAdapter::getRemainingFeatures() +{ + FeatureSet fs; + if (!m_handle) return fs; + + VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle); + + convertFeatures(features, fs); + m_descriptor->releaseFeatureSet(features); + return fs; +} + +void +PluginHostAdapter::convertFeatures(VampFeatureList *features, + FeatureSet &fs) +{ + if (!features) return; + + unsigned int outputs = m_descriptor->getOutputCount(m_handle); + + for (unsigned int i = 0; i < outputs; ++i) { + + VampFeatureList &list = features[i]; + + if (list.featureCount > 0) { + + Feature feature; + feature.values.reserve(list.features[0].v1.valueCount); + + for (unsigned int j = 0; j < list.featureCount; ++j) { + + feature.hasTimestamp = list.features[j].v1.hasTimestamp; + feature.timestamp = RealTime(list.features[j].v1.sec, + list.features[j].v1.nsec); + feature.hasDuration = false; + + if (m_descriptor->vampApiVersion >= 2) { + unsigned int j2 = j + list.featureCount; + feature.hasDuration = list.features[j2].v2.hasDuration; + feature.duration = RealTime(list.features[j2].v2.durationSec, + list.features[j2].v2.durationNsec); + } + + for (unsigned int k = 0; k < list.features[j].v1.valueCount; ++k) { + feature.values.push_back(list.features[j].v1.values[k]); + } + + if (list.features[j].v1.label) { + feature.label = list.features[j].v1.label; + } + + fs[i].push_back(feature); + + if (list.features[j].v1.valueCount > 0) { + feature.values.clear(); + } + + if (list.features[j].v1.label) { + feature.label = ""; + } + } + } + } +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginHostAdapter.cpp) + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginInputDomainAdapter.cpp mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginInputDomainAdapter.cpp --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginInputDomainAdapter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginInputDomainAdapter.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,730 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + + This file is based in part on Don Cross's public domain FFT + implementation. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#include + +// http://msdn.microsoft.com/en-us/library/4hwaceh6(v=vs.80).aspx +#define _USE_MATH_DEFINES +#include + +#include "Window.h" + + +/** + * If you want to compile using FFTW instead of the built-in FFT + * implementation for the PluginInputDomainAdapter, define HAVE_FFTW3 + * in the Makefile. + * + * Be aware that FFTW is licensed under the GPL -- unlike this SDK, + * which is provided under a more liberal BSD license in order to + * permit use in closed source applications. The use of FFTW would + * mean that your code would need to be licensed under the GPL as + * well. Do not define this symbol unless you understand and accept + * the implications of this. + * + * Parties such as Linux distribution packagers who redistribute this + * SDK for use in other programs should _not_ define this symbol, as + * it would change the effective licensing terms under which the SDK + * was available to third party developers. + * + * The default is not to use FFTW, and to use the built-in FFT instead. + * + * Note: The FFTW code uses FFTW_MEASURE, and so will perform badly on + * its first invocation unless the host has saved and restored FFTW + * wisdom (see the FFTW documentation). + */ +#ifdef HAVE_FFTW3 +#include +#endif + + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.cpp) + +namespace Vamp { + +namespace HostExt { + +class PluginInputDomainAdapter::Impl +{ +public: + Impl(Plugin *plugin, float inputSampleRate); + ~Impl(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + + void setProcessTimestampMethod(ProcessTimestampMethod m); + ProcessTimestampMethod getProcessTimestampMethod() const; + + RealTime getTimestampAdjustment() const; + + WindowType getWindowType() const; + void setWindowType(WindowType type); + +protected: + Plugin *m_plugin; + float m_inputSampleRate; + int m_channels; + int m_stepSize; + int m_blockSize; + float **m_freqbuf; + + double *m_ri; + + WindowType m_windowType; + Window *m_window; + + ProcessTimestampMethod m_method; + int m_processCount; + float **m_shiftBuffers; + +#ifdef HAVE_FFTW3 + fftw_plan m_plan; + fftw_complex *m_cbuf; +#else + double *m_ro; + double *m_io; + void fft(unsigned int n, bool inverse, + double *ri, double *ii, double *ro, double *io); +#endif + + FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp); + FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp); + + size_t makeBlockSizeAcceptable(size_t) const; + + Window::WindowType convertType(WindowType t) const; +}; + +PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) : + PluginWrapper(plugin) +{ + m_impl = new Impl(plugin, m_inputSampleRate); +} + +PluginInputDomainAdapter::~PluginInputDomainAdapter() +{ + delete m_impl; +} + +bool +PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + return m_impl->initialise(channels, stepSize, blockSize); +} + +void +PluginInputDomainAdapter::reset() +{ + m_impl->reset(); +} + +Plugin::InputDomain +PluginInputDomainAdapter::getInputDomain() const +{ + return TimeDomain; +} + +size_t +PluginInputDomainAdapter::getPreferredStepSize() const +{ + return m_impl->getPreferredStepSize(); +} + +size_t +PluginInputDomainAdapter::getPreferredBlockSize() const +{ + return m_impl->getPreferredBlockSize(); +} + +Plugin::FeatureSet +PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp) +{ + return m_impl->process(inputBuffers, timestamp); +} + +void +PluginInputDomainAdapter::setProcessTimestampMethod(ProcessTimestampMethod m) +{ + m_impl->setProcessTimestampMethod(m); +} + +PluginInputDomainAdapter::ProcessTimestampMethod +PluginInputDomainAdapter::getProcessTimestampMethod() const +{ + return m_impl->getProcessTimestampMethod(); +} + +RealTime +PluginInputDomainAdapter::getTimestampAdjustment() const +{ + return m_impl->getTimestampAdjustment(); +} + +PluginInputDomainAdapter::WindowType +PluginInputDomainAdapter::getWindowType() const +{ + return m_impl->getWindowType(); +} + +void +PluginInputDomainAdapter::setWindowType(WindowType w) +{ + m_impl->setWindowType(w); +} + + +PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) : + m_plugin(plugin), + m_inputSampleRate(inputSampleRate), + m_channels(0), + m_stepSize(0), + m_blockSize(0), + m_freqbuf(0), + m_ri(0), + m_windowType(HanningWindow), + m_window(0), + m_method(ShiftTimestamp), + m_processCount(0), + m_shiftBuffers(0), +#ifdef HAVE_FFTW3 + m_plan(0), + m_cbuf(0) +#else + m_ro(0), + m_io(0) +#endif +{ +} + +PluginInputDomainAdapter::Impl::~Impl() +{ + // the adapter will delete the plugin + + if (m_shiftBuffers) { + for (int c = 0; c < m_channels; ++c) { + delete[] m_shiftBuffers[c]; + } + delete[] m_shiftBuffers; + } + + if (m_channels > 0) { + for (int c = 0; c < m_channels; ++c) { + delete[] m_freqbuf[c]; + } + delete[] m_freqbuf; +#ifdef HAVE_FFTW3 + if (m_plan) { + fftw_destroy_plan(m_plan); + fftw_free(m_ri); + fftw_free(m_cbuf); + m_plan = 0; + } +#else + delete[] m_ri; + delete[] m_ro; + delete[] m_io; +#endif + + delete m_window; + } +} + +// for some visual studii apparently +#ifndef M_PI +#define M_PI 3.14159265358979232846 +#endif + +bool +PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (m_plugin->getInputDomain() == TimeDomain) { + + m_stepSize = int(stepSize); + m_blockSize = int(blockSize); + m_channels = int(channels); + + return m_plugin->initialise(channels, stepSize, blockSize); + } + + if (blockSize < 2) { + std::cerr << "ERROR: PluginInputDomainAdapter::initialise: blocksize < 2 not supported" << std::endl; + return false; + } + + if (blockSize & (blockSize-1)) { + std::cerr << "ERROR: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported" << std::endl; + return false; + } + + if (m_channels > 0) { + for (int c = 0; c < m_channels; ++c) { + delete[] m_freqbuf[c]; + } + delete[] m_freqbuf; +#ifdef HAVE_FFTW3 + if (m_plan) { + fftw_destroy_plan(m_plan); + fftw_free(m_ri); + fftw_free(m_cbuf); + m_plan = 0; + } +#else + delete[] m_ri; + delete[] m_ro; + delete[] m_io; +#endif + delete m_window; + } + + m_stepSize = int(stepSize); + m_blockSize = int(blockSize); + m_channels = int(channels); + + m_freqbuf = new float *[m_channels]; + for (int c = 0; c < m_channels; ++c) { + m_freqbuf[c] = new float[m_blockSize + 2]; + } + + m_window = new Window(convertType(m_windowType), m_blockSize); + +#ifdef HAVE_FFTW3 + m_ri = (double *)fftw_malloc(blockSize * sizeof(double)); + m_cbuf = (fftw_complex *)fftw_malloc((blockSize/2 + 1) * sizeof(fftw_complex)); + m_plan = fftw_plan_dft_r2c_1d(blockSize, m_ri, m_cbuf, FFTW_MEASURE); +#else + m_ri = new double[m_blockSize]; + m_ro = new double[m_blockSize]; + m_io = new double[m_blockSize]; +#endif + + m_processCount = 0; + + return m_plugin->initialise(channels, stepSize, blockSize); +} + +void +PluginInputDomainAdapter::Impl::reset() +{ + m_processCount = 0; + m_plugin->reset(); +} + +size_t +PluginInputDomainAdapter::Impl::getPreferredStepSize() const +{ + size_t step = m_plugin->getPreferredStepSize(); + + if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) { + step = getPreferredBlockSize() / 2; + } + + return step; +} + +size_t +PluginInputDomainAdapter::Impl::getPreferredBlockSize() const +{ + size_t block = m_plugin->getPreferredBlockSize(); + + if (m_plugin->getInputDomain() == FrequencyDomain) { + if (block == 0) { + block = 1024; + } else { + block = makeBlockSizeAcceptable(block); + } + } + + return block; +} + +size_t +PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const +{ + if (blockSize < 2) { + + std::cerr << "WARNING: PluginInputDomainAdapter::initialise: blocksize < 2 not" << std::endl + << "supported, increasing from " << blockSize << " to 2" << std::endl; + blockSize = 2; + + } else if (blockSize & (blockSize-1)) { + +#ifdef HAVE_FFTW3 + // not an issue with FFTW +#else + + // not a power of two, can't handle that with our built-in FFT + // implementation + + size_t nearest = blockSize; + size_t power = 0; + while (nearest > 1) { + nearest >>= 1; + ++power; + } + nearest = 1; + while (power) { + nearest <<= 1; + --power; + } + + if (blockSize - nearest > (nearest*2) - blockSize) { + nearest = nearest*2; + } + + std::cerr << "WARNING: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported, using blocksize " << nearest << " instead" << std::endl; + blockSize = nearest; + +#endif + } + + return blockSize; +} + +RealTime +PluginInputDomainAdapter::Impl::getTimestampAdjustment() const +{ + if (m_plugin->getInputDomain() == TimeDomain) { + return RealTime::zeroTime; + } else if (m_method == ShiftData || m_method == NoShift) { + return RealTime::zeroTime; + } else { + return RealTime::frame2RealTime + (m_blockSize/2, int(m_inputSampleRate + 0.5)); + } +} + +void +PluginInputDomainAdapter::Impl::setProcessTimestampMethod(ProcessTimestampMethod m) +{ + m_method = m; +} + +PluginInputDomainAdapter::ProcessTimestampMethod +PluginInputDomainAdapter::Impl::getProcessTimestampMethod() const +{ + return m_method; +} + +void +PluginInputDomainAdapter::Impl::setWindowType(WindowType t) +{ + if (m_windowType == t) return; + m_windowType = t; + if (m_window) { + delete m_window; + m_window = new Window(convertType(m_windowType), m_blockSize); + } +} + +PluginInputDomainAdapter::WindowType +PluginInputDomainAdapter::Impl::getWindowType() const +{ + return m_windowType; +} + +Window::WindowType +PluginInputDomainAdapter::Impl::convertType(WindowType t) const +{ + switch (t) { + case RectangularWindow: + return Window::RectangularWindow; + case BartlettWindow: + return Window::BartlettWindow; + case HammingWindow: + return Window::HammingWindow; + case HanningWindow: + return Window::HanningWindow; + case BlackmanWindow: + return Window::BlackmanWindow; + case NuttallWindow: + return Window::NuttallWindow; + case BlackmanHarrisWindow: + return Window::BlackmanHarrisWindow; + default: + return Window::HanningWindow; + } +} + +Plugin::FeatureSet +PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers, + RealTime timestamp) +{ + if (m_plugin->getInputDomain() == TimeDomain) { + return m_plugin->process(inputBuffers, timestamp); + } + + if (m_method == ShiftTimestamp || m_method == NoShift) { + return processShiftingTimestamp(inputBuffers, timestamp); + } else { + return processShiftingData(inputBuffers, timestamp); + } +} + +Plugin::FeatureSet +PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers, + RealTime timestamp) +{ + if (m_method == ShiftTimestamp) { + timestamp = timestamp + getTimestampAdjustment(); + } + + for (int c = 0; c < m_channels; ++c) { + + m_window->cut(inputBuffers[c], m_ri); + + for (int i = 0; i < m_blockSize/2; ++i) { + // FFT shift + double value = m_ri[i]; + m_ri[i] = m_ri[i + m_blockSize/2]; + m_ri[i + m_blockSize/2] = value; + } + +#ifdef HAVE_FFTW3 + fftw_execute(m_plan); + + for (int i = 0; i <= m_blockSize/2; ++i) { + m_freqbuf[c][i * 2] = float(m_cbuf[i][0]); + m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]); + } +#else + fft(m_blockSize, false, m_ri, 0, m_ro, m_io); + + for (int i = 0; i <= m_blockSize/2; ++i) { + m_freqbuf[c][i * 2] = float(m_ro[i]); + m_freqbuf[c][i * 2 + 1] = float(m_io[i]); + } +#endif + } + + return m_plugin->process(m_freqbuf, timestamp); +} + +Plugin::FeatureSet +PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers, + RealTime timestamp) +{ + if (m_processCount == 0) { + if (!m_shiftBuffers) { + m_shiftBuffers = new float *[m_channels]; + for (int c = 0; c < m_channels; ++c) { + m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2]; + } + } + for (int c = 0; c < m_channels; ++c) { + for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) { + m_shiftBuffers[c][i] = 0.f; + } + } + } + + for (int c = 0; c < m_channels; ++c) { + for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) { + m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i]; + } + for (int i = 0; i < m_blockSize; ++i) { + m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i]; + } + } + + for (int c = 0; c < m_channels; ++c) { + + m_window->cut(m_shiftBuffers[c], m_ri); + + for (int i = 0; i < m_blockSize/2; ++i) { + // FFT shift + double value = m_ri[i]; + m_ri[i] = m_ri[i + m_blockSize/2]; + m_ri[i + m_blockSize/2] = value; + } + +#ifdef HAVE_FFTW3 + fftw_execute(m_plan); + + for (int i = 0; i <= m_blockSize/2; ++i) { + m_freqbuf[c][i * 2] = float(m_cbuf[i][0]); + m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]); + } +#else + fft(m_blockSize, false, m_ri, 0, m_ro, m_io); + + for (int i = 0; i <= m_blockSize/2; ++i) { + m_freqbuf[c][i * 2] = float(m_ro[i]); + m_freqbuf[c][i * 2 + 1] = float(m_io[i]); + } +#endif + } + + ++m_processCount; + + return m_plugin->process(m_freqbuf, timestamp); +} + +#ifndef HAVE_FFTW3 + +void +PluginInputDomainAdapter::Impl::fft(unsigned int n, bool inverse, + double *ri, double *ii, double *ro, double *io) +{ + if (!ri || !ro || !io) return; + + unsigned int bits; + unsigned int i, j, k, m; + unsigned int blockSize, blockEnd; + + double tr, ti; + + if (n < 2) return; + if (n & (n-1)) return; + + double angle = 2.0 * M_PI; + if (inverse) angle = -angle; + + for (i = 0; ; ++i) { + if (n & (1 << i)) { + bits = i; + break; + } + } + + static unsigned int tableSize = 0; + static int *table = 0; + + if (tableSize != n) { + + delete[] table; + + table = new int[n]; + + for (i = 0; i < n; ++i) { + + m = i; + + for (j = k = 0; j < bits; ++j) { + k = (k << 1) | (m & 1); + m >>= 1; + } + + table[i] = k; + } + + tableSize = n; + } + + if (ii) { + for (i = 0; i < n; ++i) { + ro[table[i]] = ri[i]; + io[table[i]] = ii[i]; + } + } else { + for (i = 0; i < n; ++i) { + ro[table[i]] = ri[i]; + io[table[i]] = 0.0; + } + } + + blockEnd = 1; + + for (blockSize = 2; blockSize <= n; blockSize <<= 1) { + + double delta = angle / (double)blockSize; + double sm2 = -sin(-2 * delta); + double sm1 = -sin(-delta); + double cm2 = cos(-2 * delta); + double cm1 = cos(-delta); + double w = 2 * cm1; + double ar[3], ai[3]; + + for (i = 0; i < n; i += blockSize) { + + ar[2] = cm2; + ar[1] = cm1; + + ai[2] = sm2; + ai[1] = sm1; + + for (j = i, m = 0; m < blockEnd; j++, m++) { + + ar[0] = w * ar[1] - ar[2]; + ar[2] = ar[1]; + ar[1] = ar[0]; + + ai[0] = w * ai[1] - ai[2]; + ai[2] = ai[1]; + ai[1] = ai[0]; + + k = j + blockEnd; + tr = ar[0] * ro[k] - ai[0] * io[k]; + ti = ar[0] * io[k] + ai[0] * ro[k]; + + ro[k] = ro[j] - tr; + io[k] = io[j] - ti; + + ro[j] += tr; + io[j] += ti; + } + } + + blockEnd = blockSize; + } + + if (inverse) { + + double denom = (double)n; + + for (i = 0; i < n; i++) { + ro[i] /= denom; + io[i] /= denom; + } + } +} + +#endif + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginInputDomainAdapter.cpp) + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginLoader.cpp mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginLoader.cpp --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginLoader.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginLoader.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,705 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#include +#include +#include +#include +#include + +#include +#include // tolower + +#include + +#ifdef _WIN32 + +#include +#include +#define PLUGIN_SUFFIX "dll" + +#else /* ! _WIN32 */ + +#include +#include + +#ifdef __APPLE__ +#define PLUGIN_SUFFIX "dylib" +#else /* ! __APPLE__ */ +#define PLUGIN_SUFFIX "so" +#endif /* ! __APPLE__ */ + +#endif /* ! _WIN32 */ + +using namespace std; + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginLoader.cpp) + +namespace Vamp { + +namespace HostExt { + +class PluginLoader::Impl +{ +public: + Impl(); + virtual ~Impl(); + + PluginKeyList listPlugins(); + + Plugin *loadPlugin(PluginKey key, + float inputSampleRate, + int adapterFlags); + + PluginKey composePluginKey(string libraryName, string identifier); + + PluginCategoryHierarchy getPluginCategory(PluginKey key); + + string getLibraryPathForPlugin(PluginKey key); + + static void setInstanceToClean(PluginLoader *instance); + +protected: + class PluginDeletionNotifyAdapter : public PluginWrapper { + public: + PluginDeletionNotifyAdapter(Plugin *plugin, Impl *loader); + virtual ~PluginDeletionNotifyAdapter(); + protected: + Impl *m_loader; + }; + + class InstanceCleaner { + public: + InstanceCleaner() : m_instance(0) { } + ~InstanceCleaner() { delete m_instance; } + void setInstance(PluginLoader *instance) { m_instance = instance; } + protected: + PluginLoader *m_instance; + }; + + virtual void pluginDeleted(PluginDeletionNotifyAdapter *adapter); + + map m_pluginLibraryNameMap; + bool m_allPluginsEnumerated; + void enumeratePlugins(PluginKey forPlugin = ""); + + map m_taxonomy; + void generateTaxonomy(); + + map m_pluginLibraryHandleMap; + + bool decomposePluginKey(PluginKey key, + string &libraryName, string &identifier); + + void *loadLibrary(string path); + void unloadLibrary(void *handle); + void *lookupInLibrary(void *handle, const char *symbol); + + string splicePath(string a, string b); + vector listFiles(string dir, string ext); + + static InstanceCleaner m_cleaner; +}; + +PluginLoader * +PluginLoader::m_instance = 0; + +PluginLoader::Impl::InstanceCleaner +PluginLoader::Impl::m_cleaner; + +PluginLoader::PluginLoader() +{ + m_impl = new Impl(); +} + +PluginLoader::~PluginLoader() +{ + delete m_impl; +} + +PluginLoader * +PluginLoader::getInstance() +{ + if (!m_instance) { + // The cleaner doesn't own the instance, because we leave the + // instance pointer in the base class for binary backwards + // compatibility reasons and to avoid waste + m_instance = new PluginLoader(); + Impl::setInstanceToClean(m_instance); + } + return m_instance; +} + +vector +PluginLoader::listPlugins() +{ + return m_impl->listPlugins(); +} + +Plugin * +PluginLoader::loadPlugin(PluginKey key, + float inputSampleRate, + int adapterFlags) +{ + return m_impl->loadPlugin(key, inputSampleRate, adapterFlags); +} + +PluginLoader::PluginKey +PluginLoader::composePluginKey(string libraryName, string identifier) +{ + return m_impl->composePluginKey(libraryName, identifier); +} + +PluginLoader::PluginCategoryHierarchy +PluginLoader::getPluginCategory(PluginKey key) +{ + return m_impl->getPluginCategory(key); +} + +string +PluginLoader::getLibraryPathForPlugin(PluginKey key) +{ + return m_impl->getLibraryPathForPlugin(key); +} + +PluginLoader::Impl::Impl() : + m_allPluginsEnumerated(false) +{ +} + +PluginLoader::Impl::~Impl() +{ +} + +void +PluginLoader::Impl::setInstanceToClean(PluginLoader *instance) +{ + m_cleaner.setInstance(instance); +} + +vector +PluginLoader::Impl::listPlugins() +{ + if (!m_allPluginsEnumerated) enumeratePlugins(); + + vector plugins; + for (map::iterator mi = m_pluginLibraryNameMap.begin(); + mi != m_pluginLibraryNameMap.end(); ++mi) { + plugins.push_back(mi->first); + } + + return plugins; +} + +void +PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin) +{ + vector path = PluginHostAdapter::getPluginPath(); + + string libraryName, identifier; + if (forPlugin != "") { + if (!decomposePluginKey(forPlugin, libraryName, identifier)) { + std::cerr << "WARNING: Vamp::HostExt::PluginLoader: Invalid plugin key \"" + << forPlugin << "\" in enumerate" << std::endl; + return; + } + } + + for (size_t i = 0; i < path.size(); ++i) { + + vector files = listFiles(path[i], PLUGIN_SUFFIX); + + for (vector::iterator fi = files.begin(); + fi != files.end(); ++fi) { + + if (libraryName != "") { + // libraryName is lowercased and lacking an extension, + // as it came from the plugin key + string temp = *fi; + for (size_t i = 0; i < temp.length(); ++i) { + temp[i] = tolower(temp[i]); + } + string::size_type pi = temp.find('.'); + if (pi == string::npos) { + if (libraryName != temp) continue; + } else { + if (libraryName != temp.substr(0, pi)) continue; + } + } + + string fullPath = path[i]; + fullPath = splicePath(fullPath, *fi); + void *handle = loadLibrary(fullPath); + if (!handle) continue; + + VampGetPluginDescriptorFunction fn = + (VampGetPluginDescriptorFunction)lookupInLibrary + (handle, "vampGetPluginDescriptor"); + + if (!fn) { + if (forPlugin != "") { + cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \"" + << fullPath << "\"" << endl; + } + unloadLibrary(handle); + continue; + } + + int index = 0; + const VampPluginDescriptor *descriptor = 0; + bool found = false; + + while ((descriptor = fn(VAMP_API_VERSION, index))) { + ++index; + if (identifier != "") { + if (descriptor->identifier != identifier) continue; + } + found = true; + PluginKey key = composePluginKey(*fi, descriptor->identifier); +// std::cerr << "enumerate: " << key << " (path: " << fullPath << ")" << std::endl; + if (m_pluginLibraryNameMap.find(key) == + m_pluginLibraryNameMap.end()) { + m_pluginLibraryNameMap[key] = fullPath; + } + } + + if (!found && forPlugin != "") { + cerr << "Vamp::HostExt::PluginLoader: Plugin \"" + << identifier << "\" not found in library \"" + << fullPath << "\"" << endl; + } + + unloadLibrary(handle); + } + } + + if (forPlugin == "") m_allPluginsEnumerated = true; +} + +PluginLoader::PluginKey +PluginLoader::Impl::composePluginKey(string libraryName, string identifier) +{ + string basename = libraryName; + + string::size_type li = basename.rfind('/'); + if (li != string::npos) basename = basename.substr(li + 1); + + li = basename.find('.'); + if (li != string::npos) basename = basename.substr(0, li); + + for (size_t i = 0; i < basename.length(); ++i) { + basename[i] = tolower(basename[i]); + } + + return basename + ":" + identifier; +} + +bool +PluginLoader::Impl::decomposePluginKey(PluginKey key, + string &libraryName, + string &identifier) +{ + string::size_type ki = key.find(':'); + if (ki == string::npos) { + return false; + } + + libraryName = key.substr(0, ki); + identifier = key.substr(ki + 1); + return true; +} + +PluginLoader::PluginCategoryHierarchy +PluginLoader::Impl::getPluginCategory(PluginKey plugin) +{ + if (m_taxonomy.empty()) generateTaxonomy(); + if (m_taxonomy.find(plugin) == m_taxonomy.end()) { + return PluginCategoryHierarchy(); + } + return m_taxonomy[plugin]; +} + +string +PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin) +{ + if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) { + if (m_allPluginsEnumerated) return ""; + enumeratePlugins(plugin); + } + if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) { + return ""; + } + return m_pluginLibraryNameMap[plugin]; +} + +Plugin * +PluginLoader::Impl::loadPlugin(PluginKey key, + float inputSampleRate, int adapterFlags) +{ + string libname, identifier; + if (!decomposePluginKey(key, libname, identifier)) { + std::cerr << "Vamp::HostExt::PluginLoader: Invalid plugin key \"" + << key << "\" in loadPlugin" << std::endl; + return 0; + } + + string fullPath = getLibraryPathForPlugin(key); + if (fullPath == "") { + std::cerr << "Vamp::HostExt::PluginLoader: No library found in Vamp path for plugin \"" << key << "\"" << std::endl; + return 0; + } + + void *handle = loadLibrary(fullPath); + if (!handle) return 0; + + VampGetPluginDescriptorFunction fn = + (VampGetPluginDescriptorFunction)lookupInLibrary + (handle, "vampGetPluginDescriptor"); + + if (!fn) { + cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \"" + << fullPath << "\"" << endl; + unloadLibrary(handle); + return 0; + } + + int index = 0; + const VampPluginDescriptor *descriptor = 0; + + while ((descriptor = fn(VAMP_API_VERSION, index))) { + + if (string(descriptor->identifier) == identifier) { + + Vamp::PluginHostAdapter *plugin = + new Vamp::PluginHostAdapter(descriptor, inputSampleRate); + + Plugin *adapter = new PluginDeletionNotifyAdapter(plugin, this); + + m_pluginLibraryHandleMap[adapter] = handle; + + if (adapterFlags & ADAPT_INPUT_DOMAIN) { + if (adapter->getInputDomain() == Plugin::FrequencyDomain) { + adapter = new PluginInputDomainAdapter(adapter); + } + } + + if (adapterFlags & ADAPT_BUFFER_SIZE) { + adapter = new PluginBufferingAdapter(adapter); + } + + if (adapterFlags & ADAPT_CHANNEL_COUNT) { + adapter = new PluginChannelAdapter(adapter); + } + + return adapter; + } + + ++index; + } + + cerr << "Vamp::HostExt::PluginLoader: Plugin \"" + << identifier << "\" not found in library \"" + << fullPath << "\"" << endl; + + return 0; +} + +void +PluginLoader::Impl::generateTaxonomy() +{ +// cerr << "PluginLoader::Impl::generateTaxonomy" << endl; + + vector path = PluginHostAdapter::getPluginPath(); + string libfragment = "/lib/"; + vector catpath; + + string suffix = "cat"; + + for (vector::iterator i = path.begin(); + i != path.end(); ++i) { + + // It doesn't matter that we're using literal forward-slash in + // this bit, as it's only relevant if the path contains + // "/lib/", which is only meaningful and only plausible on + // systems with forward-slash delimiters + + string dir = *i; + string::size_type li = dir.find(libfragment); + + if (li != string::npos) { + catpath.push_back + (dir.substr(0, li) + + "/share/" + + dir.substr(li + libfragment.length())); + } + + catpath.push_back(dir); + } + + char buffer[1024]; + + for (vector::iterator i = catpath.begin(); + i != catpath.end(); ++i) { + + vector files = listFiles(*i, suffix); + + for (vector::iterator fi = files.begin(); + fi != files.end(); ++fi) { + + string filepath = splicePath(*i, *fi); + ifstream is(filepath.c_str(), ifstream::in | ifstream::binary); + + if (is.fail()) { +// cerr << "failed to open: " << filepath << endl; + continue; + } + +// cerr << "opened: " << filepath << endl; + + while (!!is.getline(buffer, 1024)) { + + string line(buffer); + +// cerr << "line = " << line << endl; + + string::size_type di = line.find("::"); + if (di == string::npos) continue; + + string id = line.substr(0, di); + string encodedCat = line.substr(di + 2); + + if (id.substr(0, 5) != "vamp:") continue; + id = id.substr(5); + + while (encodedCat.length() >= 1 && + encodedCat[encodedCat.length()-1] == '\r') { + encodedCat = encodedCat.substr(0, encodedCat.length()-1); + } + +// cerr << "id = " << id << ", cat = " << encodedCat << endl; + + PluginCategoryHierarchy category; + string::size_type ai; + while ((ai = encodedCat.find(" > ")) != string::npos) { + category.push_back(encodedCat.substr(0, ai)); + encodedCat = encodedCat.substr(ai + 3); + } + if (encodedCat != "") category.push_back(encodedCat); + + m_taxonomy[id] = category; + } + } + } +} + +void * +PluginLoader::Impl::loadLibrary(string path) +{ + void *handle = 0; +#ifdef _WIN32 +#ifdef UNICODE + int len = path.length() + 1; // cannot be more wchars than length in bytes of utf8 string + wchar_t *buffer = new wchar_t[len]; + int rv = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), len, buffer, len); + if (rv <= 0) { + cerr << "Vamp::HostExt::PluginLoader: Unable to convert library path \"" + << path << "\" to wide characters " << endl; + delete[] buffer; + return handle; + } + handle = LoadLibrary(buffer); + delete[] buffer; +#else + handle = LoadLibrary(path.c_str()); +#endif + if (!handle) { + cerr << "Vamp::HostExt::PluginLoader: Unable to load library \"" + << path << "\"" << endl; + } +#else + handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL); + if (!handle) { + cerr << "Vamp::HostExt::PluginLoader: Unable to load library \"" + << path << "\": " << dlerror() << endl; + } +#endif + return handle; +} + +void +PluginLoader::Impl::unloadLibrary(void *handle) +{ +#ifdef _WIN32 + FreeLibrary((HINSTANCE)handle); +#else + dlclose(handle); +#endif +} + +void * +PluginLoader::Impl::lookupInLibrary(void *handle, const char *symbol) +{ +#ifdef _WIN32 + return (void *)GetProcAddress((HINSTANCE)handle, symbol); +#else + return (void *)dlsym(handle, symbol); +#endif +} + +string +PluginLoader::Impl::splicePath(string a, string b) +{ +#ifdef _WIN32 + return a + "\\" + b; +#else + return a + "/" + b; +#endif +} + +vector +PluginLoader::Impl::listFiles(string dir, string extension) +{ + vector files; + +#ifdef _WIN32 + string expression = dir + "\\*." + extension; +#ifdef UNICODE + int len = expression.length() + 1; // cannot be more wchars than length in bytes of utf8 string + wchar_t *buffer = new wchar_t[len]; + int rv = MultiByteToWideChar(CP_UTF8, 0, expression.c_str(), len, buffer, len); + if (rv <= 0) { + cerr << "Vamp::HostExt::PluginLoader: Unable to convert wildcard path \"" + << expression << "\" to wide characters" << endl; + delete[] buffer; + return files; + } + WIN32_FIND_DATA data; + HANDLE fh = FindFirstFile(buffer, &data); + if (fh == INVALID_HANDLE_VALUE) { + delete[] buffer; + return files; + } + + bool ok = true; + while (ok) { + wchar_t *fn = data.cFileName; + int wlen = wcslen(fn) + 1; + int maxlen = wlen * 6; + char *conv = new char[maxlen]; + int rv = WideCharToMultiByte(CP_UTF8, 0, fn, wlen, conv, maxlen, 0, 0); + if (rv > 0) { + files.push_back(conv); + } + delete[] conv; + ok = FindNextFile(fh, &data); + } + + FindClose(fh); + delete[] buffer; +#else + WIN32_FIND_DATA data; + HANDLE fh = FindFirstFile(expression.c_str(), &data); + if (fh == INVALID_HANDLE_VALUE) return files; + + bool ok = true; + while (ok) { + files.push_back(data.cFileName); + ok = FindNextFile(fh, &data); + } + + FindClose(fh); +#endif +#else + + size_t extlen = extension.length(); + DIR *d = opendir(dir.c_str()); + if (!d) return files; + + struct dirent *e = 0; + while ((e = readdir(d))) { + + if (!e->d_name) continue; + + size_t len = strlen(e->d_name); + if (len < extlen + 2 || + e->d_name + len - extlen - 1 != "." + extension) { + continue; + } + + files.push_back(e->d_name); + } + + closedir(d); +#endif + + return files; +} + +void +PluginLoader::Impl::pluginDeleted(PluginDeletionNotifyAdapter *adapter) +{ + void *handle = m_pluginLibraryHandleMap[adapter]; + if (handle) unloadLibrary(handle); + m_pluginLibraryHandleMap.erase(adapter); +} + +PluginLoader::Impl::PluginDeletionNotifyAdapter::PluginDeletionNotifyAdapter(Plugin *plugin, + Impl *loader) : + PluginWrapper(plugin), + m_loader(loader) +{ +} + +PluginLoader::Impl::PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter() +{ + // We need to delete the plugin before calling pluginDeleted, as + // the delete call may require calling through to the descriptor + // (for e.g. cleanup) but pluginDeleted may unload the required + // library for the call. To prevent a double deletion when our + // parent's destructor runs (after this one), be sure to set + // m_plugin to 0 after deletion. + delete m_plugin; + m_plugin = 0; + + if (m_loader) m_loader->pluginDeleted(this); +} + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginLoader.cpp) + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginSummarisingAdapter.cpp mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginSummarisingAdapter.cpp --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginSummarisingAdapter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginSummarisingAdapter.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,954 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#include + +#include +#include +// http://msdn.microsoft.com/en-us/library/4hwaceh6(v=vs.80).aspx +#define _USE_MATH_DEFINES +#include +#include + +//#define DEBUG_PLUGIN_SUMMARISING_ADAPTER 1 +//#define DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT 1 + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginSummarisingAdapter.cpp) + +namespace Vamp { + +namespace HostExt { + +class PluginSummarisingAdapter::Impl +{ +public: + Impl(Plugin *plugin, float inputSampleRate); + ~Impl(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + + void reset(); + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + FeatureSet getRemainingFeatures(); + + void setSummarySegmentBoundaries(const SegmentBoundaries &); + + FeatureList getSummaryForOutput(int output, + SummaryType type, + AveragingMethod avg); + + FeatureSet getSummaryForAllOutputs(SummaryType type, + AveragingMethod avg); + +protected: + Plugin *m_plugin; + float m_inputSampleRate; + size_t m_stepSize; + size_t m_blockSize; + + SegmentBoundaries m_boundaries; + + typedef std::vector ValueList; + + struct Result { // smaller than Feature + RealTime time; + RealTime duration; + ValueList values; // bin number -> value + }; + + typedef std::vector ResultList; + + struct OutputAccumulator { + int bins; + ResultList results; + OutputAccumulator() : bins(0) { } + }; + + typedef std::map OutputAccumulatorMap; + OutputAccumulatorMap m_accumulators; // output number -> accumulator + + typedef std::map SegmentAccumulatorMap; + typedef std::map OutputSegmentAccumulatorMap; + OutputSegmentAccumulatorMap m_segmentedAccumulators; // output -> segmented + + typedef std::map OutputTimestampMap; + OutputTimestampMap m_prevTimestamps; // output number -> timestamp + OutputTimestampMap m_prevDurations; // output number -> durations + + struct OutputBinSummary { + + int count; + + // extents + double minimum; + double maximum; + double sum; + + // sample-average results + double median; + double mode; + double variance; + + // continuous-time average results + double median_c; + double mode_c; + double mean_c; + double variance_c; + }; + + typedef std::map OutputSummary; + typedef std::map SummarySegmentMap; + typedef std::map OutputSummarySegmentMap; + + OutputSummarySegmentMap m_summaries; + + bool m_reduced; + RealTime m_endTime; + + void accumulate(const FeatureSet &fs, RealTime, bool final); + void accumulate(int output, const Feature &f, RealTime, bool final); + void accumulateFinalDurations(); + void findSegmentBounds(RealTime t, RealTime &start, RealTime &end); + void segment(); + void reduce(); + + std::string getSummaryLabel(SummaryType type, AveragingMethod avg); +}; + +static RealTime INVALID_DURATION(INT_MIN, INT_MIN); + +PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin *plugin) : + PluginWrapper(plugin) +{ + m_impl = new Impl(plugin, m_inputSampleRate); +} + +PluginSummarisingAdapter::~PluginSummarisingAdapter() +{ + delete m_impl; +} + +bool +PluginSummarisingAdapter::initialise(size_t channels, + size_t stepSize, size_t blockSize) +{ + return + PluginWrapper::initialise(channels, stepSize, blockSize) && + m_impl->initialise(channels, stepSize, blockSize); +} + +void +PluginSummarisingAdapter::reset() +{ + m_impl->reset(); +} + +Plugin::FeatureSet +PluginSummarisingAdapter::process(const float *const *inputBuffers, RealTime timestamp) +{ + return m_impl->process(inputBuffers, timestamp); +} + +Plugin::FeatureSet +PluginSummarisingAdapter::getRemainingFeatures() +{ + return m_impl->getRemainingFeatures(); +} + +void +PluginSummarisingAdapter::setSummarySegmentBoundaries(const SegmentBoundaries &b) +{ + m_impl->setSummarySegmentBoundaries(b); +} + +Plugin::FeatureList +PluginSummarisingAdapter::getSummaryForOutput(int output, + SummaryType type, + AveragingMethod avg) +{ + return m_impl->getSummaryForOutput(output, type, avg); +} + +Plugin::FeatureSet +PluginSummarisingAdapter::getSummaryForAllOutputs(SummaryType type, + AveragingMethod avg) +{ + return m_impl->getSummaryForAllOutputs(type, avg); +} + +PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) : + m_plugin(plugin), + m_inputSampleRate(inputSampleRate), + m_reduced(false) +{ +} + +PluginSummarisingAdapter::Impl::~Impl() +{ +} + +bool +PluginSummarisingAdapter::Impl::initialise(size_t channels, + size_t stepSize, size_t blockSize) +{ + m_stepSize = stepSize; + m_blockSize = blockSize; + return true; +} + +void +PluginSummarisingAdapter::Impl::reset() +{ + m_accumulators.clear(); + m_segmentedAccumulators.clear(); + m_prevTimestamps.clear(); + m_prevDurations.clear(); + m_summaries.clear(); + m_reduced = false; + m_endTime = RealTime(); + m_plugin->reset(); +} + +Plugin::FeatureSet +PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers, + RealTime timestamp) +{ + if (m_reduced) { + std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl; + } + FeatureSet fs = m_plugin->process(inputBuffers, timestamp); + accumulate(fs, timestamp, false); + m_endTime = timestamp + + RealTime::frame2RealTime(m_stepSize, int(m_inputSampleRate + 0.5)); + return fs; +} + +Plugin::FeatureSet +PluginSummarisingAdapter::Impl::getRemainingFeatures() +{ + if (m_reduced) { + std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl; + } + FeatureSet fs = m_plugin->getRemainingFeatures(); + accumulate(fs, m_endTime, true); + return fs; +} + +void +PluginSummarisingAdapter::Impl::setSummarySegmentBoundaries(const SegmentBoundaries &b) +{ + m_boundaries = b; +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "PluginSummarisingAdapter::setSummarySegmentBoundaries: boundaries are:" << std::endl; + for (SegmentBoundaries::const_iterator i = m_boundaries.begin(); + i != m_boundaries.end(); ++i) { + std::cerr << *i << " "; + } + std::cerr << std::endl; +#endif +} + +Plugin::FeatureList +PluginSummarisingAdapter::Impl::getSummaryForOutput(int output, + SummaryType type, + AveragingMethod avg) +{ + if (!m_reduced) { + accumulateFinalDurations(); + segment(); + reduce(); + m_reduced = true; + } + + bool continuous = (avg == ContinuousTimeAverage); + + FeatureList fl; + for (SummarySegmentMap::const_iterator i = m_summaries[output].begin(); + i != m_summaries[output].end(); ++i) { + + Feature f; + + f.hasTimestamp = true; + f.timestamp = i->first; + + f.hasDuration = true; + SummarySegmentMap::const_iterator ii = i; + if (++ii == m_summaries[output].end()) { + f.duration = m_endTime - f.timestamp; + } else { + f.duration = ii->first - f.timestamp; + } + + f.label = getSummaryLabel(type, avg); + + for (OutputSummary::const_iterator j = i->second.begin(); + j != i->second.end(); ++j) { + + // these will be ordered by bin number, and no bin numbers + // will be missing except at the end (because of the way + // the accumulators were initially filled in accumulate()) + + const OutputBinSummary &summary = j->second; + double result = 0.f; + + switch (type) { + + case Minimum: + result = summary.minimum; + break; + + case Maximum: + result = summary.maximum; + break; + + case Mean: + if (continuous) { + result = summary.mean_c; + } else if (summary.count) { + result = summary.sum / summary.count; + } + break; + + case Median: + if (continuous) result = summary.median_c; + else result = summary.median; + break; + + case Mode: + if (continuous) result = summary.mode_c; + else result = summary.mode; + break; + + case Sum: + result = summary.sum; + break; + + case Variance: + if (continuous) result = summary.variance_c; + else result = summary.variance; + break; + + case StandardDeviation: + if (continuous) result = sqrtf(summary.variance_c); + else result = sqrtf(summary.variance); + break; + + case Count: + result = summary.count; + break; + + case UnknownSummaryType: + break; + + default: + break; + } + + f.values.push_back(result); + } + + fl.push_back(f); + } + return fl; +} + +Plugin::FeatureSet +PluginSummarisingAdapter::Impl::getSummaryForAllOutputs(SummaryType type, + AveragingMethod avg) +{ + if (!m_reduced) { + accumulateFinalDurations(); + segment(); + reduce(); + m_reduced = true; + } + + FeatureSet fs; + for (OutputSummarySegmentMap::const_iterator i = m_summaries.begin(); + i != m_summaries.end(); ++i) { + fs[i->first] = getSummaryForOutput(i->first, type, avg); + } + return fs; +} + +void +PluginSummarisingAdapter::Impl::accumulate(const FeatureSet &fs, + RealTime timestamp, + bool final) +{ + for (FeatureSet::const_iterator i = fs.begin(); i != fs.end(); ++i) { + for (FeatureList::const_iterator j = i->second.begin(); + j != i->second.end(); ++j) { + if (j->hasTimestamp) { + accumulate(i->first, *j, j->timestamp, final); + } else { + //!!! is this correct? + accumulate(i->first, *j, timestamp, final); + } + } + } +} + +std::string +PluginSummarisingAdapter::Impl::getSummaryLabel(SummaryType type, + AveragingMethod avg) +{ + std::string label; + std::string avglabel; + + if (avg == SampleAverage) avglabel = ", sample average"; + else avglabel = ", continuous-time average"; + + switch (type) { + case Minimum: label = "(minimum value)"; break; + case Maximum: label = "(maximum value)"; break; + case Mean: label = "(mean value" + avglabel + ")"; break; + case Median: label = "(median value" + avglabel + ")"; break; + case Mode: label = "(modal value" + avglabel + ")"; break; + case Sum: label = "(sum)"; break; + case Variance: label = "(variance" + avglabel + ")"; break; + case StandardDeviation: label = "(standard deviation" + avglabel + ")"; break; + case Count: label = "(count)"; break; + case UnknownSummaryType: label = "(unknown summary)"; break; + } + + return label; +} + +void +PluginSummarisingAdapter::Impl::accumulate(int output, + const Feature &f, + RealTime timestamp, + bool final) +{ + // What should happen if a feature's duration spans a segment + // boundary? I think we probably want to chop it, and pretend + // that it appears in both. A very long feature (e.g. key, if the + // whole audio is in a single key) might span many or all + // segments, and we want that to be reflected in the results + // (e.g. it is the modal key in all of those segments, not just + // the first). This is actually quite complicated to do. + + // If features spanning a boundary should be chopped, then we need + // to have per-segment accumulators (and the feature value goes + // into both -- with a separate phase to split the accumulator up + // into segments). + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << ", final " << final << std::endl; +#endif + + // At each process step, accumulate() is called once for each + // feature on each output within that process's returned feature + // list, and with the timestamp passed in being that of the start + // of the process block. + + // At the end (in getRemainingFeatures), accumulate() is called + // once for each feature on each output within the feature list + // returned by getRemainingFeatures, and with the timestamp being + // the same as the last process block and final set to true. + + // (What if getRemainingFeatures doesn't return any features? We + // still need to ensure that the final duration is written. Need + // a separate function to close the durations.) + + // At each call, we pull out the value for the feature and stuff + // it into the accumulator's appropriate values array; and we + // calculate the duration for the _previous_ feature, or pull it + // from the prevDurations array if the previous feature had a + // duration in its structure, and stuff that into the + // accumulator's appropriate durations array. + + if (m_prevDurations.find(output) != m_prevDurations.end()) { + + // Not the first time accumulate has been called for this + // output -- there has been a previous feature + + RealTime prevDuration; + + // Note that m_prevDurations[output] only contains the + // duration field that was contained in the previous feature. + // If it didn't have an explicit duration, + // m_prevDurations[output] should be INVALID_DURATION and we + // will have to calculate the duration from the previous and + // current timestamps. + + if (m_prevDurations[output] != INVALID_DURATION) { + prevDuration = m_prevDurations[output]; +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "Previous duration from previous feature: " << prevDuration << std::endl; +#endif + } else { + prevDuration = timestamp - m_prevTimestamps[output]; +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "Previous duration from diff: " << timestamp << " - " + << m_prevTimestamps[output] << std::endl; +#endif + } + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "output " << output << ": "; + std::cerr << "Pushing previous duration as " << prevDuration << std::endl; +#endif + + m_accumulators[output].results + [m_accumulators[output].results.size() - 1] + .duration = prevDuration; + } + + if (f.hasDuration) m_prevDurations[output] = f.duration; + else m_prevDurations[output] = INVALID_DURATION; + + m_prevTimestamps[output] = timestamp; + + if (f.hasDuration) { + RealTime et = timestamp; + et = et + f.duration; + if (et > m_endTime) m_endTime = et; + } + + Result result; + result.time = timestamp; + result.duration = INVALID_DURATION; + + if (int(f.values.size()) > m_accumulators[output].bins) { + m_accumulators[output].bins = f.values.size(); + } + + for (int i = 0; i < int(f.values.size()); ++i) { + result.values.push_back(f.values[i]); + } + + m_accumulators[output].results.push_back(result); +} + +void +PluginSummarisingAdapter::Impl::accumulateFinalDurations() +{ + for (OutputTimestampMap::iterator i = m_prevTimestamps.begin(); + i != m_prevTimestamps.end(); ++i) { + + int output = i->first; + + int acount = m_accumulators[output].results.size(); + + if (acount == 0) continue; + + RealTime prevTimestamp = i->second; + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "output " << output << ": "; +#endif + + if (m_prevDurations.find(output) != m_prevDurations.end() && + m_prevDurations[output] != INVALID_DURATION) { + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "Pushing final duration from feature as " << m_prevDurations[output] << std::endl; +#endif + + m_accumulators[output].results[acount - 1].duration = + m_prevDurations[output]; + + } else { + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "Pushing final duration from diff as " << m_endTime << " - " << m_prevTimestamps[output] << std::endl; +#endif + + m_accumulators[output].results[acount - 1].duration = + m_endTime - m_prevTimestamps[output]; + } + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "so duration for result no " << acount-1 << " is " + << m_accumulators[output].results[acount-1].duration + << std::endl; +#endif + } +} + +void +PluginSummarisingAdapter::Impl::findSegmentBounds(RealTime t, + RealTime &start, + RealTime &end) +{ +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT + std::cerr << "findSegmentBounds: t = " << t << std::endl; +#endif + + SegmentBoundaries::const_iterator i = std::upper_bound + (m_boundaries.begin(), m_boundaries.end(), t); + + start = RealTime::zeroTime; + end = m_endTime; + + if (i != m_boundaries.end()) { + end = *i; + } + + if (i != m_boundaries.begin()) { + start = *--i; + } + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT + std::cerr << "findSegmentBounds: " << t << " is in segment " << start << " -> " << end << std::endl; +#endif +} + +void +PluginSummarisingAdapter::Impl::segment() +{ + SegmentBoundaries::iterator boundaryitr = m_boundaries.begin(); + RealTime segmentStart = RealTime::zeroTime; + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT + std::cerr << "segment: starting" << std::endl; +#endif + + for (OutputAccumulatorMap::iterator i = m_accumulators.begin(); + i != m_accumulators.end(); ++i) { + + int output = i->first; + OutputAccumulator &source = i->second; + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT + std::cerr << "segment: total results for output " << output << " = " + << source.results.size() << std::endl; +#endif + + // This is basically nonsense if the results have no values + // (i.e. their times and counts are the only things of + // interest)... but perhaps it's the user's problem if they + // ask for segmentation (or any summary at all) in that case + + for (int n = 0; n < int(source.results.size()); ++n) { + + // This result spans source.results[n].time to + // source.results[n].time + source.results[n].duration. + // We need to dispose it into segments appropriately + + RealTime resultStart = source.results[n].time; + RealTime resultEnd = resultStart + source.results[n].duration; + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT + std::cerr << "output: " << output << ", result start = " << resultStart << ", end = " << resultEnd << std::endl; +#endif + + RealTime segmentStart = RealTime::zeroTime; + RealTime segmentEnd = resultEnd - RealTime(1, 0); + + RealTime prevSegmentStart = segmentStart - RealTime(1, 0); + + while (segmentEnd < resultEnd) { + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT + std::cerr << "segment end " << segmentEnd << " < result end " + << resultEnd << " (with result start " << resultStart << ")" << std::endl; +#endif + + findSegmentBounds(resultStart, segmentStart, segmentEnd); + + if (segmentStart == prevSegmentStart) { + // This can happen when we reach the end of the + // input, if a feature's end time overruns the + // input audio end time + break; + } + prevSegmentStart = segmentStart; + + RealTime chunkStart = resultStart; + if (chunkStart < segmentStart) chunkStart = segmentStart; + + RealTime chunkEnd = resultEnd; + if (chunkEnd > segmentEnd) chunkEnd = segmentEnd; + + m_segmentedAccumulators[output][segmentStart].bins = source.bins; + + Result chunk; + chunk.time = chunkStart; + chunk.duration = chunkEnd - chunkStart; + chunk.values = source.results[n].values; + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT + std::cerr << "chunk for segment " << segmentStart << ": from " << chunk.time << ", duration " << chunk.duration << std::endl; +#endif + + m_segmentedAccumulators[output][segmentStart].results + .push_back(chunk); + + resultStart = chunkEnd; + } + } + } +} + +struct ValueDurationFloatPair +{ + float value; + float duration; + + ValueDurationFloatPair() : value(0), duration(0) { } + ValueDurationFloatPair(float v, float d) : value(v), duration(d) { } + ValueDurationFloatPair &operator=(const ValueDurationFloatPair &p) { + value = p.value; + duration = p.duration; + return *this; + } + bool operator<(const ValueDurationFloatPair &p) const { + return value < p.value; + } +}; + +static double toSec(const RealTime &r) +{ + return r.sec + double(r.nsec) / 1000000000.0; +} + +void +PluginSummarisingAdapter::Impl::reduce() +{ + for (OutputSegmentAccumulatorMap::iterator i = + m_segmentedAccumulators.begin(); + i != m_segmentedAccumulators.end(); ++i) { + + int output = i->first; + SegmentAccumulatorMap &segments = i->second; + + for (SegmentAccumulatorMap::iterator j = segments.begin(); + j != segments.end(); ++j) { + + RealTime segmentStart = j->first; + OutputAccumulator &accumulator = j->second; + + int sz = accumulator.results.size(); + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "reduce: segment starting at " << segmentStart + << " on output " << output << " has " << sz << " result(s)" << std::endl; +#endif + + double totalDuration = 0.0; + //!!! is this right? + if (sz > 0) { +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "last time = " << accumulator.results[sz-1].time + << ", duration = " << accumulator.results[sz-1].duration + << " (step = " << m_stepSize << ", block = " << m_blockSize << ")" + << std::endl; +#endif + totalDuration = toSec((accumulator.results[sz-1].time + + accumulator.results[sz-1].duration) - + segmentStart); + } + + for (int bin = 0; bin < accumulator.bins; ++bin) { + + // work on all values over time for a single bin + + OutputBinSummary summary; + + summary.count = sz; + + summary.minimum = 0.f; + summary.maximum = 0.f; + + summary.median = 0.f; + summary.mode = 0.f; + summary.sum = 0.f; + summary.variance = 0.f; + + summary.median_c = 0.f; + summary.mode_c = 0.f; + summary.mean_c = 0.f; + summary.variance_c = 0.f; + + if (sz == 0) continue; + + std::vector valvec; + + for (int k = 0; k < sz; ++k) { + while (int(accumulator.results[k].values.size()) < + accumulator.bins) { + accumulator.results[k].values.push_back(0.f); + } + } + + for (int k = 0; k < sz; ++k) { + float value = accumulator.results[k].values[bin]; + valvec.push_back(ValueDurationFloatPair + (value, + toSec(accumulator.results[k].duration))); + } + + std::sort(valvec.begin(), valvec.end()); + + summary.minimum = valvec[0].value; + summary.maximum = valvec[sz-1].value; + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "total duration = " << totalDuration << std::endl; +#endif + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER +/* + std::cerr << "value vector for medians:" << std::endl; + for (int k = 0; k < sz; ++k) { + std::cerr << "(" << valvec[k].value << "," << valvec[k].duration << ") "; + } + std::cerr << std::endl; +*/ +#endif + + if (sz % 2 == 1) { + summary.median = valvec[sz/2].value; + } else { + summary.median = (valvec[sz/2].value + valvec[sz/2 + 1].value) / 2; + } + + double duracc = 0.0; + summary.median_c = valvec[sz-1].value; + + for (int k = 0; k < sz; ++k) { + duracc += valvec[k].duration; + if (duracc > totalDuration/2) { + summary.median_c = valvec[k].value; + break; + } + } + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "median_c = " << summary.median_c << std::endl; + std::cerr << "median = " << summary.median << std::endl; +#endif + + std::map distribution; + + for (int k = 0; k < sz; ++k) { + summary.sum += accumulator.results[k].values[bin]; + distribution[accumulator.results[k].values[bin]] += 1; + } + + int md = 0; + + for (std::map::iterator di = distribution.begin(); + di != distribution.end(); ++di) { + if (di->second > md) { + md = di->second; + summary.mode = di->first; + } + } + + distribution.clear(); + + std::map distribution_c; + + for (int k = 0; k < sz; ++k) { + distribution_c[accumulator.results[k].values[bin]] + += toSec(accumulator.results[k].duration); + } + + double mrd = 0.0; + + for (std::map::iterator di = distribution_c.begin(); + di != distribution_c.end(); ++di) { + if (di->second > mrd) { + mrd = di->second; + summary.mode_c = di->first; + } + } + + distribution_c.clear(); + + if (totalDuration > 0.0) { + + double sum_c = 0.0; + + for (int k = 0; k < sz; ++k) { + double value = accumulator.results[k].values[bin] + * toSec(accumulator.results[k].duration); + sum_c += value; + } + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "mean_c = " << sum_c << " / " << totalDuration << " = " + << sum_c / totalDuration << " (sz = " << sz << ")" << std::endl; +#endif + + summary.mean_c = sum_c / totalDuration; + + for (int k = 0; k < sz; ++k) { + double value = accumulator.results[k].values[bin]; +// * toSec(accumulator.results[k].duration); + summary.variance_c += + (value - summary.mean_c) * (value - summary.mean_c) + * toSec(accumulator.results[k].duration); + } + +// summary.variance_c /= summary.count; + summary.variance_c /= totalDuration; + } + + double mean = summary.sum / summary.count; + +#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER + std::cerr << "mean = " << summary.sum << " / " << summary.count << " = " + << summary.sum / summary.count << std::endl; +#endif + + for (int k = 0; k < sz; ++k) { + float value = accumulator.results[k].values[bin]; + summary.variance += (value - mean) * (value - mean); + } + summary.variance /= summary.count; + + m_summaries[output][segmentStart][bin] = summary; + } + } + } + + m_segmentedAccumulators.clear(); + m_accumulators.clear(); +} + + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginSummarisingAdapter.cpp) + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginWrapper.cpp mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginWrapper.cpp --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/PluginWrapper.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/PluginWrapper.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,204 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#include + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginWrapper.cpp) + +namespace Vamp { + +namespace HostExt { + +class PluginRateExtractor : public Plugin +{ +public: + PluginRateExtractor() : Plugin(0) { } + float getRate() const { return m_inputSampleRate; } +}; + +PluginWrapper::PluginWrapper(Plugin *plugin) : + Plugin(((PluginRateExtractor *)plugin)->getRate()), + m_plugin(plugin) +{ +} + +PluginWrapper::~PluginWrapper() +{ + delete m_plugin; +} + +bool +PluginWrapper::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + return m_plugin->initialise(channels, stepSize, blockSize); +} + +void +PluginWrapper::reset() +{ + m_plugin->reset(); +} + +Plugin::InputDomain +PluginWrapper::getInputDomain() const +{ + return m_plugin->getInputDomain(); +} + +unsigned int +PluginWrapper::getVampApiVersion() const +{ + return m_plugin->getVampApiVersion(); +} + +std::string +PluginWrapper::getIdentifier() const +{ + return m_plugin->getIdentifier(); +} + +std::string +PluginWrapper::getName() const +{ + return m_plugin->getName(); +} + +std::string +PluginWrapper::getDescription() const +{ + return m_plugin->getDescription(); +} + +std::string +PluginWrapper::getMaker() const +{ + return m_plugin->getMaker(); +} + +int +PluginWrapper::getPluginVersion() const +{ + return m_plugin->getPluginVersion(); +} + +std::string +PluginWrapper::getCopyright() const +{ + return m_plugin->getCopyright(); +} + +PluginBase::ParameterList +PluginWrapper::getParameterDescriptors() const +{ + return m_plugin->getParameterDescriptors(); +} + +float +PluginWrapper::getParameter(std::string parameter) const +{ + return m_plugin->getParameter(parameter); +} + +void +PluginWrapper::setParameter(std::string parameter, float value) +{ + m_plugin->setParameter(parameter, value); +} + +PluginBase::ProgramList +PluginWrapper::getPrograms() const +{ + return m_plugin->getPrograms(); +} + +std::string +PluginWrapper::getCurrentProgram() const +{ + return m_plugin->getCurrentProgram(); +} + +void +PluginWrapper::selectProgram(std::string program) +{ + m_plugin->selectProgram(program); +} + +size_t +PluginWrapper::getPreferredStepSize() const +{ + return m_plugin->getPreferredStepSize(); +} + +size_t +PluginWrapper::getPreferredBlockSize() const +{ + return m_plugin->getPreferredBlockSize(); +} + +size_t +PluginWrapper::getMinChannelCount() const +{ + return m_plugin->getMinChannelCount(); +} + +size_t PluginWrapper::getMaxChannelCount() const +{ + return m_plugin->getMaxChannelCount(); +} + +Plugin::OutputList +PluginWrapper::getOutputDescriptors() const +{ + return m_plugin->getOutputDescriptors(); +} + +Plugin::FeatureSet +PluginWrapper::process(const float *const *inputBuffers, RealTime timestamp) +{ + return m_plugin->process(inputBuffers, timestamp); +} + +Plugin::FeatureSet +PluginWrapper::getRemainingFeatures() +{ + return m_plugin->getRemainingFeatures(); +} + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginWrapper.cpp) diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/RealTime.cpp mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/RealTime.cpp --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/RealTime.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/RealTime.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,39 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#include +#include "../vamp-sdk/RealTime.cpp" + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/Window.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/Window.h --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-hostsdk/Window.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-hostsdk/Window.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,173 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2011 Chris Cannam and QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _WINDOW_H_ +#define _WINDOW_H_ + +#include + +// http://msdn.microsoft.com/en-us/library/4hwaceh6(v=vs.80).aspx +#define _USE_MATH_DEFINES +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +_VAMP_SDK_HOSTSPACE_BEGIN(Window.h) + +template +class Window +{ +public: + enum WindowType { + RectangularWindow, + BartlettWindow, + HammingWindow, + HanningWindow, + BlackmanWindow, + NuttallWindow, + BlackmanHarrisWindow + }; + + /** + * Construct a windower of the given type. + */ + Window(WindowType type, size_t size) : m_type(type), m_size(size) { encache(); } + Window(const Window &w) : m_type(w.m_type), m_size(w.m_size) { encache(); } + Window &operator=(const Window &w) { + if (&w == this) return *this; + m_type = w.m_type; + m_size = w.m_size; + encache(); + return *this; + } + virtual ~Window() { delete[] m_cache; } + + void cut(T *src) const { cut(src, src); } + void cut(T *src, T *dst) const { + for (size_t i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i]; + } + template + void cut(T0 *src, T *dst) const { + for (size_t i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i]; + } + + T getArea() { return m_area; } + T getValue(size_t i) { return m_cache[i]; } + + WindowType getType() const { return m_type; } + size_t getSize() const { return m_size; } + +protected: + WindowType m_type; + size_t m_size; + T *m_cache; + T m_area; + + void encache(); + void cosinewin(T *, T, T, T, T); +}; + +template +void Window::encache() +{ + int n = int(m_size); + T *mult = new T[n]; + int i; + for (i = 0; i < n; ++i) mult[i] = 1.0; + + switch (m_type) { + + case RectangularWindow: + for (i = 0; i < n; ++i) { + mult[i] *= 0.5; + } + break; + + case BartlettWindow: + for (i = 0; i < n/2; ++i) { + mult[i] *= (i / T(n/2)); + mult[i + n/2] *= (1.0 - (i / T(n/2))); + } + break; + + case HammingWindow: + cosinewin(mult, 0.54, 0.46, 0.0, 0.0); + break; + + case HanningWindow: + cosinewin(mult, 0.50, 0.50, 0.0, 0.0); + break; + + case BlackmanWindow: + cosinewin(mult, 0.42, 0.50, 0.08, 0.0); + break; + + case NuttallWindow: + cosinewin(mult, 0.3635819, 0.4891775, 0.1365995, 0.0106411); + break; + + case BlackmanHarrisWindow: + cosinewin(mult, 0.35875, 0.48829, 0.14128, 0.01168); + break; + } + + m_cache = mult; + + m_area = 0; + for (int i = 0; i < n; ++i) { + m_area += m_cache[i]; + } + m_area /= n; +} + +template +void Window::cosinewin(T *mult, T a0, T a1, T a2, T a3) +{ + int n = int(m_size); + for (int i = 0; i < n; ++i) { + mult[i] *= (a0 + - a1 * cos((2 * M_PI * i) / n) + + a2 * cos((4 * M_PI * i) / n) + - a3 * cos((6 * M_PI * i) / n)); + } +} + +_VAMP_SDK_HOSTSPACE_END(Window.h) + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-sdk/PluginAdapter.cpp mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-sdk/PluginAdapter.cpp --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-sdk/PluginAdapter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-sdk/PluginAdapter.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,919 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#include + +#include +#include + +#if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 3 ) +#error Unexpected version of Vamp SDK header included +#endif + + +//#define DEBUG_PLUGIN_ADAPTER 1 + +_VAMP_SDK_PLUGSPACE_BEGIN(PluginAdapter.cpp) + +namespace Vamp { + +class PluginAdapterBase::Impl +{ +public: + Impl(PluginAdapterBase *); + ~Impl(); + + const VampPluginDescriptor *getDescriptor(); + +protected: + PluginAdapterBase *m_base; + + static VampPluginHandle vampInstantiate(const VampPluginDescriptor *desc, + float inputSampleRate); + + static void vampCleanup(VampPluginHandle handle); + + static int vampInitialise(VampPluginHandle handle, unsigned int channels, + unsigned int stepSize, unsigned int blockSize); + + static void vampReset(VampPluginHandle handle); + + static float vampGetParameter(VampPluginHandle handle, int param); + static void vampSetParameter(VampPluginHandle handle, int param, float value); + + static unsigned int vampGetCurrentProgram(VampPluginHandle handle); + static void vampSelectProgram(VampPluginHandle handle, unsigned int program); + + static unsigned int vampGetPreferredStepSize(VampPluginHandle handle); + static unsigned int vampGetPreferredBlockSize(VampPluginHandle handle); + static unsigned int vampGetMinChannelCount(VampPluginHandle handle); + static unsigned int vampGetMaxChannelCount(VampPluginHandle handle); + + static unsigned int vampGetOutputCount(VampPluginHandle handle); + + static VampOutputDescriptor *vampGetOutputDescriptor(VampPluginHandle handle, + unsigned int i); + + static void vampReleaseOutputDescriptor(VampOutputDescriptor *desc); + + static VampFeatureList *vampProcess(VampPluginHandle handle, + const float *const *inputBuffers, + int sec, + int nsec); + + static VampFeatureList *vampGetRemainingFeatures(VampPluginHandle handle); + + static void vampReleaseFeatureSet(VampFeatureList *fs); + + void checkOutputMap(Plugin *plugin); + void markOutputsChanged(Plugin *plugin); + + void cleanup(Plugin *plugin); + unsigned int getOutputCount(Plugin *plugin); + VampOutputDescriptor *getOutputDescriptor(Plugin *plugin, + unsigned int i); + VampFeatureList *process(Plugin *plugin, + const float *const *inputBuffers, + int sec, int nsec); + VampFeatureList *getRemainingFeatures(Plugin *plugin); + VampFeatureList *convertFeatures(Plugin *plugin, + const Plugin::FeatureSet &features); + + // maps both plugins and descriptors to adapters + typedef std::map AdapterMap; + static AdapterMap *m_adapterMap; + static Impl *lookupAdapter(VampPluginHandle); + + bool m_populated; + VampPluginDescriptor m_descriptor; + Plugin::ParameterList m_parameters; + Plugin::ProgramList m_programs; + + typedef std::map OutputMap; + OutputMap m_pluginOutputs; + + std::map m_fs; + std::map > m_fsizes; + std::map > > m_fvsizes; + void resizeFS(Plugin *plugin, int n); + void resizeFL(Plugin *plugin, int n, size_t sz); + void resizeFV(Plugin *plugin, int n, int j, size_t sz); +}; + +PluginAdapterBase::PluginAdapterBase() +{ + m_impl = new Impl(this); +} + +PluginAdapterBase::~PluginAdapterBase() +{ + delete m_impl; +} + +const VampPluginDescriptor * +PluginAdapterBase::getDescriptor() +{ + return m_impl->getDescriptor(); +} + +PluginAdapterBase::Impl::Impl(PluginAdapterBase *base) : + m_base(base), + m_populated(false) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << std::endl; +#endif +} + +const VampPluginDescriptor * +PluginAdapterBase::Impl::getDescriptor() +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl[" << this << "]::getDescriptor" << std::endl; +#endif + + if (m_populated) return &m_descriptor; + + Plugin *plugin = m_base->createPlugin(48000); + + if (!plugin) { + std::cerr << "PluginAdapterBase::Impl::getDescriptor: Failed to create plugin" << std::endl; + return 0; + } + + if (plugin->getVampApiVersion() != VAMP_API_VERSION) { + std::cerr << "Vamp::PluginAdapterBase::Impl::getDescriptor: ERROR: " + << "API version " << plugin->getVampApiVersion() + << " for\nplugin \"" << plugin->getIdentifier() << "\" " + << "differs from version " + << VAMP_API_VERSION << " for adapter.\n" + << "This plugin is probably linked against a different version of the Vamp SDK\n" + << "from the version it was compiled with. It will need to be re-linked correctly\n" + << "before it can be used." << std::endl; + delete plugin; + return 0; + } + + m_parameters = plugin->getParameterDescriptors(); + m_programs = plugin->getPrograms(); + + m_descriptor.vampApiVersion = plugin->getVampApiVersion(); + m_descriptor.identifier = strdup(plugin->getIdentifier().c_str()); + m_descriptor.name = strdup(plugin->getName().c_str()); + m_descriptor.description = strdup(plugin->getDescription().c_str()); + m_descriptor.maker = strdup(plugin->getMaker().c_str()); + m_descriptor.pluginVersion = plugin->getPluginVersion(); + m_descriptor.copyright = strdup(plugin->getCopyright().c_str()); + + m_descriptor.parameterCount = m_parameters.size(); + m_descriptor.parameters = (const VampParameterDescriptor **) + malloc(m_parameters.size() * sizeof(VampParameterDescriptor)); + + unsigned int i; + + for (i = 0; i < m_parameters.size(); ++i) { + VampParameterDescriptor *desc = (VampParameterDescriptor *) + malloc(sizeof(VampParameterDescriptor)); + desc->identifier = strdup(m_parameters[i].identifier.c_str()); + desc->name = strdup(m_parameters[i].name.c_str()); + desc->description = strdup(m_parameters[i].description.c_str()); + desc->unit = strdup(m_parameters[i].unit.c_str()); + desc->minValue = m_parameters[i].minValue; + desc->maxValue = m_parameters[i].maxValue; + desc->defaultValue = m_parameters[i].defaultValue; + desc->isQuantized = m_parameters[i].isQuantized; + desc->quantizeStep = m_parameters[i].quantizeStep; + desc->valueNames = 0; + if (desc->isQuantized && !m_parameters[i].valueNames.empty()) { + desc->valueNames = (const char **) + malloc((m_parameters[i].valueNames.size()+1) * sizeof(char *)); + for (unsigned int j = 0; j < m_parameters[i].valueNames.size(); ++j) { + desc->valueNames[j] = strdup(m_parameters[i].valueNames[j].c_str()); + } + desc->valueNames[m_parameters[i].valueNames.size()] = 0; + } + m_descriptor.parameters[i] = desc; + } + + m_descriptor.programCount = m_programs.size(); + m_descriptor.programs = (const char **) + malloc(m_programs.size() * sizeof(const char *)); + + for (i = 0; i < m_programs.size(); ++i) { + m_descriptor.programs[i] = strdup(m_programs[i].c_str()); + } + + if (plugin->getInputDomain() == Plugin::FrequencyDomain) { + m_descriptor.inputDomain = vampFrequencyDomain; + } else { + m_descriptor.inputDomain = vampTimeDomain; + } + + m_descriptor.instantiate = vampInstantiate; + m_descriptor.cleanup = vampCleanup; + m_descriptor.initialise = vampInitialise; + m_descriptor.reset = vampReset; + m_descriptor.getParameter = vampGetParameter; + m_descriptor.setParameter = vampSetParameter; + m_descriptor.getCurrentProgram = vampGetCurrentProgram; + m_descriptor.selectProgram = vampSelectProgram; + m_descriptor.getPreferredStepSize = vampGetPreferredStepSize; + m_descriptor.getPreferredBlockSize = vampGetPreferredBlockSize; + m_descriptor.getMinChannelCount = vampGetMinChannelCount; + m_descriptor.getMaxChannelCount = vampGetMaxChannelCount; + m_descriptor.getOutputCount = vampGetOutputCount; + m_descriptor.getOutputDescriptor = vampGetOutputDescriptor; + m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor; + m_descriptor.process = vampProcess; + m_descriptor.getRemainingFeatures = vampGetRemainingFeatures; + m_descriptor.releaseFeatureSet = vampReleaseFeatureSet; + + if (!m_adapterMap) { + m_adapterMap = new AdapterMap; + } + (*m_adapterMap)[&m_descriptor] = this; + + delete plugin; + + m_populated = true; + return &m_descriptor; +} + +PluginAdapterBase::Impl::~Impl() +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl[" << this << "]::~Impl" << std::endl; +#endif + + if (!m_populated) return; + + free((void *)m_descriptor.identifier); + free((void *)m_descriptor.name); + free((void *)m_descriptor.description); + free((void *)m_descriptor.maker); + free((void *)m_descriptor.copyright); + + for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) { + const VampParameterDescriptor *desc = m_descriptor.parameters[i]; + free((void *)desc->identifier); + free((void *)desc->name); + free((void *)desc->description); + free((void *)desc->unit); + if (desc->valueNames) { + for (unsigned int j = 0; desc->valueNames[j]; ++j) { + free((void *)desc->valueNames[j]); + } + free((void *)desc->valueNames); + } + } + free((void *)m_descriptor.parameters); + + for (unsigned int i = 0; i < m_descriptor.programCount; ++i) { + free((void *)m_descriptor.programs[i]); + } + free((void *)m_descriptor.programs); + + if (m_adapterMap) { + + m_adapterMap->erase(&m_descriptor); + + if (m_adapterMap->empty()) { + delete m_adapterMap; + m_adapterMap = 0; + } + } +} + +PluginAdapterBase::Impl * +PluginAdapterBase::Impl::lookupAdapter(VampPluginHandle handle) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << std::endl; +#endif + + if (!m_adapterMap) return 0; + AdapterMap::const_iterator i = m_adapterMap->find(handle); + if (i == m_adapterMap->end()) return 0; + return i->second; +} + +VampPluginHandle +PluginAdapterBase::Impl::vampInstantiate(const VampPluginDescriptor *desc, + float inputSampleRate) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << std::endl; +#endif + + if (!m_adapterMap) { + m_adapterMap = new AdapterMap(); + } + + if (m_adapterMap->find(desc) == m_adapterMap->end()) { + std::cerr << "WARNING: PluginAdapterBase::Impl::vampInstantiate: Descriptor " << desc << " not in adapter map" << std::endl; + return 0; + } + + Impl *adapter = (*m_adapterMap)[desc]; + if (desc != &adapter->m_descriptor) return 0; + + Plugin *plugin = adapter->m_base->createPlugin(inputSampleRate); + if (plugin) { + (*m_adapterMap)[plugin] = adapter; + } + +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << "): returning handle " << plugin << std::endl; +#endif + + return plugin; +} + +void +PluginAdapterBase::Impl::vampCleanup(VampPluginHandle handle) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampCleanup(" << handle << ")" << std::endl; +#endif + + Impl *adapter = lookupAdapter(handle); + if (!adapter) { + delete ((Plugin *)handle); + return; + } + adapter->cleanup(((Plugin *)handle)); +} + +int +PluginAdapterBase::Impl::vampInitialise(VampPluginHandle handle, + unsigned int channels, + unsigned int stepSize, + unsigned int blockSize) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampInitialise(" << handle << ", " << channels << ", " << stepSize << ", " << blockSize << ")" << std::endl; +#endif + + Impl *adapter = lookupAdapter(handle); + if (!adapter) return 0; + bool result = ((Plugin *)handle)->initialise(channels, stepSize, blockSize); + adapter->markOutputsChanged((Plugin *)handle); + return result ? 1 : 0; +} + +void +PluginAdapterBase::Impl::vampReset(VampPluginHandle handle) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampReset(" << handle << ")" << std::endl; +#endif + + ((Plugin *)handle)->reset(); +} + +float +PluginAdapterBase::Impl::vampGetParameter(VampPluginHandle handle, + int param) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampGetParameter(" << handle << ", " << param << ")" << std::endl; +#endif + + Impl *adapter = lookupAdapter(handle); + if (!adapter) return 0.0; + Plugin::ParameterList &list = adapter->m_parameters; + return ((Plugin *)handle)->getParameter(list[param].identifier); +} + +void +PluginAdapterBase::Impl::vampSetParameter(VampPluginHandle handle, + int param, float value) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampSetParameter(" << handle << ", " << param << ", " << value << ")" << std::endl; +#endif + + Impl *adapter = lookupAdapter(handle); + if (!adapter) return; + Plugin::ParameterList &list = adapter->m_parameters; + ((Plugin *)handle)->setParameter(list[param].identifier, value); + adapter->markOutputsChanged((Plugin *)handle); +} + +unsigned int +PluginAdapterBase::Impl::vampGetCurrentProgram(VampPluginHandle handle) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampGetCurrentProgram(" << handle << ")" << std::endl; +#endif + + Impl *adapter = lookupAdapter(handle); + if (!adapter) return 0; + Plugin::ProgramList &list = adapter->m_programs; + std::string program = ((Plugin *)handle)->getCurrentProgram(); + for (unsigned int i = 0; i < list.size(); ++i) { + if (list[i] == program) return i; + } + return 0; +} + +void +PluginAdapterBase::Impl::vampSelectProgram(VampPluginHandle handle, + unsigned int program) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampSelectProgram(" << handle << ", " << program << ")" << std::endl; +#endif + + Impl *adapter = lookupAdapter(handle); + if (!adapter) return; + + Plugin::ProgramList &list = adapter->m_programs; + ((Plugin *)handle)->selectProgram(list[program]); + + adapter->markOutputsChanged((Plugin *)handle); +} + +unsigned int +PluginAdapterBase::Impl::vampGetPreferredStepSize(VampPluginHandle handle) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampGetPreferredStepSize(" << handle << ")" << std::endl; +#endif + + return ((Plugin *)handle)->getPreferredStepSize(); +} + +unsigned int +PluginAdapterBase::Impl::vampGetPreferredBlockSize(VampPluginHandle handle) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampGetPreferredBlockSize(" << handle << ")" << std::endl; +#endif + + return ((Plugin *)handle)->getPreferredBlockSize(); +} + +unsigned int +PluginAdapterBase::Impl::vampGetMinChannelCount(VampPluginHandle handle) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampGetMinChannelCount(" << handle << ")" << std::endl; +#endif + + return ((Plugin *)handle)->getMinChannelCount(); +} + +unsigned int +PluginAdapterBase::Impl::vampGetMaxChannelCount(VampPluginHandle handle) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampGetMaxChannelCount(" << handle << ")" << std::endl; +#endif + + return ((Plugin *)handle)->getMaxChannelCount(); +} + +unsigned int +PluginAdapterBase::Impl::vampGetOutputCount(VampPluginHandle handle) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampGetOutputCount(" << handle << ")" << std::endl; +#endif + + Impl *adapter = lookupAdapter(handle); + +// std::cerr << "vampGetOutputCount: handle " << handle << " -> adapter "<< adapter << std::endl; + + if (!adapter) return 0; + return adapter->getOutputCount((Plugin *)handle); +} + +VampOutputDescriptor * +PluginAdapterBase::Impl::vampGetOutputDescriptor(VampPluginHandle handle, + unsigned int i) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampGetOutputDescriptor(" << handle << ", " << i << ")" << std::endl; +#endif + + Impl *adapter = lookupAdapter(handle); + +// std::cerr << "vampGetOutputDescriptor: handle " << handle << " -> adapter "<< adapter << std::endl; + + if (!adapter) return 0; + return adapter->getOutputDescriptor((Plugin *)handle, i); +} + +void +PluginAdapterBase::Impl::vampReleaseOutputDescriptor(VampOutputDescriptor *desc) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampReleaseOutputDescriptor(" << desc << ")" << std::endl; +#endif + + if (desc->identifier) free((void *)desc->identifier); + if (desc->name) free((void *)desc->name); + if (desc->description) free((void *)desc->description); + if (desc->unit) free((void *)desc->unit); + if (desc->hasFixedBinCount && desc->binNames) { + for (unsigned int i = 0; i < desc->binCount; ++i) { + if (desc->binNames[i]) { + free((void *)desc->binNames[i]); + } + } + } + if (desc->binNames) free((void *)desc->binNames); + free((void *)desc); +} + +VampFeatureList * +PluginAdapterBase::Impl::vampProcess(VampPluginHandle handle, + const float *const *inputBuffers, + int sec, + int nsec) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampProcess(" << handle << ", " << sec << ", " << nsec << ")" << std::endl; +#endif + + Impl *adapter = lookupAdapter(handle); + if (!adapter) return 0; + return adapter->process((Plugin *)handle, inputBuffers, sec, nsec); +} + +VampFeatureList * +PluginAdapterBase::Impl::vampGetRemainingFeatures(VampPluginHandle handle) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampGetRemainingFeatures(" << handle << ")" << std::endl; +#endif + + Impl *adapter = lookupAdapter(handle); + if (!adapter) return 0; + return adapter->getRemainingFeatures((Plugin *)handle); +} + +void +PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList *fs) +{ +#ifdef DEBUG_PLUGIN_ADAPTER + std::cerr << "PluginAdapterBase::Impl::vampReleaseFeatureSet" << std::endl; +#endif +} + +void +PluginAdapterBase::Impl::cleanup(Plugin *plugin) +{ + if (m_fs.find(plugin) != m_fs.end()) { + size_t outputCount = 0; + if (m_pluginOutputs[plugin]) { + outputCount = m_pluginOutputs[plugin]->size(); + } + VampFeatureList *list = m_fs[plugin]; + for (unsigned int i = 0; i < outputCount; ++i) { + for (unsigned int j = 0; j < m_fsizes[plugin][i]; ++j) { + if (list[i].features[j].v1.label) { + free(list[i].features[j].v1.label); + } + if (list[i].features[j].v1.values) { + free(list[i].features[j].v1.values); + } + } + if (list[i].features) free(list[i].features); + } + m_fs.erase(plugin); + m_fsizes.erase(plugin); + m_fvsizes.erase(plugin); + } + + if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) { + delete m_pluginOutputs[plugin]; + m_pluginOutputs.erase(plugin); + } + + if (m_adapterMap) { + m_adapterMap->erase(plugin); + + if (m_adapterMap->empty()) { + delete m_adapterMap; + m_adapterMap = 0; + } + } + + delete ((Plugin *)plugin); +} + +void +PluginAdapterBase::Impl::checkOutputMap(Plugin *plugin) +{ + OutputMap::iterator i = m_pluginOutputs.find(plugin); + + if (i == m_pluginOutputs.end() || !i->second) { + + m_pluginOutputs[plugin] = new Plugin::OutputList + (plugin->getOutputDescriptors()); + +// std::cerr << "PluginAdapterBase::Impl::checkOutputMap: Have " << m_pluginOutputs[plugin]->size() << " outputs for plugin " << plugin->getIdentifier() << std::endl; + } +} + +void +PluginAdapterBase::Impl::markOutputsChanged(Plugin *plugin) +{ + OutputMap::iterator i = m_pluginOutputs.find(plugin); + +// std::cerr << "PluginAdapterBase::Impl::markOutputsChanged" << std::endl; + + if (i != m_pluginOutputs.end()) { + + Plugin::OutputList *list = i->second; + m_pluginOutputs.erase(i); + delete list; + } +} + +unsigned int +PluginAdapterBase::Impl::getOutputCount(Plugin *plugin) +{ + checkOutputMap(plugin); + + return m_pluginOutputs[plugin]->size(); +} + +VampOutputDescriptor * +PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin, + unsigned int i) +{ + checkOutputMap(plugin); + + Plugin::OutputDescriptor &od = + (*m_pluginOutputs[plugin])[i]; + + VampOutputDescriptor *desc = (VampOutputDescriptor *) + malloc(sizeof(VampOutputDescriptor)); + + desc->identifier = strdup(od.identifier.c_str()); + desc->name = strdup(od.name.c_str()); + desc->description = strdup(od.description.c_str()); + desc->unit = strdup(od.unit.c_str()); + desc->hasFixedBinCount = od.hasFixedBinCount; + desc->binCount = od.binCount; + + if (od.hasFixedBinCount && od.binCount > 0 + // We would like to do "&& !od.binNames.empty()" here -- but we + // can't, because it will crash older versions of the host adapter + // which try to copy the names across whenever the bin count is + // non-zero, regardless of whether they exist or not + ) { + desc->binNames = (const char **) + malloc(od.binCount * sizeof(const char *)); + + for (unsigned int i = 0; i < od.binCount; ++i) { + if (i < od.binNames.size()) { + desc->binNames[i] = strdup(od.binNames[i].c_str()); + } else { + desc->binNames[i] = 0; + } + } + } else { + desc->binNames = 0; + } + + desc->hasKnownExtents = od.hasKnownExtents; + desc->minValue = od.minValue; + desc->maxValue = od.maxValue; + desc->isQuantized = od.isQuantized; + desc->quantizeStep = od.quantizeStep; + + switch (od.sampleType) { + case Plugin::OutputDescriptor::OneSamplePerStep: + desc->sampleType = vampOneSamplePerStep; break; + case Plugin::OutputDescriptor::FixedSampleRate: + desc->sampleType = vampFixedSampleRate; break; + case Plugin::OutputDescriptor::VariableSampleRate: + desc->sampleType = vampVariableSampleRate; break; + } + + desc->sampleRate = od.sampleRate; + desc->hasDuration = od.hasDuration; + + return desc; +} + +VampFeatureList * +PluginAdapterBase::Impl::process(Plugin *plugin, + const float *const *inputBuffers, + int sec, int nsec) +{ +// std::cerr << "PluginAdapterBase::Impl::process" << std::endl; + RealTime rt(sec, nsec); + checkOutputMap(plugin); + return convertFeatures(plugin, plugin->process(inputBuffers, rt)); +} + +VampFeatureList * +PluginAdapterBase::Impl::getRemainingFeatures(Plugin *plugin) +{ +// std::cerr << "PluginAdapterBase::Impl::getRemainingFeatures" << std::endl; + checkOutputMap(plugin); + return convertFeatures(plugin, plugin->getRemainingFeatures()); +} + +VampFeatureList * +PluginAdapterBase::Impl::convertFeatures(Plugin *plugin, + const Plugin::FeatureSet &features) +{ + int lastN = -1; + + int outputCount = 0; + if (m_pluginOutputs[plugin]) outputCount = m_pluginOutputs[plugin]->size(); + + resizeFS(plugin, outputCount); + VampFeatureList *fs = m_fs[plugin]; + +// std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: sizeof(Feature) == " << sizeof(Plugin::Feature) << ", sizeof(VampFeature) == " << sizeof(VampFeature) << ", sizeof(VampFeatureList) == " << sizeof(VampFeatureList) << std::endl; + + for (Plugin::FeatureSet::const_iterator fi = features.begin(); + fi != features.end(); ++fi) { + + int n = fi->first; + +// std::cerr << "PluginAdapterBase::Impl::convertFeatures: n = " << n << std::endl; + + if (n >= int(outputCount)) { + std::cerr << "WARNING: PluginAdapterBase::Impl::convertFeatures: Too many outputs from plugin (" << n+1 << ", only should be " << outputCount << ")" << std::endl; + continue; + } + + if (n > lastN + 1) { + for (int i = lastN + 1; i < n; ++i) { + fs[i].featureCount = 0; + } + } + + const Plugin::FeatureList &fl = fi->second; + + size_t sz = fl.size(); + if (sz > m_fsizes[plugin][n]) resizeFL(plugin, n, sz); + fs[n].featureCount = sz; + + for (size_t j = 0; j < sz; ++j) { + +// std::cerr << "PluginAdapterBase::Impl::convertFeatures: j = " << j << std::endl; + + VampFeature *feature = &fs[n].features[j].v1; + + feature->hasTimestamp = fl[j].hasTimestamp; + feature->sec = fl[j].timestamp.sec; + feature->nsec = fl[j].timestamp.nsec; + feature->valueCount = fl[j].values.size(); + + VampFeatureV2 *v2 = &fs[n].features[j + sz].v2; + + v2->hasDuration = fl[j].hasDuration; + v2->durationSec = fl[j].duration.sec; + v2->durationNsec = fl[j].duration.nsec; + + if (feature->label) free(feature->label); + + if (fl[j].label.empty()) { + feature->label = 0; + } else { + feature->label = strdup(fl[j].label.c_str()); + } + + if (feature->valueCount > m_fvsizes[plugin][n][j]) { + resizeFV(plugin, n, j, feature->valueCount); + } + + for (unsigned int k = 0; k < feature->valueCount; ++k) { +// std::cerr << "PluginAdapterBase::Impl::convertFeatures: k = " << k << std::endl; + feature->values[k] = fl[j].values[k]; + } + } + + lastN = n; + } + + if (lastN == -1) return 0; + + if (int(outputCount) > lastN + 1) { + for (int i = lastN + 1; i < int(outputCount); ++i) { + fs[i].featureCount = 0; + } + } + +// std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: have " << outputCount << " outputs" << std::endl; +// for (int i = 0; i < outputCount; ++i) { +// std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: output " << i << " has " << fs[i].featureCount << " features" << std::endl; +// } + + + return fs; +} + +void +PluginAdapterBase::Impl::resizeFS(Plugin *plugin, int n) +{ +// std::cerr << "PluginAdapterBase::Impl::resizeFS(" << plugin << ", " << n << ")" << std::endl; + + int i = m_fsizes[plugin].size(); + if (i >= n) return; + +// std::cerr << "resizing from " << i << std::endl; + + m_fs[plugin] = (VampFeatureList *)realloc + (m_fs[plugin], n * sizeof(VampFeatureList)); + + while (i < n) { + m_fs[plugin][i].featureCount = 0; + m_fs[plugin][i].features = 0; + m_fsizes[plugin].push_back(0); + m_fvsizes[plugin].push_back(std::vector()); + i++; + } +} + +void +PluginAdapterBase::Impl::resizeFL(Plugin *plugin, int n, size_t sz) +{ +// std::cerr << "PluginAdapterBase::Impl::resizeFL(" << plugin << ", " << n << ", " +// << sz << ")" << std::endl; + + size_t i = m_fsizes[plugin][n]; + if (i >= sz) return; + +// std::cerr << "resizing from " << i << std::endl; + + m_fs[plugin][n].features = (VampFeatureUnion *)realloc + (m_fs[plugin][n].features, 2 * sz * sizeof(VampFeatureUnion)); + + while (m_fsizes[plugin][n] < sz) { + m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.hasTimestamp = 0; + m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.valueCount = 0; + m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.values = 0; + m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.label = 0; + m_fs[plugin][n].features[m_fsizes[plugin][n] + sz].v2.hasDuration = 0; + m_fvsizes[plugin][n].push_back(0); + m_fsizes[plugin][n]++; + } +} + +void +PluginAdapterBase::Impl::resizeFV(Plugin *plugin, int n, int j, size_t sz) +{ +// std::cerr << "PluginAdapterBase::Impl::resizeFV(" << plugin << ", " << n << ", " +// << j << ", " << sz << ")" << std::endl; + + size_t i = m_fvsizes[plugin][n][j]; + if (i >= sz) return; + +// std::cerr << "resizing from " << i << std::endl; + + m_fs[plugin][n].features[j].v1.values = (float *)realloc + (m_fs[plugin][n].features[j].v1.values, sz * sizeof(float)); + + m_fvsizes[plugin][n][j] = sz; +} + +PluginAdapterBase::Impl::AdapterMap * +PluginAdapterBase::Impl::m_adapterMap = 0; + +} + +_VAMP_SDK_PLUGSPACE_END(PluginAdapter.cpp) + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-sdk/RealTime.cpp mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-sdk/RealTime.cpp --- mixxx-1.10.1-1/lib/vamp-2.3/src/vamp-sdk/RealTime.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/src/vamp-sdk/RealTime.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,252 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +/* + This is a modified version of a source file from the + Rosegarden MIDI and audio sequencer and notation editor. + This file copyright 2000-2006 Chris Cannam. + Relicensed by the author as detailed above. +*/ + +#include + +#if (__GNUC__ < 3) +#include +#define stringstream strstream +#else +#include +#endif + +using std::cerr; +using std::endl; + +#ifndef _WIN32 +#include +#endif + +#include + +_VAMP_SDK_PLUGSPACE_BEGIN(RealTime.cpp) + +namespace Vamp { + +// A RealTime consists of two ints that must be at least 32 bits each. +// A signed 32-bit int can store values exceeding +/- 2 billion. This +// means we can safely use our lower int for nanoseconds, as there are +// 1 billion nanoseconds in a second and we need to handle double that +// because of the implementations of addition etc that we use. +// +// The maximum valid RealTime on a 32-bit system is somewhere around +// 68 years: 999999999 nanoseconds longer than the classic Unix epoch. + +#define ONE_BILLION 1000000000 + +RealTime::RealTime(int s, int n) : + sec(s), nsec(n) +{ + if (sec == 0) { + while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; } + while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; } + } else if (sec < 0) { + while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; } + while (nsec > 0) { nsec -= ONE_BILLION; ++sec; } + } else { + while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; } + while (nsec < 0) { nsec += ONE_BILLION; --sec; } + } +} + +RealTime +RealTime::fromSeconds(double sec) +{ + return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5)); +} + +RealTime +RealTime::fromMilliseconds(int msec) +{ + return RealTime(msec / 1000, (msec % 1000) * 1000000); +} + +#ifndef _WIN32 +RealTime +RealTime::fromTimeval(const struct timeval &tv) +{ + return RealTime(tv.tv_sec, tv.tv_usec * 1000); +} +#endif + +std::ostream &operator<<(std::ostream &out, const RealTime &rt) +{ + if (rt < RealTime::zeroTime) { + out << "-"; + } else { + out << " "; + } + + int s = (rt.sec < 0 ? -rt.sec : rt.sec); + int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec); + + out << s << "."; + + int nn(n); + if (nn == 0) out << "00000000"; + else while (nn < (ONE_BILLION / 10)) { + out << "0"; + nn *= 10; + } + + out << n << "R"; + return out; +} + +std::string +RealTime::toString() const +{ + std::stringstream out; + out << *this; + +#if (__GNUC__ < 3) + out << std::ends; +#endif + + std::string s = out.str(); + + // remove trailing R + return s.substr(0, s.length() - 1); +} + +std::string +RealTime::toText(bool fixedDp) const +{ + if (*this < RealTime::zeroTime) return "-" + (-*this).toText(); + + std::stringstream out; + + if (sec >= 3600) { + out << (sec / 3600) << ":"; + } + + if (sec >= 60) { + out << (sec % 3600) / 60 << ":"; + } + + if (sec >= 10) { + out << ((sec % 60) / 10); + } + + out << (sec % 10); + + int ms = msec(); + + if (ms != 0) { + out << "."; + out << (ms / 100); + ms = ms % 100; + if (ms != 0) { + out << (ms / 10); + ms = ms % 10; + } else if (fixedDp) { + out << "0"; + } + if (ms != 0) { + out << ms; + } else if (fixedDp) { + out << "0"; + } + } else if (fixedDp) { + out << ".000"; + } + +#if (__GNUC__ < 3) + out << std::ends; +#endif + + std::string s = out.str(); + + return s; +} + + +RealTime +RealTime::operator/(int d) const +{ + int secdiv = sec / d; + int secrem = sec % d; + + double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d; + + return RealTime(secdiv, int(nsecdiv + 0.5)); +} + +double +RealTime::operator/(const RealTime &r) const +{ + double lTotal = double(sec) * ONE_BILLION + double(nsec); + double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec); + + if (rTotal == 0) return 0.0; + else return lTotal/rTotal; +} + +long +RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate) +{ + if (time < zeroTime) return -realTime2Frame(-time, sampleRate); + double s = time.sec + double(time.nsec + 1) / 1000000000.0; + return long(s * sampleRate); +} + +RealTime +RealTime::frame2RealTime(long frame, unsigned int sampleRate) +{ + if (frame < 0) return -frame2RealTime(-frame, sampleRate); + + RealTime rt; + rt.sec = frame / long(sampleRate); + frame -= rt.sec * long(sampleRate); + rt.nsec = (int)(((double(frame) * 1000000.0) / sampleRate) * 1000.0); + return rt; +} + +const RealTime RealTime::zeroTime(0,0); + +} + +_VAMP_SDK_PLUGSPACE_END(RealTime.cpp) + + + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp/vamp.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp/vamp.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp/vamp.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp/vamp.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,388 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef VAMP_HEADER_INCLUDED +#define VAMP_HEADER_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Plugin API version. This is incremented when a change is made that + * changes the binary layout of the descriptor records. When this + * happens, there should be a mechanism for retaining compatibility + * with older hosts and/or plugins. + * + * See also the vampApiVersion field in the plugin descriptor, and the + * hostApiVersion argument to the vampGetPluginDescriptor function. + */ +#define VAMP_API_VERSION 2 + +/** + * C language API for Vamp plugins. + * + * This is the formal plugin API for Vamp. Plugin authors may prefer + * to use the C++ classes provided in the Vamp plugin SDK, instead of + * using this API directly. There is an adapter class provided that + * makes C++ plugins available using this C API with relatively little + * work, and the C++ headers are more thoroughly documented. + * + * IMPORTANT: The comments in this file summarise the purpose of each + * of the declared fields and functions, but do not provide a complete + * guide to their permitted values and expected usage. Please refer + * to the C++ headers in the Vamp plugin SDK for further details and + * plugin lifecycle documentation. + */ + +typedef struct _VampParameterDescriptor +{ + /** Computer-usable name of the parameter. Must not change. [a-zA-Z0-9_] */ + const char *identifier; + + /** Human-readable name of the parameter. May be translatable. */ + const char *name; + + /** Human-readable short text about the parameter. May be translatable. */ + const char *description; + + /** Human-readable unit of the parameter. */ + const char *unit; + + /** Minimum value. */ + float minValue; + + /** Maximum value. */ + float maxValue; + + /** Default value. Plugin is responsible for setting this on initialise. */ + float defaultValue; + + /** 1 if parameter values are quantized to a particular resolution. */ + int isQuantized; + + /** Quantization resolution, if isQuantized. */ + float quantizeStep; + + /** Human-readable names of the values, if isQuantized. May be NULL. */ + const char **valueNames; + +} VampParameterDescriptor; + +typedef enum +{ + /** Each process call returns results aligned with call's block start. */ + vampOneSamplePerStep, + + /** Returned results are evenly spaced at samplerate specified below. */ + vampFixedSampleRate, + + /** Returned results have their own individual timestamps. */ + vampVariableSampleRate + +} VampSampleType; + +typedef struct _VampOutputDescriptor +{ + /** Computer-usable name of the output. Must not change. [a-zA-Z0-9_] */ + const char *identifier; + + /** Human-readable name of the output. May be translatable. */ + const char *name; + + /** Human-readable short text about the output. May be translatable. */ + const char *description; + + /** Human-readable name of the unit of the output. */ + const char *unit; + + /** 1 if output has equal number of values for each returned result. */ + int hasFixedBinCount; + + /** Number of values per result, if hasFixedBinCount. */ + unsigned int binCount; + + /** Names of returned value bins, if hasFixedBinCount. May be NULL. */ + const char **binNames; + + /** 1 if each returned value falls within the same fixed min/max range. */ + int hasKnownExtents; + + /** Minimum value for a returned result in any bin, if hasKnownExtents. */ + float minValue; + + /** Maximum value for a returned result in any bin, if hasKnownExtents. */ + float maxValue; + + /** 1 if returned results are quantized to a particular resolution. */ + int isQuantized; + + /** Quantization resolution for returned results, if isQuantized. */ + float quantizeStep; + + /** Time positioning method for returned results (see VampSampleType). */ + VampSampleType sampleType; + + /** Sample rate of returned results, if sampleType is vampFixedSampleRate. + "Resolution" of result, if sampleType is vampVariableSampleRate. */ + float sampleRate; + + /** 1 if the returned results for this output are known to have a + duration field. + + This field is new in Vamp API version 2; it must not be tested + for plugins that report an older API version in their plugin + descriptor. + */ + int hasDuration; + +} VampOutputDescriptor; + +typedef struct _VampFeature +{ + /** 1 if the feature has a timestamp (i.e. if vampVariableSampleRate). */ + int hasTimestamp; + + /** Seconds component of timestamp. */ + int sec; + + /** Nanoseconds component of timestamp. */ + int nsec; + + /** Number of values. Must be binCount if hasFixedBinCount. */ + unsigned int valueCount; + + /** Values for this returned sample. */ + float *values; + + /** Label for this returned sample. May be NULL. */ + char *label; + +} VampFeature; + +typedef struct _VampFeatureV2 +{ + /** 1 if the feature has a duration. */ + int hasDuration; + + /** Seconds component of duratiion. */ + int durationSec; + + /** Nanoseconds component of duration. */ + int durationNsec; + +} VampFeatureV2; + +typedef union _VampFeatureUnion +{ + // sizeof(featureV1) >= sizeof(featureV2) for backward compatibility + VampFeature v1; + VampFeatureV2 v2; + +} VampFeatureUnion; + +typedef struct _VampFeatureList +{ + /** Number of features in this feature list. */ + unsigned int featureCount; + + /** Features in this feature list. May be NULL if featureCount is + zero. + + If present, this array must contain featureCount feature + structures for a Vamp API version 1 plugin, or 2*featureCount + feature unions for a Vamp API version 2 plugin. + + The features returned by an API version 2 plugin must consist + of the same feature structures as in API version 1 for the + first featureCount array elements, followed by featureCount + unions that contain VampFeatureV2 structures (or NULL pointers + if no V2 feature structures are present). + */ + VampFeatureUnion *features; + +} VampFeatureList; + +typedef enum +{ + vampTimeDomain, + vampFrequencyDomain + +} VampInputDomain; + +typedef void *VampPluginHandle; + +typedef struct _VampPluginDescriptor +{ + /** API version with which this descriptor is compatible. */ + unsigned int vampApiVersion; + + /** Computer-usable name of the plugin. Must not change. [a-zA-Z0-9_] */ + const char *identifier; + + /** Human-readable name of the plugin. May be translatable. */ + const char *name; + + /** Human-readable short text about the plugin. May be translatable. */ + const char *description; + + /** Human-readable name of plugin's author or vendor. */ + const char *maker; + + /** Version number of the plugin. */ + int pluginVersion; + + /** Human-readable summary of copyright or licensing for plugin. */ + const char *copyright; + + /** Number of parameter inputs. */ + unsigned int parameterCount; + + /** Fixed descriptors for parameter inputs. */ + const VampParameterDescriptor **parameters; + + /** Number of programs. */ + unsigned int programCount; + + /** Fixed names for programs. */ + const char **programs; + + /** Preferred input domain for audio input (time or frequency). */ + VampInputDomain inputDomain; + + /** Create and return a new instance of this plugin. */ + VampPluginHandle (*instantiate)(const struct _VampPluginDescriptor *, + float inputSampleRate); + + /** Destroy an instance of this plugin. */ + void (*cleanup)(VampPluginHandle); + + /** Initialise an instance following parameter configuration. */ + int (*initialise)(VampPluginHandle, + unsigned int inputChannels, + unsigned int stepSize, + unsigned int blockSize); + + /** Reset an instance, ready to use again on new input data. */ + void (*reset)(VampPluginHandle); + + /** Get a parameter value. */ + float (*getParameter)(VampPluginHandle, int); + + /** Set a parameter value. May only be called before initialise. */ + void (*setParameter)(VampPluginHandle, int, float); + + /** Get the current program (if programCount > 0). */ + unsigned int (*getCurrentProgram)(VampPluginHandle); + + /** Set the current program. May only be called before initialise. */ + void (*selectProgram)(VampPluginHandle, unsigned int); + + /** Get the plugin's preferred processing window increment in samples. */ + unsigned int (*getPreferredStepSize)(VampPluginHandle); + + /** Get the plugin's preferred processing window size in samples. */ + unsigned int (*getPreferredBlockSize)(VampPluginHandle); + + /** Get the minimum number of input channels this plugin can handle. */ + unsigned int (*getMinChannelCount)(VampPluginHandle); + + /** Get the maximum number of input channels this plugin can handle. */ + unsigned int (*getMaxChannelCount)(VampPluginHandle); + + /** Get the number of feature outputs (distinct sets of results). */ + unsigned int (*getOutputCount)(VampPluginHandle); + + /** Get a descriptor for a given feature output. Returned pointer + is valid only until next call to getOutputDescriptor for this + handle, or releaseOutputDescriptor for this descriptor. Host + must call releaseOutputDescriptor after use. */ + VampOutputDescriptor *(*getOutputDescriptor)(VampPluginHandle, + unsigned int); + + /** Destroy a descriptor for a feature output. */ + void (*releaseOutputDescriptor)(VampOutputDescriptor *); + + /** Process an input block and return a set of features. Returned + pointer is valid only until next call to process, + getRemainingFeatures, or cleanup for this handle, or + releaseFeatureSet for this feature set. Host must call + releaseFeatureSet after use. */ + VampFeatureList *(*process)(VampPluginHandle, + const float *const *inputBuffers, + int sec, + int nsec); + + /** Return any remaining features at the end of processing. */ + VampFeatureList *(*getRemainingFeatures)(VampPluginHandle); + + /** Release a feature set returned from process or getRemainingFeatures. */ + void (*releaseFeatureSet)(VampFeatureList *); + +} VampPluginDescriptor; + + +/** Get the descriptor for a given plugin index in this library. + Return NULL if the index is outside the range of valid indices for + this plugin library. + + The hostApiVersion argument tells the library code the highest + Vamp API version supported by the host. The function should + return a plugin descriptor compatible with the highest API version + supported by the library that is no higher than that supported by + the host. Provided the descriptor has the correct vampApiVersion + field for its actual compatibility level, the host should be able + to do the right thing with it: use it if possible, discard it + otherwise. + + This is the only symbol that a Vamp plugin actually needs to + export from its shared object; all others can be hidden. See the + accompanying documentation for notes on how to achieve this with + certain compilers. +*/ +const VampPluginDescriptor *vampGetPluginDescriptor + (unsigned int hostApiVersion, unsigned int index); + + +/** Function pointer type for vampGetPluginDescriptor. */ +typedef const VampPluginDescriptor *(*VampGetPluginDescriptorFunction) + (unsigned int, unsigned int); + +#ifdef __cplusplus +} +#endif + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/Plugin.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/Plugin.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/Plugin.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/Plugin.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,47 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_HOSTSDK_PLUGIN_H_ +#define _VAMP_HOSTSDK_PLUGIN_H_ + +// Do not include vamp-sdk/Plugin.h directly from host code. Always +// use this header instead. + +#include "hostguard.h" + +#include + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginBase.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginBase.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginBase.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginBase.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,47 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_HOSTSDK_PLUGIN_BASE_H_ +#define _VAMP_HOSTSDK_PLUGIN_BASE_H_ + +// Do not include vamp-sdk/PluginBase.h directly from host code. +// Always use this header instead. + +#include "hostguard.h" + +#include + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginBufferingAdapter.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginBufferingAdapter.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginBufferingAdapter.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginBufferingAdapter.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,194 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + This file by Mark Levy and Chris Cannam, Copyright 2007-2008 QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_PLUGIN_BUFFERING_ADAPTER_H_ +#define _VAMP_PLUGIN_BUFFERING_ADAPTER_H_ + +#include "hostguard.h" +#include "PluginWrapper.h" + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginBufferingAdapter.h) + +namespace Vamp { + +namespace HostExt { + +/** + * \class PluginBufferingAdapter PluginBufferingAdapter.h + * + * PluginBufferingAdapter is a Vamp plugin adapter that allows plugins + * to be used by a host supplying an audio stream in non-overlapping + * buffers of arbitrary size. + * + * A host using PluginBufferingAdapter may ignore the preferred step + * and block size reported by the plugin, and still expect the plugin + * to run. The value of blockSize and stepSize passed to initialise + * should be the size of the buffer which the host will supply; the + * stepSize should be equal to the blockSize. + * + * If the internal step size used for the plugin differs from that + * supplied by the host, the adapter will modify the sample type and + * rate specifications for the plugin outputs appropriately, and set + * timestamps on the output features for outputs that formerly used a + * different sample rate specification. This is necessary in order to + * obtain correct time stamping. + * + * In other respects, the PluginBufferingAdapter behaves identically + * to the plugin that it wraps. The wrapped plugin will be deleted + * when the wrapper is deleted. + */ + +class PluginBufferingAdapter : public PluginWrapper +{ +public: + /** + * Construct a PluginBufferingAdapter wrapping the given plugin. + * The adapter takes ownership of the plugin, which will be + * deleted when the adapter is deleted. + */ + PluginBufferingAdapter(Plugin *plugin); + virtual ~PluginBufferingAdapter(); + + /** + * Return the preferred step size for this adapter. + * + * Because of the way this adapter works, its preferred step size + * will always be the same as its preferred block size. This may + * or may not be the same as the preferred step size of the + * underlying plugin, which may be obtained by calling + * getPluginPreferredStepSize(). + */ + size_t getPreferredStepSize() const; + + /** + * Return the preferred block size for this adapter. + * + * This may or may not be the same as the preferred block size of + * the underlying plugin, which may be obtained by calling + * getPluginPreferredBlockSize(). + * + * Note that this adapter may be initialised with any block size, + * not just its supposedly preferred one. + */ + size_t getPreferredBlockSize() const; + + /** + * Initialise the adapter (and therefore the plugin) for the given + * number of channels. Initialise the adapter for the given step + * and block size, which must be equal. + * + * The step and block size used for the underlying plugin will + * depend on its preferences, or any values previously passed to + * setPluginStepSize and setPluginBlockSize. + */ + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + + /** + * Return the preferred step size of the plugin wrapped by this + * adapter. + * + * This is included mainly for informational purposes. This value + * is not likely to be a valid step size for the adapter itself, + * and it is not usually of any use in interpreting the results + * (because the adapter re-writes OneSamplePerStep outputs to + * FixedSampleRate so that the hop size no longer needs to be + * known beforehand in order to interpret them). + */ + size_t getPluginPreferredStepSize() const; + + /** + * Return the preferred block size of the plugin wrapped by this + * adapter. + * + * This is included mainly for informational purposes. + */ + size_t getPluginPreferredBlockSize() const; + + /** + * Set the step size that will be used for the underlying plugin + * when initialise() is called. If this is not set, the plugin's + * own preferred step size will be used. You will not usually + * need to call this function. If you do call it, it must be + * before the first call to initialise(). + */ + void setPluginStepSize(size_t stepSize); + + /** + * Set the block size that will be used for the underlying plugin + * when initialise() is called. If this is not set, the plugin's + * own preferred block size will be used. You will not usually + * need to call this function. If you do call it, it must be + * before the first call to initialise(). + */ + void setPluginBlockSize(size_t blockSize); + + /** + * Return the step and block sizes that were actually used when + * initialising the underlying plugin. + * + * This is included mainly for informational purposes. You will + * not usually need to call this function. If this is called + * before initialise(), it will return 0 for both values. If it + * is called after a failed call to initialise(), it will return + * the values that were used in the failed call to the plugin's + * initialise() function. + */ + void getActualStepAndBlockSizes(size_t &stepSize, size_t &blockSize); + + void setParameter(std::string, float); + void selectProgram(std::string); + + OutputList getOutputDescriptors() const; + + void reset(); + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + class Impl; + Impl *m_impl; +}; + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginBufferingAdapter.h) + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginChannelAdapter.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginChannelAdapter.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginChannelAdapter.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginChannelAdapter.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,149 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_PLUGIN_CHANNEL_ADAPTER_H_ +#define _VAMP_PLUGIN_CHANNEL_ADAPTER_H_ + +#include "hostguard.h" +#include "PluginWrapper.h" + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginChannelAdapter.h) + +namespace Vamp { + +namespace HostExt { + +/** + * \class PluginChannelAdapter PluginChannelAdapter.h + * + * PluginChannelAdapter is a Vamp plugin adapter that implements a + * policy for management of plugins that expect a different number of + * input channels from the number actually available in the source + * audio data. + * + * A host using PluginChannelAdapter may ignore the getMinChannelCount + * and getMaxChannelCount reported by the plugin, and still expect the + * plugin to run. + * + * PluginChannelAdapter implements the following policy: + * + * - If the plugin supports the provided number of channels directly, + * PluginChannelAdapter will just run the plugin as normal. + * + * - If the plugin only supports exactly one channel but more than + * one channel is provided, PluginChannelAdapter will use the mean of + * the channels. This ensures that the resulting values remain + * within the same magnitude range as expected for mono data. + * + * - If the plugin requires more than one channel but exactly one is + * provided, the provided channel will be duplicated across all the + * plugin input channels. + * + * If none of the above apply: + * + * - If the plugin requires more channels than are provided, the + * minimum acceptable number of channels will be produced by adding + * empty (zero valued) channels to those provided. + * + * - If the plugin requires fewer channels than are provided, the + * maximum acceptable number of channels will be produced by + * discarding the excess channels. + * + * Hosts requiring a different channel policy from the above will need + * to implement it themselves, instead of using PluginChannelAdapter. + * + * Note that PluginChannelAdapter does not override the minimum and + * maximum channel counts returned by the wrapped plugin. The host + * will need to be aware that it is using a PluginChannelAdapter, and + * be prepared to ignore these counts as necessary. (This contrasts + * with the approach used in PluginInputDomainAdapter, which aims to + * make the host completely unaware of which underlying input domain + * is in fact in use.) + * + * (The rationale for this is that a host may wish to use the + * PluginChannelAdapter but still discriminate in some way on the + * basis of the number of channels actually supported. For example, a + * simple stereo audio host may prefer to reject plugins that require + * more than two channels on the grounds that doesn't actually + * understand what they are for, rather than allow the channel adapter + * to make a potentially meaningless channel conversion for them.) + * + * In every respect other than its management of channels, the + * PluginChannelAdapter behaves identically to the plugin that it + * wraps. The wrapped plugin will be deleted when the wrapper is + * deleted. + * + * \note This class was introduced in version 1.1 of the Vamp plugin SDK. + */ + +class PluginChannelAdapter : public PluginWrapper +{ +public: + /** + * Construct a PluginChannelAdapter wrapping the given plugin. + * The adapter takes ownership of the plugin, which will be + * deleted when the adapter is deleted. + */ + PluginChannelAdapter(Plugin *plugin); + virtual ~PluginChannelAdapter(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + + /** + * Call process(), providing interleaved audio data with the + * number of channels passed to initialise(). The adapter will + * de-interleave into temporary buffers as appropriate before + * calling process(). + * + * \note This function was introduced in version 1.4 of the Vamp + * plugin SDK. + */ + FeatureSet processInterleaved(const float *inputBuffer, RealTime timestamp); + +protected: + class Impl; + Impl *m_impl; +}; + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginChannelAdapter.h) + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginHostAdapter.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginHostAdapter.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginHostAdapter.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginHostAdapter.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,123 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_PLUGIN_HOST_ADAPTER_H_ +#define _VAMP_PLUGIN_HOST_ADAPTER_H_ + +#include "hostguard.h" +#include "Plugin.h" + +#include + +#include + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginHostAdapter.h) + +namespace Vamp { + +/** + * \class PluginHostAdapter PluginHostAdapter.h + * + * PluginHostAdapter is a wrapper class that a Vamp host can use to + * make the C-language VampPluginDescriptor object appear as a C++ + * Vamp::Plugin object. + * + * The Vamp API is defined in vamp/vamp.h as a C API. The C++ objects + * used for convenience by plugins and hosts actually communicate + * using the C low-level API, but the details of this communication + * are handled seamlessly by the Vamp SDK implementation provided the + * plugin and host use the proper C++ wrapper objects. + * + * See also PluginAdapter, the plugin-side wrapper that makes a C++ + * plugin object available using the C query API. + */ + +class PluginHostAdapter : public Plugin +{ +public: + PluginHostAdapter(const VampPluginDescriptor *descriptor, + float inputSampleRate); + virtual ~PluginHostAdapter(); + + static std::vector getPluginPath(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const; + + unsigned int getVampApiVersion() const; + std::string getIdentifier() const; + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + + ParameterList getParameterDescriptors() const; + float getParameter(std::string) const; + void setParameter(std::string, float); + + ProgramList getPrograms() const; + std::string getCurrentProgram() const; + void selectProgram(std::string); + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + size_t getMinChannelCount() const; + size_t getMaxChannelCount() const; + + OutputList getOutputDescriptors() const; + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + void convertFeatures(VampFeatureList *, FeatureSet &); + + const VampPluginDescriptor *m_descriptor; + VampPluginHandle m_handle; +}; + +} + +_VAMP_SDK_HOSTSPACE_END(PluginHostAdapter.h) + +#endif + + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginInputDomainAdapter.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginInputDomainAdapter.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginInputDomainAdapter.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginInputDomainAdapter.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,236 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_PLUGIN_INPUT_DOMAIN_ADAPTER_H_ +#define _VAMP_PLUGIN_INPUT_DOMAIN_ADAPTER_H_ + +#include "hostguard.h" +#include "PluginWrapper.h" + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.h) + +namespace Vamp { + +namespace HostExt { + +/** + * \class PluginInputDomainAdapter PluginInputDomainAdapter.h + * + * PluginInputDomainAdapter is a Vamp plugin adapter that converts + * time-domain input into frequency-domain input for plugins that need + * it. This permits a host to use time- and frequency-domain plugins + * interchangeably without needing to handle the conversion itself. + * + * This adapter uses a basic windowed FFT (using Hann window by + * default) that supports power-of-two block sizes only. If a + * frequency domain plugin requests a non-power-of-two blocksize, the + * adapter will adjust it to a nearby power of two instead. Thus, + * getPreferredBlockSize() will always return a power of two if the + * wrapped plugin is a frequency domain one. If the plugin doesn't + * accept the adjusted power of two block size, initialise() will + * fail. + * + * The adapter provides no way for the host to discover whether the + * underlying plugin is actually a time or frequency domain plugin + * (except that if the preferred block size is not a power of two, it + * must be a time domain plugin). + * + * The FFT implementation is simple and self-contained, but unlikely + * to be the fastest available: a host can usually do better if it + * cares enough. + * + * The window shape for the FFT frame can be set using setWindowType + * and the current shape retrieved using getWindowType. (This was + * added in v2.3 of the SDK.) + * + * In every respect other than its input domain handling, the + * PluginInputDomainAdapter behaves identically to the plugin that it + * wraps. The wrapped plugin will be deleted when the wrapper is + * deleted. + * + * \note This class was introduced in version 1.1 of the Vamp plugin SDK. + */ + +class PluginInputDomainAdapter : public PluginWrapper +{ +public: + /** + * Construct a PluginInputDomainAdapter wrapping the given plugin. + * The adapter takes ownership of the plugin, which will be + * deleted when the adapter is deleted. + */ + PluginInputDomainAdapter(Plugin *plugin); + virtual ~PluginInputDomainAdapter(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const; + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + + /** + * ProcessTimestampMethod determines how the + * PluginInputDomainAdapter handles timestamps for the data passed + * to the process() function of the plugin it wraps, in the case + * where the plugin is expecting frequency-domain data. + * + * The Vamp specification requires that the timestamp passed to + * the plugin for frequency-domain input should be that of the + * centre of the processing block, rather than the start as is the + * case for time-domain input. + * + * Since PluginInputDomainAdapter aims to be transparent in use, + * it needs to handle this timestamp adjustment itself. However, + * some control is available over the method used for adjustment, + * by means of the ProcessTimestampMethod setting. + * + * If ProcessTimestampMethod is set to ShiftTimestamp (the + * default), then the data passed to the wrapped plugin will be + * calculated from the same input data block as passed to the + * wrapper, but the timestamp passed to the plugin will be + * advanced by half of the window size. + * + * If ProcessTimestampMethod is set to ShiftData, then the + * timestamp passed to the wrapped plugin will be the same as that + * passed to the process call of the wrapper, but the data block + * used to calculate the input will be shifted back (earlier) by + * half of the window size, with half a block of zero padding at + * the start of the first process call. This has the advantage of + * preserving the first half block of audio without any + * deterioration from window shaping. + * + * If ProcessTimestampMethod is set to NoShift, then no adjustment + * will be made and the timestamps will be incorrect. + */ + enum ProcessTimestampMethod { + ShiftTimestamp, + ShiftData, + NoShift + }; + + /** + * Set the method used for timestamp adjustment in plugins taking + * frequency-domain input. See the ProcessTimestampMethod + * documentation for details. + * + * This function must be called before the first call to + * process(). + */ + void setProcessTimestampMethod(ProcessTimestampMethod); + + /** + * Retrieve the method used for timestamp adjustment in plugins + * taking frequency-domain input. See the ProcessTimestampMethod + * documentation for details. + */ + ProcessTimestampMethod getProcessTimestampMethod() const; + + /** + * Return the amount by which the timestamps supplied to process() + * are being incremented when they are passed to the plugin's own + * process() implementation. + * + * The Vamp API mandates that the timestamp passed to the plugin + * for time-domain input should be the time of the first sample in + * the block, but the timestamp passed for frequency-domain input + * should be the timestamp of the centre of the block. + * + * The PluginInputDomainAdapter adjusts its timestamps properly so + * that the plugin receives correct times, but in some + * circumstances (such as for establishing the correct timing of + * implicitly-timed features, i.e. features without their own + * timestamps) the host may need to be aware that this adjustment + * is taking place. + * + * If the plugin requires time-domain input or the + * PluginInputDomainAdapter is configured with its + * ProcessTimestampMethod set to ShiftData instead of + * ShiftTimestamp, then this function will return zero. + * + * The result of calling this function before initialise() has + * been called is undefined. + */ + RealTime getTimestampAdjustment() const; + + /** + * The set of supported window shapes. + */ + enum WindowType { + + RectangularWindow = 0, + + BartlettWindow = 1, /// synonym for RectangularWindow + TriangularWindow = 1, /// synonym for BartlettWindow + + HammingWindow = 2, + + HanningWindow = 3, /// synonym for HannWindow + HannWindow = 3, /// synonym for HanningWindow + + BlackmanWindow = 4, + + NuttallWindow = 7, + + BlackmanHarrisWindow = 8 + }; + + /** + * Return the current window shape. The default is HanningWindow. + */ + WindowType getWindowType() const; + + /** + * Set the current window shape. + */ + void setWindowType(WindowType type); + + +protected: + class Impl; + Impl *m_impl; +}; + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginInputDomainAdapter.h) + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginLoader.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginLoader.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginLoader.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginLoader.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,243 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_PLUGIN_LOADER_H_ +#define _VAMP_PLUGIN_LOADER_H_ + +#include +#include +#include + +#include "hostguard.h" +#include "PluginWrapper.h" + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginLoader.h) + +namespace Vamp { + +class Plugin; + +namespace HostExt { + +/** + * \class PluginLoader PluginLoader.h + * + * Vamp::HostExt::PluginLoader is a convenience class for discovering + * and loading Vamp plugins using the typical plugin-path, library + * naming, and categorisation conventions described in the Vamp SDK + * documentation. This class is intended to greatly simplify the task + * of becoming a Vamp plugin host for any C++ application. + * + * Hosts are not required by the Vamp specification to use the same + * plugin search path and naming conventions as implemented by this + * class, and are certainly not required to use this actual class. + * But we do strongly recommend it. + * + * \note This class was introduced in version 1.1 of the Vamp plugin SDK. + */ + +class PluginLoader +{ +public: + /** + * Obtain a pointer to the singleton instance of PluginLoader. + * Use this to obtain your loader object. + */ + static PluginLoader *getInstance(); + + /** + * PluginKey is a string type that is used to identify a plugin + * uniquely within the scope of "the current system". It consists + * of the lower-cased base name of the plugin library, a colon + * separator, and the identifier string for the plugin. It is + * only meaningful in the context of a given plugin path (the one + * returned by PluginHostAdapter::getPluginPath()). + * + * Use composePluginKey() to construct a plugin key from a known + * plugin library name and identifier. + * + * Note: the fact that the library component of the key is + * lower-cased implies that library names are matched + * case-insensitively by the PluginLoader class, regardless of the + * case sensitivity of the underlying filesystem. (Plugin + * identifiers _are_ case sensitive, however.) Also, it is not + * possible to portably extract a working library name from a + * plugin key, as the result may fail on case-sensitive + * filesystems. Use getLibraryPathForPlugin() instead. + */ + typedef std::string PluginKey; + + /** + * PluginKeyList is a sequence of plugin keys, such as returned by + * listPlugins(). + */ + typedef std::vector PluginKeyList; + + /** + * PluginCategoryHierarchy is a sequence of general->specific + * category names, as may be associated with a single plugin. + * This sequence describes the location of a plugin within a + * category forest, containing the human-readable names of the + * plugin's category tree root, followed by each of the nodes down + * to the leaf containing the plugin. + * + * \see getPluginCategory() + */ + typedef std::vector PluginCategoryHierarchy; + + /** + * Search for all available Vamp plugins, and return a list of + * them in the order in which they were found. + */ + PluginKeyList listPlugins(); + + /** + * AdapterFlags contains a set of values that may be OR'd together + * to indicate in which circumstances PluginLoader should use a + * plugin adapter to make a plugin easier to use for a host that + * does not want to cater for complex features. + * + * The available flags are: + * + * ADAPT_INPUT_DOMAIN - If the plugin expects frequency domain + * input, wrap it in a PluginInputDomainAdapter that automatically + * converts the plugin to one that expects time-domain input. + * This enables a host to accommodate time- and frequency-domain + * plugins without needing to do any conversion itself. + * + * ADAPT_CHANNEL_COUNT - Wrap the plugin in a PluginChannelAdapter + * to handle any mismatch between the number of channels of audio + * the plugin can handle and the number available in the host. + * This enables a host to use plugins that may require the input + * to be mixed down to mono, etc., without having to worry about + * doing that itself. + * + * ADAPT_BUFFER_SIZE - Wrap the plugin in a PluginBufferingAdapter + * permitting the host to provide audio input using any block + * size, with no overlap, regardless of the plugin's preferred + * block size (suitable for hosts that read from non-seekable + * streaming media, for example). This adapter introduces some + * run-time overhead and also changes the semantics of the plugin + * slightly (see the PluginBufferingAdapter header documentation + * for details). + * + * ADAPT_ALL_SAFE - Perform all available adaptations that are + * meaningful for the plugin and "safe". Currently this means to + * ADAPT_INPUT_DOMAIN if the plugin wants FrequencyDomain input; + * ADAPT_CHANNEL_COUNT always; and ADAPT_BUFFER_SIZE never. + * + * ADAPT_ALL - Perform all available adaptations that are + * meaningful for the plugin. + * + * See PluginInputDomainAdapter, PluginChannelAdapter and + * PluginBufferingAdapter for more details of the classes that the + * loader may use if these flags are set. + */ + enum AdapterFlags { + + ADAPT_INPUT_DOMAIN = 0x01, + ADAPT_CHANNEL_COUNT = 0x02, + ADAPT_BUFFER_SIZE = 0x04, + + ADAPT_ALL_SAFE = 0x03, + + ADAPT_ALL = 0xff + }; + + /** + * Load a Vamp plugin, given its identifying key. If the plugin + * could not be loaded, returns 0. + * + * The returned plugin should be deleted (using the standard C++ + * delete keyword) after use. + * + * \param adapterFlags a bitwise OR of the values in the AdapterFlags + * enumeration, indicating under which circumstances an adapter should be + * used to wrap the original plugin. If adapterFlags is 0, no + * optional adapters will be used. Otherwise, the returned plugin + * may be of an adapter class type which will behave identically + * to the original plugin, apart from any particular features + * implemented by the adapter itself. + * + * \see AdapterFlags, PluginInputDomainAdapter, PluginChannelAdapter + */ + Plugin *loadPlugin(PluginKey key, + float inputSampleRate, + int adapterFlags = 0); + + /** + * Given a Vamp plugin library name and plugin identifier, return + * the corresponding plugin key in a form suitable for passing in to + * loadPlugin(). + */ + PluginKey composePluginKey(std::string libraryName, + std::string identifier); + + /** + * Return the category hierarchy for a Vamp plugin, given its + * identifying key. + * + * If the plugin has no category information, return an empty + * hierarchy. + * + * \see PluginCategoryHierarchy + */ + PluginCategoryHierarchy getPluginCategory(PluginKey plugin); + + /** + * Return the file path of the dynamic library from which the + * given plugin will be loaded (if available). + */ + std::string getLibraryPathForPlugin(PluginKey plugin); + +protected: + PluginLoader(); + virtual ~PluginLoader(); + + class Impl; + Impl *m_impl; + + static PluginLoader *m_instance; +}; + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginLoader.h) + +#endif + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginSummarisingAdapter.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginSummarisingAdapter.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginSummarisingAdapter.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginSummarisingAdapter.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,197 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_PLUGIN_SUMMARISING_ADAPTER_H_ +#define _VAMP_PLUGIN_SUMMARISING_ADAPTER_H_ + +#include "hostguard.h" +#include "PluginWrapper.h" + +#include + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginSummarisingAdapter.h) + +namespace Vamp { + +namespace HostExt { + +/** + * \class PluginSummarisingAdapter PluginSummarisingAdapter.h + * + * PluginSummarisingAdapter is a Vamp plugin adapter that provides + * summarisation methods such as mean and median averages of output + * features, for use in any context where an available plugin produces + * individual values but the result that is actually needed is some + * sort of aggregate. + * + * To make use of PluginSummarisingAdapter, the host should configure, + * initialise and run the plugin through the adapter interface just as + * normal. Then, after the process and getRemainingFeatures methods + * have been properly called and processing is complete, the host may + * call getSummaryForOutput or getSummaryForAllOutputs to obtain + * summarised features: averages, maximum values, etc, depending on + * the SummaryType passed to the function. + * + * By default PluginSummarisingAdapter calculates a single summary of + * each output's feature across the whole duration of processed audio. + * A host needing summaries of sub-segments of the whole audio may + * call setSummarySegmentBoundaries before retrieving the summaries, + * providing a list of times such that one summary will be provided + * for each segment between two consecutive times. + * + * PluginSummarisingAdapter is straightforward rather than fast. It + * calculates all of the summary types for all outputs always, and + * then returns only the ones that are requested. It is designed on + * the basis that, for most features, summarising and storing + * summarised results is far cheaper than calculating the results in + * the first place. If this is not true for your particular feature, + * PluginSummarisingAdapter may not be the best approach for you. + * + * \note This class was introduced in version 2.0 of the Vamp plugin SDK. + */ + +class PluginSummarisingAdapter : public PluginWrapper +{ +public: + /** + * Construct a PluginSummarisingAdapter wrapping the given plugin. + * The adapter takes ownership of the plugin, which will be + * deleted when the adapter is deleted. + */ + PluginSummarisingAdapter(Plugin *plugin); + virtual ~PluginSummarisingAdapter(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + + void reset(); + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + FeatureSet getRemainingFeatures(); + + typedef std::set SegmentBoundaries; + + /** + * Specify a series of segment boundaries, such that one summary + * will be returned for each of the contiguous intra-boundary + * segments. This function must be called before + * getSummaryForOutput or getSummaryForAllOutputs. + * + * Note that you cannot retrieve results with multiple different + * segmentations by repeatedly calling this function followed by + * one of the getSummary functions. The summaries are all + * calculated at the first call to any getSummary function, and + * once the summaries have been calculated, they remain + * calculated. + */ + void setSummarySegmentBoundaries(const SegmentBoundaries &); + + enum SummaryType { + Minimum = 0, + Maximum = 1, + Mean = 2, + Median = 3, + Mode = 4, + Sum = 5, + Variance = 6, + StandardDeviation = 7, + Count = 8, + + UnknownSummaryType = 999 + }; + + /** + * AveragingMethod indicates how the adapter should handle + * average-based summaries of features whose results are not + * equally spaced in time. + * + * If SampleAverage is specified, summary types based on averages + * will be calculated by treating each result individually without + * regard to its time: for example, the mean will be the sum of + * all values divided by the number of values. + * + * If ContinuousTimeAverage is specified, each feature will be + * considered to have a duration, either as specified in the + * feature's duration field, or until the following feature: thus, + * for example, the mean will be the sum of the products of values + * and durations, divided by the total duration. + * + * Although SampleAverage is useful for many types of feature, + * ContinuousTimeAverage is essential for some situations, for + * example finding the result that spans the largest proportion of + * the input given a feature that emits a new result only when the + * value changes (the modal value integrated over time). + */ + enum AveragingMethod { + SampleAverage = 0, + ContinuousTimeAverage = 1 + }; + + /** + * Return summaries of the features that were returned on the + * given output, using the given SummaryType and AveragingMethod. + * + * The plugin must have been fully run (process() and + * getRemainingFeatures() calls all made as appropriate) before + * this function is called. + */ + FeatureList getSummaryForOutput(int output, + SummaryType type, + AveragingMethod method = SampleAverage); + + /** + * Return summaries of the features that were returned on all of + * the plugin's outputs, using the given SummaryType and + * AveragingMethod. + * + * The plugin must have been fully run (process() and + * getRemainingFeatures() calls all made as appropriate) before + * this function is called. + */ + FeatureSet getSummaryForAllOutputs(SummaryType type, + AveragingMethod method = SampleAverage); + +protected: + class Impl; + Impl *m_impl; +}; + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginSummarisingAdapter.h) + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginWrapper.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginWrapper.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/PluginWrapper.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/PluginWrapper.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,135 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006-2009 Chris Cannam and QMUL. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_PLUGIN_WRAPPER_H_ +#define _VAMP_PLUGIN_WRAPPER_H_ + +#include "hostguard.h" +#include + +_VAMP_SDK_HOSTSPACE_BEGIN(PluginWrapper.h) + +namespace Vamp { + +namespace HostExt { + +/** + * \class PluginWrapper PluginWrapper.h + * + * PluginWrapper is a simple base class for adapter plugins. It takes + * a pointer to a "to be wrapped" Vamp plugin on construction, and + * provides implementations of all the Vamp plugin methods that simply + * delegate through to the wrapped plugin. A subclass can therefore + * override only the methods that are meaningful for the particular + * adapter. + * + * \note This class was introduced in version 1.1 of the Vamp plugin SDK. + */ + +class PluginWrapper : public Plugin +{ +public: + virtual ~PluginWrapper(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const; + + unsigned int getVampApiVersion() const; + std::string getIdentifier() const; + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + + ParameterList getParameterDescriptors() const; + float getParameter(std::string) const; + void setParameter(std::string, float); + + ProgramList getPrograms() const; + std::string getCurrentProgram() const; + void selectProgram(std::string); + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + size_t getMinChannelCount() const; + size_t getMaxChannelCount() const; + + OutputList getOutputDescriptors() const; + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + + FeatureSet getRemainingFeatures(); + + /** + * Return a pointer to the plugin wrapper of type WrapperType + * surrounding this wrapper's plugin, if present. + * + * This is useful in situations where a plugin is wrapped by + * multiple different wrappers (one inside another) and the host + * wants to call some wrapper-specific function on one of the + * layers without having to care about the order in which they are + * wrapped. For example, the plugin returned by + * PluginLoader::loadPlugin may have more than one wrapper; if the + * host wanted to query or fine-tune some property of one of them, + * it would be hard to do so without knowing the order of the + * wrappers. This function therefore gives direct access to the + * wrapper of a particular type. + */ + template + WrapperType *getWrapper() { + WrapperType *w = dynamic_cast(this); + if (w) return w; + PluginWrapper *pw = dynamic_cast(m_plugin); + if (pw) return pw->getWrapper(); + return 0; + } + +protected: + PluginWrapper(Plugin *plugin); // I take ownership of plugin + Plugin *m_plugin; +}; + +} + +} + +_VAMP_SDK_HOSTSPACE_END(PluginWrapper.h) + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/RealTime.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/RealTime.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/RealTime.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/RealTime.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,46 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_HOSTSDK_REALTIME_H_ +#define _VAMP_HOSTSDK_REALTIME_H_ + +// Do not include vamp-sdk/RealTime.h directly from host code. Always +// use this header instead. + +#include "hostguard.h" +#include + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/hostguard.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/hostguard.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/hostguard.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/hostguard.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,69 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_HOSTSDK_HOSTGUARD_H_ +#define _VAMP_HOSTSDK_HOSTGUARD_H_ + +#ifdef _VAMP_IN_PLUGINSDK +#error You have included headers from both vamp-sdk and vamp-hostsdk in the same source file. Please include only vamp-sdk headers in plugin code, and only vamp-hostsdk headers in host code. +#else + +#define _VAMP_IN_HOSTSDK + +#ifdef _VAMP_NO_HOST_NAMESPACE +#define _VAMP_SDK_HOSTSPACE_BEGIN(h) +#define _VAMP_SDK_HOSTSPACE_END(h) +#define _VAMP_SDK_PLUGSPACE_BEGIN(h) +#define _VAMP_SDK_PLUGSPACE_END(h) +#else +#define _VAMP_SDK_HOSTSPACE_BEGIN(h) \ + namespace _VampHost { + +#define _VAMP_SDK_HOSTSPACE_END(h) \ + } \ + using namespace _VampHost; +#define _VAMP_SDK_PLUGSPACE_BEGIN(h) \ + namespace _VampHost { + +#define _VAMP_SDK_PLUGSPACE_END(h) \ + } \ + using namespace _VampHost; +#endif + +#endif + +#endif + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/vamp-hostsdk.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/vamp-hostsdk.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-hostsdk/vamp-hostsdk.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-hostsdk/vamp-hostsdk.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,53 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_HOSTSDK_SINGLE_INCLUDE_H_ +#define _VAMP_HOSTSDK_SINGLE_INCLUDE_H_ + +#include "PluginBase.h" +#include "PluginBufferingAdapter.h" +#include "PluginChannelAdapter.h" +#include "Plugin.h" +#include "PluginHostAdapter.h" +#include "PluginInputDomainAdapter.h" +#include "PluginLoader.h" +#include "PluginSummarisingAdapter.h" +#include "PluginWrapper.h" +#include "RealTime.h" + +#endif + + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/Plugin.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/Plugin.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/Plugin.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/Plugin.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,446 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_SDK_PLUGIN_H_ +#define _VAMP_SDK_PLUGIN_H_ + +#include +#include +#include + +#include "PluginBase.h" +#include "RealTime.h" + +#include "plugguard.h" +_VAMP_SDK_PLUGSPACE_BEGIN(Plugin.h) + +namespace Vamp { + +/** + * \class Plugin Plugin.h + * + * Vamp::Plugin is a base class for plugin instance classes + * that provide feature extraction from audio or related data. + * + * In most cases, the input will be audio and the output will be a + * stream of derived data at a lower sampling resolution than the + * input. + * + * Note that this class inherits several abstract methods from + * PluginBase. These must be implemented by the subclass. + * + * + * PLUGIN LIFECYCLE + * + * Feature extraction plugins are managed differently from real-time + * plugins (such as VST effects). The main difference is that the + * parameters for a feature extraction plugin are configured before + * the plugin is used, and do not change during use. + * + * 1. Host constructs the plugin, passing it the input sample rate. + * The plugin may do basic initialisation, but should not do anything + * computationally expensive at this point. You must make sure your + * plugin is cheap to construct, otherwise you'll seriously affect the + * startup performance of almost all hosts. If you have serious + * initialisation to do, the proper place is in initialise() (step 5). + * + * 2. Host may query the plugin's available outputs. + * + * 3. Host queries programs and parameter descriptors, and may set + * some or all of them. Parameters that are not explicitly set should + * take their default values as specified in the parameter descriptor. + * When a program is set, the parameter values may change and the host + * will re-query them to check. + * + * 4. Host queries the preferred step size, block size and number of + * channels. These may all vary depending on the parameter values. + * (Note however that you cannot make the number of distinct outputs + * dependent on parameter values.) + * + * 5. Plugin is properly initialised with a call to initialise. This + * fixes the step size, block size, and number of channels, as well as + * all of the parameter and program settings. If the values passed in + * to initialise do not match the plugin's advertised preferred values + * from step 4, the plugin may refuse to initialise and return false + * (although if possible it should accept the new values). Any + * computationally expensive setup code should take place here. + * + * 6. Host finally checks the number of values, resolution, extents + * etc per output (which may vary depending on the number of channels, + * step size and block size as well as the parameter values). + * + * 7. Host will repeatedly call the process method to pass in blocks + * of input data. This method may return features extracted from that + * data (if the plugin is causal). + * + * 8. Host will call getRemainingFeatures exactly once, after all the + * input data has been processed. This may return any non-causal or + * leftover features. + * + * 9. At any point after initialise was called, the host may + * optionally call the reset method and restart processing. (This + * does not mean it can change the parameters, which are fixed from + * initialise until destruction.) + * + * A plugin does not need to handle the case where setParameter or + * selectProgram is called after initialise has been called. It's the + * host's responsibility not to do that. Similarly, the plugin may + * safely assume that initialise is called no more than once. + */ + +class Plugin : public PluginBase +{ +public: + virtual ~Plugin() { } + + /** + * Initialise a plugin to prepare it for use with the given number + * of input channels, step size (window increment, in sample + * frames) and block size (window size, in sample frames). + * + * The input sample rate should have been already specified at + * construction time. + * + * Return true for successful initialisation, false if the number + * of input channels, step size and/or block size cannot be + * supported. + */ + virtual bool initialise(size_t inputChannels, + size_t stepSize, + size_t blockSize) = 0; + + /** + * Reset the plugin after use, to prepare it for another clean + * run. Not called for the first initialisation (i.e. initialise + * must also do a reset). + */ + virtual void reset() = 0; + + enum InputDomain { TimeDomain, FrequencyDomain }; + + /** + * Get the plugin's required input domain. + * + * If this is TimeDomain, the samples provided to the process() + * function (below) will be in the time domain, as for a + * traditional audio processing plugin. + * + * If this is FrequencyDomain, the host will carry out a windowed + * FFT of size equal to the negotiated block size on the data + * before passing the frequency bin data in to process(). The + * input data for the FFT will be rotated so as to place the + * origin in the centre of the block. + * The plugin does not get to choose the window type -- the host + * will either let the user do so, or will use a Hanning window. + */ + virtual InputDomain getInputDomain() const = 0; + + /** + * Get the preferred block size (window size -- the number of + * sample frames passed in each block to the process() function). + * This should be called before initialise(). + * + * A plugin that can handle any block size may return 0. The + * final block size will be set in the initialise() call. + */ + virtual size_t getPreferredBlockSize() const { return 0; } + + /** + * Get the preferred step size (window increment -- the distance + * in sample frames between the start frames of consecutive blocks + * passed to the process() function) for the plugin. This should + * be called before initialise(). + * + * A plugin may return 0 if it has no particular interest in the + * step size. In this case, the host should make the step size + * equal to the block size if the plugin is accepting input in the + * time domain. If the plugin is accepting input in the frequency + * domain, the host may use any step size. The final step size + * will be set in the initialise() call. + */ + virtual size_t getPreferredStepSize() const { return 0; } + + /** + * Get the minimum supported number of input channels. + */ + virtual size_t getMinChannelCount() const { return 1; } + + /** + * Get the maximum supported number of input channels. + */ + virtual size_t getMaxChannelCount() const { return 1; } + + struct OutputDescriptor + { + /** + * The name of the output, in computer-usable form. Should be + * reasonably short and without whitespace or punctuation, using + * the characters [a-zA-Z0-9_-] only. + * Example: "zero_crossing_count" + */ + std::string identifier; + + /** + * The human-readable name of the output. + * Example: "Zero Crossing Counts" + */ + std::string name; + + /** + * A human-readable short text describing the output. May be + * empty if the name has said it all already. + * Example: "The number of zero crossing points per processing block" + */ + std::string description; + + /** + * The unit of the output, in human-readable form. + */ + std::string unit; + + /** + * True if the output has the same number of values per sample + * for every output sample. Outputs for which this is false + * are unlikely to be very useful in a general-purpose host. + */ + bool hasFixedBinCount; + + /** + * The number of values per result of the output. Undefined + * if hasFixedBinCount is false. If this is zero, the output + * is point data (i.e. only the time of each output is of + * interest, the value list will be empty). + */ + size_t binCount; + + /** + * The (human-readable) names of each of the bins, if + * appropriate. This is always optional. + */ + std::vector binNames; + + /** + * True if the results in each output bin fall within a fixed + * numeric range (minimum and maximum values). Undefined if + * binCount is zero. + */ + bool hasKnownExtents; + + /** + * Minimum value of the results in the output. Undefined if + * hasKnownExtents is false or binCount is zero. + */ + float minValue; + + /** + * Maximum value of the results in the output. Undefined if + * hasKnownExtents is false or binCount is zero. + */ + float maxValue; + + /** + * True if the output values are quantized to a particular + * resolution. Undefined if binCount is zero. + */ + bool isQuantized; + + /** + * Quantization resolution of the output values (e.g. 1.0 if + * they are all integers). Undefined if isQuantized is false + * or binCount is zero. + */ + float quantizeStep; + + enum SampleType { + + /// Results from each process() align with that call's block start + OneSamplePerStep, + + /// Results are evenly spaced in time (sampleRate specified below) + FixedSampleRate, + + /// Results are unevenly spaced and have individual timestamps + VariableSampleRate + }; + + /** + * Positioning in time of the output results. + */ + SampleType sampleType; + + /** + * Sample rate of the output results, as samples per second. + * Undefined if sampleType is OneSamplePerStep. + * + * If sampleType is VariableSampleRate and this value is + * non-zero, then it may be used to calculate a resolution for + * the output (i.e. the "duration" of each sample, in time, + * will be 1/sampleRate seconds). It's recommended to set + * this to zero if that behaviour is not desired. + */ + float sampleRate; + + /** + * True if the returned results for this output are known to + * have a duration field. + */ + bool hasDuration; + + OutputDescriptor() : // defaults for mandatory non-class-type members + hasFixedBinCount(false), hasKnownExtents(false), isQuantized(false), + sampleType(OneSamplePerStep), hasDuration(false) { } + }; + + typedef std::vector OutputList; + + /** + * Get the outputs of this plugin. An output's index in this list + * is used as its numeric index when looking it up in the + * FeatureSet returned from the process() call. + */ + virtual OutputList getOutputDescriptors() const = 0; + + struct Feature + { + /** + * True if an output feature has its own timestamp. This is + * mandatory if the output has VariableSampleRate, optional if + * the output has FixedSampleRate, and unused if the output + * has OneSamplePerStep. + */ + bool hasTimestamp; + + /** + * Timestamp of the output feature. This is mandatory if the + * output has VariableSampleRate or if the output has + * FixedSampleRate and hasTimestamp is true, and unused + * otherwise. + */ + RealTime timestamp; + + /** + * True if an output feature has a specified duration. This + * is optional if the output has VariableSampleRate or + * FixedSampleRate, and and unused if the output has + * OneSamplePerStep. + */ + bool hasDuration; + + /** + * Duration of the output feature. This is mandatory if the + * output has VariableSampleRate or FixedSampleRate and + * hasDuration is true, and unused otherwise. + */ + RealTime duration; + + /** + * Results for a single sample of this feature. If the output + * hasFixedBinCount, there must be the same number of values + * as the output's binCount count. + */ + std::vector values; + + /** + * Label for the sample of this feature. + */ + std::string label; + + Feature() : // defaults for mandatory non-class-type members + hasTimestamp(false), hasDuration(false) { } + }; + + typedef std::vector FeatureList; + + typedef std::map FeatureSet; // key is output no + + /** + * Process a single block of input data. + * + * If the plugin's inputDomain is TimeDomain, inputBuffers will + * point to one array of floats per input channel, and each of + * these arrays will contain blockSize consecutive audio samples + * (the host will zero-pad as necessary). The timestamp in this + * case will be the real time in seconds of the start of the + * supplied block of samples. + * + * If the plugin's inputDomain is FrequencyDomain, inputBuffers + * will point to one array of floats per input channel, and each + * of these arrays will contain blockSize/2+1 consecutive pairs of + * real and imaginary component floats corresponding to bins + * 0..(blockSize/2) of the FFT output. That is, bin 0 (the first + * pair of floats) contains the DC output, up to bin blockSize/2 + * which contains the Nyquist-frequency output. There will + * therefore be blockSize+2 floats per channel in total. The + * timestamp will be the real time in seconds of the centre of the + * FFT input window (i.e. the very first block passed to process + * might contain the FFT of half a block of zero samples and the + * first half-block of the actual data, with a timestamp of zero). + * + * Return any features that have become available after this + * process call. (These do not necessarily have to fall within + * the process block, except for OneSamplePerStep outputs.) + */ + virtual FeatureSet process(const float *const *inputBuffers, + RealTime timestamp) = 0; + + /** + * After all blocks have been processed, calculate and return any + * remaining features derived from the complete input. + */ + virtual FeatureSet getRemainingFeatures() = 0; + + /** + * Used to distinguish between Vamp::Plugin and other potential + * sibling subclasses of PluginBase. Do not reimplement this + * function in your subclass. + */ + virtual std::string getType() const { return "Feature Extraction Plugin"; } + +protected: + Plugin(float inputSampleRate) : + m_inputSampleRate(inputSampleRate) { } + + float m_inputSampleRate; +}; + +} + +_VAMP_SDK_PLUGSPACE_END(Plugin.h) + +#endif + + + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/PluginAdapter.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/PluginAdapter.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/PluginAdapter.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/PluginAdapter.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,121 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_PLUGIN_ADAPTER_H_ +#define _VAMP_PLUGIN_ADAPTER_H_ + +#include +#include + +#include "Plugin.h" + +#include "plugguard.h" +_VAMP_SDK_PLUGSPACE_BEGIN(PluginAdapter.h) + +namespace Vamp { + +/** + * \class PluginAdapterBase PluginAdapter.h + * + * PluginAdapter and PluginAdapterBase provide a wrapper class that a + * plugin library can use to make its C++ Vamp::Plugin objects + * available through the Vamp C API. + * + * Almost all Vamp plugin libraries will want to make use of this. To + * do so, all they need to do is declare a PluginAdapter for each + * plugin class T in their library. It's very simple, and you need to + * know absolutely nothing about how it works in order to use it. + * Just cut and paste from an existing plugin's discovery function. + * \see vampGetPluginDescriptor + */ + +class PluginAdapterBase +{ +public: + virtual ~PluginAdapterBase(); + + /** + * Return a VampPluginDescriptor describing the plugin that is + * wrapped by this adapter. + */ + const VampPluginDescriptor *getDescriptor(); + +protected: + PluginAdapterBase(); + + virtual Plugin *createPlugin(float inputSampleRate) = 0; + + class Impl; + Impl *m_impl; +}; + +/** + * \class PluginAdapter PluginAdapter.h + * + * PluginAdapter turns a PluginAdapterBase into a specific wrapper for + * a particular plugin implementation. + * + * See PluginAdapterBase. + */ + +template +class PluginAdapter : public PluginAdapterBase +{ +public: + PluginAdapter() : PluginAdapterBase() { } + virtual ~PluginAdapter() { } + +protected: + Plugin *createPlugin(float inputSampleRate) { + P *p = new P(inputSampleRate); + Plugin *plugin = dynamic_cast(p); + if (!plugin) { + std::cerr << "ERROR: PluginAdapter::createPlugin: " + << "Template type is not a plugin!" + << std::endl; + delete p; + return 0; + } + return plugin; + } +}; + +} + +_VAMP_SDK_PLUGSPACE_END(PluginAdapter.h) + +#endif + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/PluginBase.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/PluginBase.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/PluginBase.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/PluginBase.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,262 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_SDK_PLUGIN_BASE_H_ +#define _VAMP_SDK_PLUGIN_BASE_H_ + +#include +#include + +#define VAMP_SDK_VERSION "2.3" +#define VAMP_SDK_MAJOR_VERSION 2 +#define VAMP_SDK_MINOR_VERSION 3 + +#include "plugguard.h" +_VAMP_SDK_PLUGSPACE_BEGIN(PluginBase.h) + +namespace Vamp { + +/** + * A base class for plugins with optional configurable parameters, + * programs, etc. The Vamp::Plugin is derived from this, and + * individual Vamp plugins should derive from that. + * + * This class does not provide the necessary interfaces to instantiate + * or run a plugin. It only specifies an interface for retrieving + * those controls that the host may wish to show to the user for + * editing. It could meaningfully be subclassed by real-time plugins + * or other sorts of plugin as well as Vamp plugins. + */ + +class PluginBase +{ +public: + virtual ~PluginBase() { } + + /** + * Get the Vamp API compatibility level of the plugin. + */ + virtual unsigned int getVampApiVersion() const { return 2; } + + /** + * Get the computer-usable name of the plugin. This should be + * reasonably short and contain no whitespace or punctuation + * characters. It may only contain the characters [a-zA-Z0-9_-]. + * This is the authoritative way for a program to identify a + * plugin within a given library. + * + * This text may be visible to the user, but it should not be the + * main text used to identify a plugin to the user (that will be + * the name, below). + * + * Example: "zero_crossings" + */ + virtual std::string getIdentifier() const = 0; + + /** + * Get a human-readable name or title of the plugin. This + * should be brief and self-contained, as it may be used to + * identify the plugin to the user in isolation (i.e. without also + * showing the plugin's "identifier"). + * + * Example: "Zero Crossings" + */ + virtual std::string getName() const = 0; + + /** + * Get a human-readable description for the plugin, typically + * a line of text that may optionally be displayed in addition + * to the plugin's "name". May be empty if the name has said + * it all already. + * + * Example: "Detect and count zero crossing points" + */ + virtual std::string getDescription() const = 0; + + /** + * Get the name of the author or vendor of the plugin in + * human-readable form. This should be a short identifying text, + * as it may be used to label plugins from the same source in a + * menu or similar. + */ + virtual std::string getMaker() const = 0; + + /** + * Get the copyright statement or licensing summary for the + * plugin. This can be an informative text, without the same + * presentation constraints as mentioned for getMaker above. + */ + virtual std::string getCopyright() const = 0; + + /** + * Get the version number of the plugin. + */ + virtual int getPluginVersion() const = 0; + + + struct ParameterDescriptor + { + /** + * The name of the parameter, in computer-usable form. Should + * be reasonably short, and may only contain the characters + * [a-zA-Z0-9_-]. + */ + std::string identifier; + + /** + * The human-readable name of the parameter. + */ + std::string name; + + /** + * A human-readable short text describing the parameter. May be + * empty if the name has said it all already. + */ + std::string description; + + /** + * The unit of the parameter, in human-readable form. + */ + std::string unit; + + /** + * The minimum value of the parameter. + */ + float minValue; + + /** + * The maximum value of the parameter. + */ + float maxValue; + + /** + * The default value of the parameter. The plugin should + * ensure that parameters have this value on initialisation + * (i.e. the host is not required to explicitly set parameters + * if it wants to use their default values). + */ + float defaultValue; + + /** + * True if the parameter values are quantized to a particular + * resolution. + */ + bool isQuantized; + + /** + * Quantization resolution of the parameter values (e.g. 1.0 + * if they are all integers). Undefined if isQuantized is + * false. + */ + float quantizeStep; + + /** + * Names for the quantized values. If isQuantized is true, + * this may either be empty or contain one string for each of + * the quantize steps from minValue up to maxValue inclusive. + * Undefined if isQuantized is false. + * + * If these names are provided, they should be shown to the + * user in preference to the values themselves. The user may + * never see the actual numeric values unless they are also + * encoded in the names. + */ + std::vector valueNames; + + ParameterDescriptor() : // the defaults are invalid: you must set them + minValue(0), maxValue(0), defaultValue(0), isQuantized(false) { } + }; + + typedef std::vector ParameterList; + + /** + * Get the controllable parameters of this plugin. + */ + virtual ParameterList getParameterDescriptors() const { + return ParameterList(); + } + + /** + * Get the value of a named parameter. The argument is the identifier + * field from that parameter's descriptor. + */ + virtual float getParameter(std::string) const { return 0.0; } + + /** + * Set a named parameter. The first argument is the identifier field + * from that parameter's descriptor. + */ + virtual void setParameter(std::string, float) { } + + + typedef std::vector ProgramList; + + /** + * Get the program settings available in this plugin. A program + * is a named shorthand for a set of parameter values; changing + * the program may cause the plugin to alter the values of its + * published parameters (and/or non-public internal processing + * parameters). The host should re-read the plugin's parameter + * values after setting a new program. + * + * The programs must have unique names. + */ + virtual ProgramList getPrograms() const { return ProgramList(); } + + /** + * Get the current program. + */ + virtual std::string getCurrentProgram() const { return ""; } + + /** + * Select a program. (If the given program name is not one of the + * available programs, do nothing.) + */ + virtual void selectProgram(std::string) { } + + /** + * Get the type of plugin. This is to be implemented by the + * immediate subclass, not by actual plugins. Do not attempt to + * implement this in plugin code. + */ + virtual std::string getType() const = 0; +}; + +} + +_VAMP_SDK_PLUGSPACE_END(PluginBase.h) + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/RealTime.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/RealTime.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/RealTime.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/RealTime.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,167 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +/* + This is a modified version of a source file from the + Rosegarden MIDI and audio sequencer and notation editor. + This file copyright 2000-2006 Chris Cannam. + Relicensed by the author as detailed above. +*/ + +#ifndef _VAMP_REAL_TIME_H_ +#define _VAMP_REAL_TIME_H_ + +#include +#include + +#ifndef _WIN32 +struct timeval; +#endif + +#include "plugguard.h" +_VAMP_SDK_PLUGSPACE_BEGIN(RealTime.h) + +namespace Vamp { + +/** + * \class RealTime RealTime.h + * + * RealTime represents time values to nanosecond precision + * with accurate arithmetic and frame-rate conversion functions. + */ + +struct RealTime +{ + int sec; + int nsec; + + int usec() const { return nsec / 1000; } + int msec() const { return nsec / 1000000; } + + RealTime(): sec(0), nsec(0) {} + RealTime(int s, int n); + + RealTime(const RealTime &r) : + sec(r.sec), nsec(r.nsec) { } + + static RealTime fromSeconds(double sec); + static RealTime fromMilliseconds(int msec); + +#ifndef _WIN32 + static RealTime fromTimeval(const struct timeval &); +#endif + + RealTime &operator=(const RealTime &r) { + sec = r.sec; nsec = r.nsec; return *this; + } + + RealTime operator+(const RealTime &r) const { + return RealTime(sec + r.sec, nsec + r.nsec); + } + RealTime operator-(const RealTime &r) const { + return RealTime(sec - r.sec, nsec - r.nsec); + } + RealTime operator-() const { + return RealTime(-sec, -nsec); + } + + bool operator <(const RealTime &r) const { + if (sec == r.sec) return nsec < r.nsec; + else return sec < r.sec; + } + + bool operator >(const RealTime &r) const { + if (sec == r.sec) return nsec > r.nsec; + else return sec > r.sec; + } + + bool operator==(const RealTime &r) const { + return (sec == r.sec && nsec == r.nsec); + } + + bool operator!=(const RealTime &r) const { + return !(r == *this); + } + + bool operator>=(const RealTime &r) const { + if (sec == r.sec) return nsec >= r.nsec; + else return sec >= r.sec; + } + + bool operator<=(const RealTime &r) const { + if (sec == r.sec) return nsec <= r.nsec; + else return sec <= r.sec; + } + + RealTime operator/(int d) const; + + /** + * Return the ratio of two times. + */ + double operator/(const RealTime &r) const; + + /** + * Return a human-readable debug-type string to full precision + * (probably not a format to show to a user directly) + */ + std::string toString() const; + + /** + * Return a user-readable string to the nearest millisecond + * in a form like HH:MM:SS.mmm + */ + std::string toText(bool fixedDp = false) const; + + /** + * Convert a RealTime into a sample frame at the given sample rate. + */ + static long realTime2Frame(const RealTime &r, unsigned int sampleRate); + + /** + * Convert a sample frame at the given sample rate into a RealTime. + */ + static RealTime frame2RealTime(long frame, unsigned int sampleRate); + + static const RealTime zeroTime; +}; + +std::ostream &operator<<(std::ostream &out, const RealTime &rt); + +} + +_VAMP_SDK_PLUGSPACE_END(RealTime.h) + +#endif diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/plugguard.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/plugguard.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/plugguard.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/plugguard.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,98 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_SDK_PLUGGUARD_H_ +#define _VAMP_SDK_PLUGGUARD_H_ + +/** + * Normal usage should be: + * + * - Plugins include vamp-sdk/Plugin.h or vamp-sdk/PluginBase.h. + * These files include this header, which specifies an appropriate + * namespace for the plugin classes to avoid any risk of conflict + * with non-plugin class implementations in the host on load. + * + * - Hosts include vamp-hostsdk/Plugin.h, vamp-hostsdk/PluginBase.h, + * vamp-hostsdk/PluginHostAdapter, vamp-hostsdk/PluginLoader.h etc. + * These files include vamp-hostsdk/hostguard.h, which makes a note + * that we are in a host. A file such as vamp-hostsdk/Plugin.h + * then simply includes vamp-sdk/Plugin.h, and this guard header + * takes notice of the fact that it has been included from a host + * and leaves the plugin namespace unset. + * + * Problems will occur when a host includes files directly from the + * vamp-sdk directory. There are two reasons this might happen: + * mistake, perhaps owing to ignorance of the fact that this isn't + * allowed (particularly since it was the normal mechanism in v1 of + * the SDK); and a wish to incorporate plugin code directly into the + * host rather than having to load it. + * + * What if the host does include a vamp-sdk header by mistake? We can + * catch it if it's included before something from vamp-hostsdk. If + * it's included after something from vamp-hostsdk, it will work OK + * anyway. The remaining problem case is where nothing from + * vamp-hostsdk is included in the same file. We can't catch that. + */ + +#ifndef _VAMP_IN_HOSTSDK + +#define _VAMP_IN_PLUGINSDK 1 + +#ifdef _VAMP_NO_PLUGIN_NAMESPACE +#define _VAMP_SDK_PLUGSPACE_BEGIN(h) +#define _VAMP_SDK_PLUGSPACE_END(h) +#else +#ifdef _VAMP_PLUGIN_IN_HOST_NAMESPACE +#define _VAMP_SDK_PLUGSPACE_BEGIN(h) \ + namespace _VampHost { + +#define _VAMP_SDK_PLUGSPACE_END(h) \ + } \ + using namespace _VampHost; +#else +#define _VAMP_SDK_PLUGSPACE_BEGIN(h) \ + namespace _VampPlugin { + +#define _VAMP_SDK_PLUGSPACE_END(h) \ + } \ + using namespace _VampPlugin; +#endif +#endif + +#endif + +#endif + diff -Nru mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/vamp-sdk.h mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/vamp-sdk.h --- mixxx-1.10.1-1/lib/vamp-2.3/vamp-sdk/vamp-sdk.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/vamp-2.3/vamp-sdk/vamp-sdk.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,46 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_SDK_SINGLE_INCLUDE_H_ +#define _VAMP_SDK_SINGLE_INCLUDE_H_ + +#include "PluginBase.h" +#include "Plugin.h" +#include "RealTime.h" + +#endif + + diff -Nru mixxx-1.10.1-1/lib/xwax/debug.h mixxx-1.11.0-bzr3863/lib/xwax/debug.h --- mixxx-1.10.1-1/lib/xwax/debug.h 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/xwax/debug.h 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 Mark Hills + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include + +#ifdef DEBUG +#define debug(...) fprintf(stderr, __VA_ARGS__) +#define dassert(x) assert(x) +#else +#define debug(...) +#define dassert(x) +#endif + +#endif diff -Nru mixxx-1.10.1-1/lib/xwax/lut.c mixxx-1.11.0-bzr3863/lib/xwax/lut.c --- mixxx-1.10.1-1/lib/xwax/lut.c 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/xwax/lut.c 2013-05-09 13:58:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Mark Hills + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -34,25 +34,25 @@ /* Initialise an empty hash lookup table to store the given number * of timecode -> position lookups */ -int lut_init(struct lut_t *lut, int nslots) +int lut_init(struct lut *lut, int nslots) { int n, hashes; size_t bytes; hashes = 1 << HASH_BITS; - bytes = sizeof(struct slot_t) * nslots + sizeof(slot_no_t) * hashes; + bytes = sizeof(struct slot) * nslots + sizeof(slot_no_t) * hashes; fprintf(stderr, "Lookup table has %d hashes to %d slots" " (%d slots per hash, %zuKb)\n", hashes, nslots, nslots / hashes, bytes / 1024); - lut->slot = (struct slot_t*)malloc(sizeof(struct slot_t) * nslots); + lut->slot = malloc(sizeof(struct slot) * nslots); if (lut->slot == NULL) { perror("malloc"); return -1; } - lut->table = (slot_no_t*)malloc(sizeof(slot_no_t) * hashes); + lut->table = malloc(sizeof(slot_no_t) * hashes); if (lut->table == NULL) { perror("malloc"); return -1; @@ -67,17 +67,18 @@ } -void lut_clear(struct lut_t *lut) +void lut_clear(struct lut *lut) { free(lut->table); + free(lut->slot); } -void lut_push(struct lut_t *lut, unsigned int timecode) +void lut_push(struct lut *lut, unsigned int timecode) { unsigned int hash; slot_no_t slot_no; - struct slot_t *slot; + struct slot *slot; slot_no = lut->avail++; /* take the next available slot */ @@ -90,11 +91,11 @@ } -unsigned int lut_lookup(struct lut_t *lut, unsigned int timecode) +unsigned int lut_lookup(struct lut *lut, unsigned int timecode) { unsigned int hash; slot_no_t slot_no; - struct slot_t *slot; + struct slot *slot; hash = HASH(timecode); slot_no = lut->table[hash]; diff -Nru mixxx-1.10.1-1/lib/xwax/lut.cpp mixxx-1.11.0-bzr3863/lib/xwax/lut.cpp --- mixxx-1.10.1-1/lib/xwax/lut.cpp 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/xwax/lut.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Mark Hills + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -34,19 +34,19 @@ /* Initialise an empty hash lookup table to store the given number * of timecode -> position lookups */ -int lut_init(struct lut_t *lut, int nslots) +int lut_init(struct lut *lut, int nslots) { int n, hashes; size_t bytes; hashes = 1 << HASH_BITS; - bytes = sizeof(struct slot_t) * nslots + sizeof(slot_no_t) * hashes; + bytes = sizeof(struct slot) * nslots + sizeof(slot_no_t) * hashes; fprintf(stderr, "Lookup table has %d hashes to %d slots" " (%d slots per hash, %zuKb)\n", hashes, nslots, nslots / hashes, bytes / 1024); - lut->slot = (struct slot_t*)malloc(sizeof(struct slot_t) * nslots); + lut->slot = (struct slot*)malloc(sizeof(struct slot) * nslots); if (lut->slot == NULL) { perror("malloc"); return -1; @@ -67,17 +67,18 @@ } -void lut_clear(struct lut_t *lut) +void lut_clear(struct lut *lut) { free(lut->table); + free(lut->slot); } -void lut_push(struct lut_t *lut, unsigned int timecode) +void lut_push(struct lut *lut, unsigned int timecode) { unsigned int hash; slot_no_t slot_no; - struct slot_t *slot; + struct slot *slot; slot_no = lut->avail++; /* take the next available slot */ @@ -90,11 +91,11 @@ } -unsigned int lut_lookup(struct lut_t *lut, unsigned int timecode) +unsigned int lut_lookup(struct lut *lut, unsigned int timecode) { unsigned int hash; slot_no_t slot_no; - struct slot_t *slot; + struct slot *slot; hash = HASH(timecode); slot_no = lut->table[hash]; diff -Nru mixxx-1.10.1-1/lib/xwax/lut.h mixxx-1.11.0-bzr3863/lib/xwax/lut.h --- mixxx-1.10.1-1/lib/xwax/lut.h 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/xwax/lut.h 2013-05-09 13:58:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Mark Hills + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,21 +22,21 @@ typedef unsigned int slot_no_t; -struct slot_t { +struct slot { unsigned int timecode; slot_no_t next; /* next slot with the same hash */ }; -struct lut_t { - struct slot_t *slot; +struct lut { + struct slot *slot; slot_no_t *table, /* hash -> slot lookup */ avail; /* next available slot */ }; -int lut_init(struct lut_t *lut, int nslots); -void lut_clear(struct lut_t *lut); +int lut_init(struct lut *lut, int nslots); +void lut_clear(struct lut *lut); -void lut_push(struct lut_t *lut, unsigned int timecode); -unsigned int lut_lookup(struct lut_t *lut, unsigned int timecode); +void lut_push(struct lut *lut, unsigned int timecode); +unsigned int lut_lookup(struct lut *lut, unsigned int timecode); #endif diff -Nru mixxx-1.10.1-1/lib/xwax/pitch.h mixxx-1.11.0-bzr3863/lib/xwax/pitch.h --- mixxx-1.10.1-1/lib/xwax/pitch.h 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/xwax/pitch.h 2013-05-09 13:58:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Mark Hills + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,17 +23,17 @@ /* Values for the filter concluded experimentally */ #define ALPHA (1.0/512) -#define BETA (ALPHA/1024) +#define BETA (ALPHA/256) /* State of the pitch calculation filter */ -struct pitch_t { - float dt, x, v; +struct pitch { + double dt, x, v; }; /* Prepare the filter for observations every dt seconds */ -static inline void pitch_init(struct pitch_t *p, float dt) +static inline void pitch_init(struct pitch *p, double dt) { p->dt = dt; p->x = 0.0; @@ -46,9 +46,9 @@ * Because the vinyl uses timestamps, the values for dx are discrete * rather than smooth. */ -static inline void pitch_dt_observation(struct pitch_t *p, float dx) +static inline void pitch_dt_observation(struct pitch *p, double dx) { - float predicted_x, predicted_v, residual_x; + double predicted_x, predicted_v, residual_x; predicted_x = p->x + p->v * p->dt; predicted_v = p->v; @@ -63,7 +63,7 @@ /* Get the pitch after filtering */ -static inline float pitch_current(struct pitch_t *p) +static inline double pitch_current(struct pitch *p) { return p->v; } diff -Nru mixxx-1.10.1-1/lib/xwax/timecoder.c mixxx-1.11.0-bzr3863/lib/xwax/timecoder.c --- mixxx-1.10.1-1/lib/xwax/timecoder.c 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/xwax/timecoder.c 2013-05-09 13:58:23.000000000 +0000 @@ -1,15 +1,15 @@ /* - * Copyright (C) 2010 Mark Hills + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2, as published by the Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details. - * + * * You should have received a copy of the GNU General Public License * version 2 along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, @@ -23,6 +23,7 @@ #include #include +#include "debug.h" #include "timecoder.h" #define ZERO_THRESHOLD 128 @@ -31,16 +32,16 @@ #define REF_PEAKS_AVG 48 /* in wave cycles */ -/* The number of correct bits which come in before the timecode - * is declared valid. Set this too low, and risk the record skipping around - * (often to blank areas of track) during scratching */ +/* The number of correct bits which come in before the timecode is + * declared valid. Set this too low, and risk the record skipping + * around (often to blank areas of track) during scratching */ #define VALID_BITS 24 #define MONITOR_DECAY_EVERY 512 /* in samples */ #define SQ(x) ((x)*(x)) - +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) /* Timecode definitions */ @@ -48,8 +49,7 @@ #define SWITCH_PRIMARY 0x2 /* use left channel (not right) as primary */ #define SWITCH_POLARITY 0x4 /* read bit values in negative (not positive) */ - -static struct timecode_def_t timecode_def[] = { +static struct timecode_def timecodes[] = { { .name = "serato_2a", .desc = "Serato 2nd Ed., side A", @@ -71,7 +71,7 @@ .seed = 0x8f3c6, .taps = 0x4f0d8, /* reverse of side A */ .length = 922000, - .safe = 905000, + .safe = 908000, .lookup = false }, { @@ -95,8 +95,8 @@ .seed = 0x134503, .taps = 0x041040, .length = 1500000, - .safe = 1214000, - .lookup = false + .safe = 605000, + .lookup = false }, { .name = "traktor_b", @@ -107,7 +107,7 @@ .seed = 0x32066c, .taps = 0x041040, /* same as side A */ .length = 2110000, - .safe = 1814000, + .safe = 907000, .lookup = false }, { @@ -119,7 +119,7 @@ .seed = 0x22c90, .taps = 0x00008, .length = 950000, - .safe = 923000, + .safe = 655000, .lookup = false }, { @@ -131,17 +131,14 @@ .seed = 0x22c90, .taps = 0x00008, .length = 312000, - .safe = 310000, + .safe = 238000, .lookup = false }, - { - .name = NULL - } }; - -/* Linear Feeback Shift Register in the forward direction. New values - * are generated at the least-significant bit. */ +/* + * Calculate LFSR bit + */ static inline bits_t lfsr(bits_t code, bits_t taps) { @@ -158,8 +155,12 @@ return xrs & 0x1; } +/* + * Linear Feedback Shift Register in the forward direction. New values + * are generated at the least-significant bit. + */ -static inline bits_t fwd(bits_t current, struct timecode_def_t *def) +static inline bits_t fwd(bits_t current, struct timecode_def *def) { bits_t l; @@ -169,8 +170,11 @@ return (current >> 1) | (l << (def->bits - 1)); } +/* + * Linear Feedback Shift Register in the reverse direction + */ -static inline bits_t rev(bits_t current, struct timecode_def_t *def) +static inline bits_t rev(bits_t current, struct timecode_def *def) { bits_t l, mask; @@ -181,24 +185,13 @@ return ((current << 1) & mask) | l; } +/* + * Where necessary, build the lookup table required for this timecode + * + * Return: -1 if not enough memory could be allocated, otherwise 0 + */ -static struct timecode_def_t* find_definition(const char *name) -{ - struct timecode_def_t *def; - - def = &timecode_def[0]; - while (def->name) { - if (!strcmp(def->name, name)) - return def; - def++; - } - return NULL; -} - - -/* Where necessary, build the lookup table required for this timecode */ - -static int build_lookup(struct timecode_def_t *def) +static int build_lookup(struct timecode_def *def) { unsigned int n; bits_t current, last; @@ -213,58 +206,93 @@ return -1; current = def->seed; - + for (n = 0; n < def->length; n++) { /* timecode must not wrap */ - assert(lut_lookup(&def->lut, current) == (unsigned)-1); + dassert(lut_lookup(&def->lut, current) == (unsigned)-1); lut_push(&def->lut, current); last = current; current = fwd(current, def); - assert(rev(current, def) == last); + dassert(rev(current, def) == last); } def->lookup = true; - - return 0; + + return 0; } +/* + * Find a timecode definition by name + * + * Return: pointer to timecode definition, or NULL if not found + */ + +struct timecode_def* timecoder_find_definition(const char *name) +{ + struct timecode_def *def, *end; + + def = &timecodes[0]; + end = def + ARRAY_SIZE(timecodes); + + for (;;) { + if (!strcmp(def->name, name)) + break; + + def++; -/* Free the timecoder lookup tables when they are no longer needed */ + if (def == end) + return NULL; + } + + if (build_lookup(def) == -1) + return NULL; + + return def; +} + +/* + * Free the timecoder lookup tables when they are no longer needed + */ void timecoder_free_lookup(void) { - struct timecode_def_t *def; + struct timecode_def *def, *end; - def = &timecode_def[0]; - while (def->name) { + def = &timecodes[0]; + end = def + ARRAY_SIZE(timecodes); + + while (def < end) { if (def->lookup) lut_clear(&def->lut); def++; } } +/* + * Initialise filter values for one channel + */ -static void init_channel(struct timecoder_channel_t *ch) +static void init_channel(struct timecoder_channel *ch) { - ch->positive = 0; + ch->positive = false; ch->zero = 0; } +/* + * Initialise a timecode decoder at the given reference speed + * + * Return: -1 if the timecoder could not be initialised, otherwise 0 + */ -/* Initialise a timecode decoder at the given reference speed */ - -int timecoder_init(struct timecoder_t *tc, const char *def_name, double speed, - unsigned int sample_rate) +void timecoder_init(struct timecoder *tc, struct timecode_def *def, + double speed, unsigned int sample_rate) { + assert(def != NULL); + /* A definition contains a lookup table which can be shared * across multiple timecoders */ - tc->def = find_definition(def_name); - if (tc->def == NULL) { - fprintf(stderr, "Timecode definition '%s' is not known.\n", def_name); - return -1; - } - if (build_lookup(tc->def) == -1) - return -1; + assert(def->lookup); + tc->def = def; tc->speed = speed; tc->dt = 1.0 / sample_rate; @@ -282,25 +310,29 @@ tc->timecode_ticker = 0; tc->mon = NULL; - - return 0; } +/* + * Clear resources associated with a timecode decoder + */ -/* Clear a timecode decoder */ - -void timecoder_clear(struct timecoder_t *tc) +void timecoder_clear(struct timecoder *tc) { - timecoder_monitor_clear(tc); + assert(tc->mon == NULL); } +/* + * Initialise a raster display of the incoming audio + * + * The monitor (otherwise known as 'scope' in the interface) is an x-y + * display of the post-calibrated incoming audio. + * + * Return: -1 if not enough memory could be allocated, otherwise 0 + */ -/* The monitor (otherwise known as 'scope' in the interface) is the - * display of the incoming audio. Initialise one for the given - * timecoder */ - -int timecoder_monitor_init(struct timecoder_t *tc, int size) +int timecoder_monitor_init(struct timecoder *tc, int size) { + assert(tc->mon == NULL); tc->mon_size = size; tc->mon = malloc(SQ(tc->mon_size)); if (tc->mon == NULL) { @@ -312,73 +344,78 @@ return 0; } +/* + * Clear the monitor on the given timecoder + */ -/* Clear the monitor on the given timecoder */ - -void timecoder_monitor_clear(struct timecoder_t *tc) +void timecoder_monitor_clear(struct timecoder *tc) { - if (tc->mon) { - free(tc->mon); - tc->mon = NULL; - } + assert(tc->mon != NULL); + free(tc->mon); + tc->mon = NULL; } +/* + * Update channel information with axis-crossings + */ -static void detect_zero_crossing(struct timecoder_channel_t *ch, - signed int v, float alpha) +static void detect_zero_crossing(struct timecoder_channel *ch, + signed int v, double alpha) { ch->crossing_ticker++; - ch->swapped = 0; + ch->swapped = false; if (v > ch->zero + ZERO_THRESHOLD && !ch->positive) { - ch->swapped = 1; - ch->positive = 1; + ch->swapped = true; + ch->positive = true; ch->crossing_ticker = 0; } else if (v < ch->zero - ZERO_THRESHOLD && ch->positive) { - ch->swapped = 1; - ch->positive = 0; + ch->swapped = true; + ch->positive = false; ch->crossing_ticker = 0; } - + ch->zero += alpha * (v - ch->zero); } +/* + * Plot the given sample value in the x-y monitor + */ -/* Plot the given sample value in the monitor (scope) */ - -static void update_monitor(struct timecoder_t *tc, signed int x, signed int y) +static void update_monitor(struct timecoder *tc, signed int x, signed int y) { int px, py, p; - float v, w; + double v, w; if (!tc->mon) return; /* Decay the pixels already in the montior */ - + if (++tc->mon_counter % MONITOR_DECAY_EVERY == 0) { for (p = 0; p < SQ(tc->mon_size); p++) { if (tc->mon[p]) tc->mon[p] = tc->mon[p] * 7 / 8; } } - - v = (float)x / tc->ref_level / 2; - w = (float)y / tc->ref_level / 2; - + + v = (double)x / tc->ref_level / 2; + w = (double)y / tc->ref_level / 2; + px = tc->mon_size / 2 + (v * tc->mon_size / 2); py = tc->mon_size / 2 + (w * tc->mon_size / 2); /* Set the pixel value to white */ - + if (px > 0 && px < tc->mon_size && py > 0 && py < tc->mon_size) tc->mon[py * tc->mon_size + px] = 0xff; } +/* + * Extract the bitstream from the sample value + */ -/* Process a single bitstream reading */ - -static void process_bitstream(struct timecoder_t *tc, signed int m) +static void process_bitstream(struct timecoder *tc, signed int m) { bits_t b; @@ -411,28 +448,25 @@ } /* Take note of the last time we read a valid timecode */ - + tc->timecode_ticker = 0; /* Adjust the reference level based on this new peak */ tc->ref_level = (tc->ref_level * (REF_PEAKS_AVG - 1) + m) / REF_PEAKS_AVG; -#ifdef DEBUG_BITSTREAM - fprintf(stderr, "%+6d zero, %+6d (ref %+6d)\t= %d%c (%5d)\n", - tc->primary.zero, - m, - tc->ref_level, - b, - tc->valid_counter == 0 ? 'x' : ' ', - tc->valid_counter); -#endif + debug("%+6d zero, %+6d (ref %+6d)\t= %d%c (%5d)\n", + tc->primary.zero, + m, tc->ref_level, + b, tc->valid_counter == 0 ? 'x' : ' ', + tc->valid_counter); } +/* + * Process a single sample from the incoming audio + */ -/* Process a single sample from the incoming audio */ - -static void process_sample(struct timecoder_t *tc, +static void process_sample(struct timecoder *tc, signed int primary, signed int secondary) { signed int m; /* pcm sample, sum of two shorts */ @@ -445,14 +479,22 @@ /* If an axis has been crossed, use the direction of the crossing * to work out the direction of the vinyl */ - if (tc->primary.swapped) { - tc->forwards = (tc->primary.positive != tc->secondary.positive); - if (tc->def->flags & SWITCH_PHASE) - tc->forwards = !tc->forwards; - } if (tc->secondary.swapped) { - tc->forwards = (tc->primary.positive == tc->secondary.positive); - if (tc->def->flags & SWITCH_PHASE) - tc->forwards = !tc->forwards; + if (tc->primary.swapped || tc->secondary.swapped) { + bool forwards; + + if (tc->primary.swapped) { + forwards = (tc->primary.positive != tc->secondary.positive); + } else { + forwards = (tc->primary.positive == tc->secondary.positive); + } + + if (tc->def->flags & SWITCH_PHASE) + forwards = !forwards; + + if (forwards != tc->forwards) { /* direction has changed */ + tc->forwards = forwards; + tc->valid_counter = 0; + } } /* If any axis has been crossed, register movement using the pitch @@ -461,7 +503,7 @@ if (!tc->primary.swapped && !tc->secondary.swapped) pitch_dt_observation(&tc->pitch, 0.0); else { - float dx; + double dx; dx = 1.0 / tc->def->resolution / 4; if (!tc->forwards) @@ -481,10 +523,43 @@ tc->timecode_ticker++; } +/* + * Cycle to the next timecode definition which has a valid lookup + * + * Return: pointer to timecode definition + */ + +static struct timecode_def* next_definition(struct timecode_def *def) +{ + assert(def != NULL); + + do { + def++; + + if (def > timecodes + ARRAY_SIZE(timecodes)) + def = timecodes; + + } while (!def->lookup); + + return def; +} + +/* + * Change the timecode definition to the next available + */ -/* Submit and decode a block of PCM audio data to the timecoder */ +void timecoder_cycle_definition(struct timecoder *tc) +{ + tc->def = next_definition(tc->def); + tc->valid_counter = 0; + tc->timecode_ticker = 0; +} -void timecoder_submit(struct timecoder_t *tc, const signed short *pcm, size_t npcm) +/* + * Submit and decode a block of PCM audio data to the timecode decoder + */ + +void timecoder_submit(struct timecoder *tc, const signed short *pcm, size_t npcm) { while (npcm--) { signed int primary, secondary; @@ -504,13 +579,19 @@ } } +/* + * Get the last-known position of the timecode + * + * If now data is available or if too few bits have been error + * checked, then this counts as invalid. The last known position is + * given along with the time elapsed since the position stamp was + * read. + * + * Return: the known position of the timecode, or -1 if not known + * Post: if when != NULL, *when is the elapsed time in seconds + */ -/* Return the known position in the timecode, or -1 if not known. If - * two few bits have been error-checked, then this also counts as - * invalid. If 'when' is given, return the time, in seconds since this - * value was read. */ - -signed int timecoder_get_position(struct timecoder_t *tc, float *when) +signed int timecoder_get_position(struct timecoder *tc, double *when) { signed int r; @@ -518,13 +599,13 @@ r = lut_lookup(&tc->def->lut, tc->bitstream); if (r >= 0) { - //normalize position to milliseconds, not timecode steps -- Owen - r = (float)r * (1000.0 / (tc->def->resolution * tc->speed)); + //normalize position to milliseconds, not timecode steps -- Owen + r = (float)r * (1000.0 / (tc->def->resolution * tc->speed)); if (when) *when = tc->timecode_ticker * tc->dt; return r; } } - + return -1; } diff -Nru mixxx-1.10.1-1/lib/xwax/timecoder.h mixxx-1.11.0-bzr3863/lib/xwax/timecoder.h --- mixxx-1.10.1-1/lib/xwax/timecoder.h 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/xwax/timecoder.h 2013-05-09 13:58:23.000000000 +0000 @@ -1,15 +1,15 @@ -/* - * Copyright (C) 2010 Mark Hills +/* + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2, as published by the Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details. - * + * * You should have received a copy of the GNU General Public License * version 2 along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, @@ -24,17 +24,14 @@ #include #endif -/* #include "device.h" */ #include "lut.h" #include "pitch.h" #define TIMECODER_CHANNELS 2 - typedef unsigned int bits_t; - -struct timecode_def_t { +struct timecode_def { char *name, *desc; int bits, /* number of bits in string */ resolution, /* wave cycles per second */ @@ -44,31 +41,29 @@ unsigned int length, /* in cycles */ safe; /* last 'safe' timecode number (for auto disconnect) */ bool lookup; /* true if lut has been generated */ - struct lut_t lut; + struct lut lut; }; - -struct timecoder_channel_t { - int positive, /* wave is in positive part of cycle */ +struct timecoder_channel { + bool positive, /* wave is in positive part of cycle */ swapped; /* wave recently swapped polarity */ signed int zero; unsigned int crossing_ticker; /* samples since we last crossed zero */ }; - -struct timecoder_t { - struct timecode_def_t *def; +struct timecoder { + struct timecode_def *def; double speed; /* Precomputed values */ - float dt, zero_alpha; + double dt, zero_alpha; /* Pitch information */ - int forwards; - struct timecoder_channel_t primary, secondary; - struct pitch_t pitch; + bool forwards; + struct timecoder_channel primary, secondary; + struct pitch pitch; /* Numerical timecode */ @@ -84,52 +79,65 @@ int mon_size, mon_counter; }; - +struct timecode_def* timecoder_find_definition(const char *name); void timecoder_free_lookup(void); -int timecoder_init(struct timecoder_t *tc, const char *def_name, double speed, - unsigned int sample_rate); -void timecoder_clear(struct timecoder_t *tc); - -int timecoder_monitor_init(struct timecoder_t *tc, int size); -void timecoder_monitor_clear(struct timecoder_t *tc); +void timecoder_init(struct timecoder *tc, struct timecode_def *def, + double speed, unsigned int sample_rate); +void timecoder_clear(struct timecoder *tc); + +int timecoder_monitor_init(struct timecoder *tc, int size); +void timecoder_monitor_clear(struct timecoder *tc); + +void timecoder_cycle_definition(struct timecoder *tc); +void timecoder_submit(struct timecoder *tc, const signed short *pcm, size_t npcm); +signed int timecoder_get_position(struct timecoder *tc, double *when); -void timecoder_submit(struct timecoder_t *tc, const signed short *pcm, size_t npcm); - -signed int timecoder_get_position(struct timecoder_t *tc, float *when); +/* + * The timecode definition currently in use by this decoder + */ +static inline struct timecode_def* timecoder_get_definition(struct timecoder *tc) +{ + return tc->def; +} -/* Return the pitch relative to reference playback speed */ +/* + * Return the pitch relative to reference playback speed + */ -static inline float timecoder_get_pitch(struct timecoder_t *tc) +static inline double timecoder_get_pitch(struct timecoder *tc) { return pitch_current(&tc->pitch) / tc->speed; } - -/* The last 'safe' timecode value on the record. Beyond this value, we +/* + * The last 'safe' timecode value on the record. Beyond this value, we * probably want to ignore the timecode values, as we will hit the - * label of the record. */ + * label of the record. + */ -static inline unsigned int timecoder_get_safe(struct timecoder_t *tc) +static inline unsigned int timecoder_get_safe(struct timecoder *tc) { - return tc->def->safe * 1000 / (tc->def->resolution * tc->speed); + return tc->def->safe; } +/* + * The resolution of the timecode. This is the number of bits per + * second at reference playback speed + */ -/* The resolution of the timecode. This is the number of bits per - * second at reference playback speed */ - -static inline double timecoder_get_resolution(struct timecoder_t *tc) +static inline double timecoder_get_resolution(struct timecoder *tc) { return tc->def->resolution * tc->speed; } +/* + * The number of revolutions per second of the timecode vinyl, + * used only for visual display + */ -/* The number of revolutions per second of the timecode vinyl, - * used only for visual display */ - -static inline double timecoder_revs_per_sec(struct timecoder_t *tc) +static inline double timecoder_revs_per_sec(struct timecoder *tc) { return (33.0 + 1.0 / 3) * tc->speed / 60; } diff -Nru mixxx-1.10.1-1/lib/xwax/timecoder_win32.cpp mixxx-1.11.0-bzr3863/lib/xwax/timecoder_win32.cpp --- mixxx-1.10.1-1/lib/xwax/timecoder_win32.cpp 2012-06-30 15:32:22.000000000 +0000 +++ mixxx-1.11.0-bzr3863/lib/xwax/timecoder_win32.cpp 2013-05-09 13:58:23.000000000 +0000 @@ -1,15 +1,15 @@ /* - * Copyright (C) 2010 Mark Hills + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2, as published by the Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details. - * + * * You should have received a copy of the GNU General Public License * version 2 along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, @@ -25,6 +25,7 @@ #include #endif +#include "debug.h" #include "timecoder.h" #define ZERO_THRESHOLD 128 @@ -33,16 +34,16 @@ #define REF_PEAKS_AVG 48 /* in wave cycles */ -/* The number of correct bits which come in before the timecode - * is declared valid. Set this too low, and risk the record skipping around - * (often to blank areas of track) during scratching */ +/* The number of correct bits which come in before the timecode is + * declared valid. Set this too low, and risk the record skipping + * around (often to blank areas of track) during scratching */ #define VALID_BITS 24 #define MONITOR_DECAY_EVERY 512 /* in samples */ #define SQ(x) ((x)*(x)) - +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) /* Timecode definitions */ @@ -50,8 +51,7 @@ #define SWITCH_PRIMARY 0x2 /* use left channel (not right) as primary */ #define SWITCH_POLARITY 0x4 /* read bit values in negative (not positive) */ - -static struct timecode_def_t timecode_def[] = { +static struct timecode_def timecodes[] = { { "serato_2a", "Serato 2nd Ed., side A", @@ -73,7 +73,7 @@ 0x8f3c6, 0x4f0d8, /* reverse of side A */ 922000, - 905000, + 908000, false }, { @@ -97,7 +97,7 @@ 0x134503, 0x041040, 1500000, - 1214000, + 605000, false }, { @@ -109,7 +109,7 @@ 0x32066c, 0x041040, /* same as side A */ 2110000, - 1814000, + 907000, false }, { @@ -121,7 +121,7 @@ 0x22c90, 0x00008, 950000, - 923000, + 655000, false }, { @@ -133,17 +133,16 @@ 0x22c90, 0x00008, 312000, - 310000, + 238000, false }, { NULL } }; - - -/* Linear Feeback Shift Register in the forward direction. New values - * are generated at the least-significant bit. */ +/* + * Calculate LFSR bit + */ static inline bits_t lfsr(bits_t code, bits_t taps) { @@ -160,8 +159,12 @@ return xrs & 0x1; } +/* + * Linear Feedback Shift Register in the forward direction. New values + * are generated at the least-significant bit. + */ -static inline bits_t fwd(bits_t current, struct timecode_def_t *def) +static inline bits_t fwd(bits_t current, struct timecode_def *def) { bits_t l; @@ -171,8 +174,11 @@ return (current >> 1) | (l << (def->bits - 1)); } +/* + * Linear Feedback Shift Register in the reverse direction + */ -static inline bits_t rev(bits_t current, struct timecode_def_t *def) +static inline bits_t rev(bits_t current, struct timecode_def *def) { bits_t l, mask; @@ -183,24 +189,13 @@ return ((current << 1) & mask) | l; } +/* + * Where necessary, build the lookup table required for this timecode + * + * Return: -1 if not enough memory could be allocated, otherwise 0 + */ -static struct timecode_def_t* find_definition(const char *name) -{ - struct timecode_def_t *def; - - def = &timecode_def[0]; - while (def->name) { - if (!strcmp(def->name, name)) - return def; - def++; - } - return NULL; -} - - -/* Where necessary, build the lookup table required for this timecode */ - -static int build_lookup(struct timecode_def_t *def) +static int build_lookup(struct timecode_def *def) { unsigned int n; bits_t current, last; @@ -215,58 +210,93 @@ return -1; current = def->seed; - + for (n = 0; n < def->length; n++) { /* timecode must not wrap */ - assert(lut_lookup(&def->lut, current) == (unsigned)-1); + dassert(lut_lookup(&def->lut, current) == (unsigned)-1); lut_push(&def->lut, current); last = current; current = fwd(current, def); - assert(rev(current, def) == last); + dassert(rev(current, def) == last); } def->lookup = true; - - return 0; + + return 0; } +/* + * Find a timecode definition by name + * + * Return: pointer to timecode definition, or NULL if not found + */ -/* Free the timecoder lookup tables when they are no longer needed */ +struct timecode_def* timecoder_find_definition(const char *name) +{ + struct timecode_def *def, *end; + + def = &timecodes[0]; + end = def + ARRAY_SIZE(timecodes); + + for (;;) { + if (!strcmp(def->name, name)) + break; + + def++; + + if (def == end) + return NULL; + } + + if (build_lookup(def) == -1) + return NULL; + + return def; +} + +/* + * Free the timecoder lookup tables when they are no longer needed + */ void timecoder_free_lookup(void) { - struct timecode_def_t *def; + struct timecode_def *def, *end; + + def = &timecodes[0]; + end = def + ARRAY_SIZE(timecodes); - def = &timecode_def[0]; - while (def->name) { + while (def < end) { if (def->lookup) lut_clear(&def->lut); def++; } } +/* + * Initialise filter values for one channel + */ -static void init_channel(struct timecoder_channel_t *ch) +static void init_channel(struct timecoder_channel *ch) { - ch->positive = 0; + ch->positive = false; ch->zero = 0; } +/* + * Initialise a timecode decoder at the given reference speed + * + * Return: -1 if the timecoder could not be initialised, otherwise 0 + */ -/* Initialise a timecode decoder at the given reference speed */ - -int timecoder_init(struct timecoder_t *tc, const char *def_name, double speed, - unsigned int sample_rate) +void timecoder_init(struct timecoder *tc, struct timecode_def *def, + double speed, unsigned int sample_rate) { + assert(def != NULL); + /* A definition contains a lookup table which can be shared * across multiple timecoders */ - tc->def = find_definition(def_name); - if (tc->def == NULL) { - fprintf(stderr, "Timecode definition '%s' is not known.\n", def_name); - return -1; - } - if (build_lookup(tc->def) == -1) - return -1; + assert(def->lookup); + tc->def = def; tc->speed = speed; tc->dt = 1.0 / sample_rate; @@ -284,25 +314,29 @@ tc->timecode_ticker = 0; tc->mon = NULL; - - return 0; } +/* + * Clear resources associated with a timecode decoder + */ -/* Clear a timecode decoder */ - -void timecoder_clear(struct timecoder_t *tc) +void timecoder_clear(struct timecoder *tc) { - timecoder_monitor_clear(tc); + assert(tc->mon == NULL); } +/* + * Initialise a raster display of the incoming audio + * + * The monitor (otherwise known as 'scope' in the interface) is an x-y + * display of the post-calibrated incoming audio. + * + * Return: -1 if not enough memory could be allocated, otherwise 0 + */ -/* The monitor (otherwise known as 'scope' in the interface) is the - * display of the incoming audio. Initialise one for the given - * timecoder */ - -int timecoder_monitor_init(struct timecoder_t *tc, int size) +int timecoder_monitor_init(struct timecoder *tc, int size) { + assert(tc->mon == NULL); tc->mon_size = size; tc->mon = (unsigned char*)malloc(SQ(tc->mon_size)); if (tc->mon == NULL) { @@ -314,73 +348,78 @@ return 0; } +/* + * Clear the monitor on the given timecoder + */ -/* Clear the monitor on the given timecoder */ - -void timecoder_monitor_clear(struct timecoder_t *tc) +void timecoder_monitor_clear(struct timecoder *tc) { - if (tc->mon) { - free(tc->mon); - tc->mon = NULL; - } + assert(tc->mon != NULL); + free(tc->mon); + tc->mon = NULL; } +/* + * Update channel information with axis-crossings + */ -static void detect_zero_crossing(struct timecoder_channel_t *ch, - signed int v, float alpha) +static void detect_zero_crossing(struct timecoder_channel *ch, + signed int v, double alpha) { ch->crossing_ticker++; - ch->swapped = 0; + ch->swapped = false; if (v > ch->zero + ZERO_THRESHOLD && !ch->positive) { - ch->swapped = 1; - ch->positive = 1; + ch->swapped = true; + ch->positive = true; ch->crossing_ticker = 0; } else if (v < ch->zero - ZERO_THRESHOLD && ch->positive) { - ch->swapped = 1; - ch->positive = 0; + ch->swapped = true; + ch->positive = false; ch->crossing_ticker = 0; } - + ch->zero += alpha * (v - ch->zero); } +/* + * Plot the given sample value in the x-y monitor + */ -/* Plot the given sample value in the monitor (scope) */ - -static void update_monitor(struct timecoder_t *tc, signed int x, signed int y) +static void update_monitor(struct timecoder *tc, signed int x, signed int y) { int px, py, p; - float v, w; + double v, w; if (!tc->mon) return; /* Decay the pixels already in the montior */ - + if (++tc->mon_counter % MONITOR_DECAY_EVERY == 0) { for (p = 0; p < SQ(tc->mon_size); p++) { if (tc->mon[p]) tc->mon[p] = tc->mon[p] * 7 / 8; } } - - v = (float)x / tc->ref_level / 2; - w = (float)y / tc->ref_level / 2; - + + v = (double)x / tc->ref_level / 2; + w = (double)y / tc->ref_level / 2; + px = tc->mon_size / 2 + (v * tc->mon_size / 2); py = tc->mon_size / 2 + (w * tc->mon_size / 2); /* Set the pixel value to white */ - + if (px > 0 && px < tc->mon_size && py > 0 && py < tc->mon_size) tc->mon[py * tc->mon_size + px] = 0xff; } +/* + * Extract the bitstream from the sample value + */ -/* Process a single bitstream reading */ - -static void process_bitstream(struct timecoder_t *tc, signed int m) +static void process_bitstream(struct timecoder *tc, signed int m) { bits_t b; @@ -413,28 +452,25 @@ } /* Take note of the last time we read a valid timecode */ - + tc->timecode_ticker = 0; /* Adjust the reference level based on this new peak */ tc->ref_level = (tc->ref_level * (REF_PEAKS_AVG - 1) + m) / REF_PEAKS_AVG; -#ifdef DEBUG_BITSTREAM - fprintf(stderr, "%+6d zero, %+6d (ref %+6d)\t= %d%c (%5d)\n", - tc->primary.zero, - m, - tc->ref_level, - b, - tc->valid_counter == 0 ? 'x' : ' ', - tc->valid_counter); -#endif + debug("%+6d zero, %+6d (ref %+6d)\t= %d%c (%5d)\n", + tc->primary.zero, + m, tc->ref_level, + b, tc->valid_counter == 0 ? 'x' : ' ', + tc->valid_counter); } +/* + * Process a single sample from the incoming audio + */ -/* Process a single sample from the incoming audio */ - -static void process_sample(struct timecoder_t *tc, +static void process_sample(struct timecoder *tc, signed int primary, signed int secondary) { signed int m; /* pcm sample, sum of two shorts */ @@ -447,14 +483,22 @@ /* If an axis has been crossed, use the direction of the crossing * to work out the direction of the vinyl */ - if (tc->primary.swapped) { - tc->forwards = (tc->primary.positive != tc->secondary.positive); - if (tc->def->flags & SWITCH_PHASE) - tc->forwards = !tc->forwards; - } if (tc->secondary.swapped) { - tc->forwards = (tc->primary.positive == tc->secondary.positive); - if (tc->def->flags & SWITCH_PHASE) - tc->forwards = !tc->forwards; + if (tc->primary.swapped || tc->secondary.swapped) { + bool forwards; + + if (tc->primary.swapped) { + forwards = (tc->primary.positive != tc->secondary.positive); + } else { + forwards = (tc->primary.positive == tc->secondary.positive); + } + + if (tc->def->flags & SWITCH_PHASE) + forwards = !forwards; + + if (forwards != tc->forwards) { /* direction has changed */ + tc->forwards = forwards; + tc->valid_counter = 0; + } } /* If any axis has been crossed, register movement using the pitch @@ -463,7 +507,7 @@ if (!tc->primary.swapped && !tc->secondary.swapped) pitch_dt_observation(&tc->pitch, 0.0); else { - float dx; + double dx; dx = 1.0 / tc->def->resolution / 4; if (!tc->forwards) @@ -483,10 +527,43 @@ tc->timecode_ticker++; } +/* + * Cycle to the next timecode definition which has a valid lookup + * + * Return: pointer to timecode definition + */ + +static struct timecode_def* next_definition(struct timecode_def *def) +{ + assert(def != NULL); + + do { + def++; + + if (def > timecodes + ARRAY_SIZE(timecodes)) + def = timecodes; + + } while (!def->lookup); + + return def; +} + +/* + * Change the timecode definition to the next available + */ -/* Submit and decode a block of PCM audio data to the timecoder */ +void timecoder_cycle_definition(struct timecoder *tc) +{ + tc->def = next_definition(tc->def); + tc->valid_counter = 0; + tc->timecode_ticker = 0; +} -void timecoder_submit(struct timecoder_t *tc, const signed short *pcm, size_t npcm) +/* + * Submit and decode a block of PCM audio data to the timecode decoder + */ + +void timecoder_submit(struct timecoder *tc, const signed short *pcm, size_t npcm) { while (npcm--) { signed int primary, secondary; @@ -506,13 +583,19 @@ } } +/* + * Get the last-known position of the timecode + * + * If now data is available or if too few bits have been error + * checked, then this counts as invalid. The last known position is + * given along with the time elapsed since the position stamp was + * read. + * + * Return: the known position of the timecode, or -1 if not known + * Post: if when != NULL, *when is the elapsed time in seconds + */ -/* Return the known position in the timecode, or -1 if not known. If - * two few bits have been error-checked, then this also counts as - * invalid. If 'when' is given, return the time, in seconds since this - * value was read. */ - -signed int timecoder_get_position(struct timecoder_t *tc, float *when) +signed int timecoder_get_position(struct timecoder *tc, double *when) { signed int r; @@ -520,13 +603,13 @@ r = lut_lookup(&tc->def->lut, tc->bitstream); if (r >= 0) { - //normalize position to milliseconds, not timecode steps -- Owen - r = (float)r * (1000.0 / (tc->def->resolution * tc->speed)); + //normalize position to milliseconds, not timecode steps -- Owen + r = (float)r * (1000.0 / (tc->def->resolution * tc->speed)); if (when) *when = tc->timecode_ticker * tc->dt; return r; } } - + return -1; } diff -Nru mixxx-1.10.1-1/plugins/soundsourcem4a/LICENSE mixxx-1.11.0-bzr3863/plugins/soundsourcem4a/LICENSE --- mixxx-1.10.1-1/plugins/soundsourcem4a/LICENSE 2012-06-30 15:32:21.000000000 +0000 +++ mixxx-1.11.0-bzr3863/plugins/soundsourcem4a/LICENSE 2013-05-09 13:58:23.000000000 +0000 @@ -1,5 +1,5 @@ Mixxx M4A Playback Plugin, compatible with Mixxx 1.8.0 -Copyright (C) 2009-2010 Mixxx development team +Copyright (C) 2009-2010 Mixxx Development Team The source code for Mixxx and the Mixxx M4A Playback Plugin is licensed under the GPL as follows: @@ -7,7 +7,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. +(at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of diff -Nru mixxx-1.10.1-1/res/controllers/Akai MPD24.midi.xml mixxx-1.11.0-bzr3863/res/controllers/Akai MPD24.midi.xml --- mixxx-1.10.1-1/res/controllers/Akai MPD24.midi.xml 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/res/controllers/Akai MPD24.midi.xml 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,355 @@ + + + + Akai MPD24 + klico + MIDI mapping for Akai MPD24 + http://mixxx.org/forums/viewtopic.php?f=7&t=39 + + + + + [Master] + crossfader + 0xB0 + 17 + + + + [Master] + balance + 0xB0 + 32 + + + + [Master] + volume + 0xB0 + 3 + + + + [Master] + headVolume + 0xB0 + 26 + + + + [Master] + headMix + 0xB0 + 4 + + + + [Channel1] + play + 0x90 + 48 + + + + [Channel1] + play + 0x80 + 48 + + + + [Channel1] + back + 0x90 + 44 + + + + [Channel1] + back + 0x80 + 44 + + + + [Channel1] + fwd + 0x90 + 45 + + + + [Channel1] + fwd + 0x80 + 45 + + + + [Channel1] + rate_temp_down + 0x90 + 36 + + + + [Channel1] + rate_temp_down + 0x80 + 36 + + + + [Channel1] + rate_temp_up + 0x90 + 37 + + + + [Channel1] + rate_temp_up + 0x80 + 37 + + + + [Channel1] + volume + 0xB0 + 1 + + + + [Channel1] + rate + 0xB0 + 2 + + + + [Channel1] + pfl + 0x90 + 41 + + + + [Channel1] + pfl + 0x80 + 41 + + + + [Channel1] + cue_default + 0x90 + 49 + + + + [Channel1] + cue_default + 0x80 + 49 + + + + [Channel1] + flanger + 0x90 + 40 + + + + [Channel1] + flanger + 0x80 + 40 + + + + [Channel1] + filterLow + 0xB0 + 7 + + + + [Channel1] + filterMid + 0xB0 + 9 + + + + [Channel1] + filterHigh + 0xB0 + 11 + + + + [Channel1] + pregain + 0xB0 + 13 + + + + [Channel2] + play + 0x90 + 50 + + + + [Channel2] + play + 0x80 + 50 + + + + [Channel2] + back + 0x90 + 46 + + + + [Channel2] + back + 0x80 + 46 + + + + [Channel2] + fwd + 0x90 + 47 + + + + [Channel2] + fwd + 0x80 + 47 + + + + [Channel2] + rate_temp_down + 0x90 + 38 + + + + [Channel2] + rate_temp_down + 0x80 + 38 + + + + [Channel2] + rate_temp_up + 0x90 + 39 + + + + [Channel2] + rate_temp_up + 0x80 + 39 + + + + [Channel2] + volume + 0xB0 + 6 + + + + [Channel2] + rate + 0xB0 + 5 + + + + [Channel2] + pfl + 0x90 + 42 + + + + [Channel2] + pfl + 0x80 + 42 + + + + [Channel2] + cue_default + 0x90 + 51 + + + + [Channel2] + cue_default + 0x80 + 51 + + + + [Channel2] + flanger + 0x90 + 43 + + + + [Channel2] + flanger + 0x80 + 43 + + + + [Channel2] + filterLow + 0xB0 + 8 + + + + [Channel2] + filterMid + 0xB0 + 10 + + + + [Channel2] + filterHigh + 0xB0 + 12 + + + + [Channel2] + pregain + 0xB0 + 14 + + + + diff -Nru mixxx-1.10.1-1/res/controllers/Akai-LPD8-RK-scripts.js mixxx-1.11.0-bzr3863/res/controllers/Akai-LPD8-RK-scripts.js --- mixxx-1.10.1-1/res/controllers/Akai-LPD8-RK-scripts.js 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/res/controllers/Akai-LPD8-RK-scripts.js 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,595 @@ +function LPD8RK() {} +LPD8RK.debug=false; + +//set defaults - don't change these +LPD8RK.oldHotcueBank=0;//storage for the last active hotcue bank - used for bank indicator lights +LPD8RK.LEDinterval=300;//interval in milliseconds for LED update +LPD8RK.hotcueClear=false;//if true, hitting hotcue button clears it. +LPD8RK.loopbuttonDown=false;//if true, special loop functions with knob modifiers are enabled. +LPD8RK.looplen=0x40;//default position of looplength dial - active when loop buttons are held down +LPD8RK.looptype="beatloop";//default looptype - beatloop if <64, beatlooproll otherwise +LPD8RK.loopmove=0.0125;//default loop move distance in seconds +LPD8RK.doreloop=true;//don't change this +LPD8RK.beatjumpstep=1;//default beat jump step in beats +LPD8RK.vol=new Array();//array of volumes to return to after mute - don't change +LPD8RK.hotcueBank=1;//default hotcue bank to show on PAD setting, adjustable by knob + + +//array of valid LED addresses +LPD8RK.validLEDS = new Array(); +LPD8RK.validLEDS[0x90]={0x2b : true,0x27 : true,0x2a : true,0x26 : true,0x29 : true,0x25 : true,0x28 : true,0x24 : true}; +LPD8RK.validLEDS[0x91]={0x2c : true,0x27 : true,0x2e : true,0x2a : true,0x26 : true,0x24 : true,0x25 : true,0x23 : true}; +LPD8RK.validLEDS[0x92]={0x48 : true,0x41 : true,0x47 : true,0x40 : true,0x45 : true,0x3e : true,0x43 : true,0x3c : true}; +LPD8RK.validLEDS[0x93]={0x30 : true,0x29 : true,0x2f : true,0x28 : true,0x2d : true,0x26 : true,0x2b : true,0x24 : true}; +LPD8RK.validLEDS[0xb0]={0x01 : true,0x09 : true,0x04 : true,0x08 : true,0x03 : true,0x06 : true,0x03 : true,0x05 : true}; +LPD8RK.validLEDS[0xb1]={0x01 : true,0x09 : true,0x04 : true,0x08 : true,0x03 : true,0x06 : true,0x03 : true,0x05 : true}; +LPD8RK.validLEDS[0xb2]={0x01 : true,0x09 : true,0x04 : true,0x08 : true,0x03 : true,0x06 : true,0x03 : true,0x05 : true}; +LPD8RK.validLEDS[0xb3]={0x01 : true,0x09 : true,0x04 : true,0x08 : true,0x03 : true,0x06 : true,0x03 : true,0x05 : true}; + + +//map hotcue pads and leds +LPD8RK.hotcues = new Array(); +//preset 1 (group, cuenum, status, ctrl) +//initialize +LPD8RK.hotcues["902b"] = new Array(); +LPD8RK.hotcues["9027"] = new Array(); +LPD8RK.hotcues["902a"] = new Array(); +LPD8RK.hotcues["9026"] = new Array(); +LPD8RK.hotcues["9029"] = new Array(); +LPD8RK.hotcues["9025"] = new Array(); +//bank 1 +LPD8RK.hotcues["902b"][1] = new Array("[Channel1]", "1", 0x90, 0x2b); +LPD8RK.hotcues["9027"][1] = new Array("[Channel1]", "2", 0x90, 0x27); +LPD8RK.hotcues["902a"][1] = new Array("[Channel1]", "3", 0x90, 0x2a); +LPD8RK.hotcues["9026"][1] = new Array("[Channel1]", "4", 0x90, 0x26); +LPD8RK.hotcues["9029"][1] = new Array("[Channel1]", "5", 0x90, 0x29); +LPD8RK.hotcues["9025"][1] = new Array("[Channel1]", "6", 0x90, 0x25); +//bank 2 +LPD8RK.hotcues["902b"][2] = new Array("[Channel1]", "7", 0x90, 0x2b); +LPD8RK.hotcues["9027"][2] = new Array("[Channel1]", "8", 0x90, 0x27); +LPD8RK.hotcues["902a"][2] = new Array("[Channel1]", "9", 0x90, 0x2a); +LPD8RK.hotcues["9026"][2] = new Array("[Channel1]", "10", 0x90, 0x26); +LPD8RK.hotcues["9029"][2] = new Array("[Channel1]", "11", 0x90, 0x29); +LPD8RK.hotcues["9025"][2] = new Array("[Channel1]", "12", 0x90, 0x25); +//bank 3 +LPD8RK.hotcues["902b"][3] = new Array("[Channel1]", "13", 0x90, 0x2b); +LPD8RK.hotcues["9027"][3] = new Array("[Channel1]", "14", 0x90, 0x27); +LPD8RK.hotcues["902a"][3] = new Array("[Channel1]", "15", 0x90, 0x2a); +LPD8RK.hotcues["9026"][3] = new Array("[Channel1]", "16", 0x90, 0x26); +LPD8RK.hotcues["9029"][3] = new Array("[Channel1]", "17", 0x90, 0x29); +LPD8RK.hotcues["9025"][3] = new Array("[Channel1]", "18", 0x90, 0x25); +//bank 4 +LPD8RK.hotcues["902b"][4] = new Array("[Channel1]", "19", 0x90, 0x2b); +LPD8RK.hotcues["9027"][4] = new Array("[Channel1]", "20", 0x90, 0x27); +LPD8RK.hotcues["902a"][4] = new Array("[Channel1]", "21", 0x90, 0x2a); +LPD8RK.hotcues["9026"][4] = new Array("[Channel1]", "22", 0x90, 0x26); +LPD8RK.hotcues["9029"][4] = new Array("[Channel1]", "23", 0x90, 0x29); +LPD8RK.hotcues["9025"][4] = new Array("[Channel1]", "24", 0x90, 0x25); +//bank 5 +LPD8RK.hotcues["902b"][5] = new Array("[Channel1]", "25", 0x90, 0x2b); +LPD8RK.hotcues["9027"][5] = new Array("[Channel1]", "26", 0x90, 0x27); +LPD8RK.hotcues["902a"][5] = new Array("[Channel1]", "27", 0x90, 0x2a); +LPD8RK.hotcues["9026"][5] = new Array("[Channel1]", "28", 0x90, 0x26); +LPD8RK.hotcues["9029"][5] = new Array("[Channel1]", "29", 0x90, 0x29); +LPD8RK.hotcues["9025"][5] = new Array("[Channel1]", "30", 0x90, 0x25); + +//################## +//preset 2 (group, cuenum, status, ctrl) +//initialize +LPD8RK.hotcues["912c"] = new Array(); +LPD8RK.hotcues["9127"] = new Array(); +LPD8RK.hotcues["912e"] = new Array(); +LPD8RK.hotcues["912a"] = new Array(); +LPD8RK.hotcues["9126"] = new Array(); +LPD8RK.hotcues["9124"] = new Array(); +//bank 1 +LPD8RK.hotcues["912c"][1] = new Array("[Channel2]", "1", 0x91, 0x2c); +LPD8RK.hotcues["9127"][1] = new Array("[Channel2]", "2", 0x91, 0x27); +LPD8RK.hotcues["912e"][1] = new Array("[Channel2]", "3", 0x91, 0x2e); +LPD8RK.hotcues["912a"][1] = new Array("[Channel2]", "4", 0x91, 0x2a); +LPD8RK.hotcues["9126"][1] = new Array("[Channel2]", "5", 0x91, 0x26); +LPD8RK.hotcues["9124"][1] = new Array("[Channel2]", "6", 0x91, 0x24); +//bank 2 +LPD8RK.hotcues["912c"][2] = new Array("[Channel2]", "7", 0x91, 0x2c); +LPD8RK.hotcues["9127"][2] = new Array("[Channel2]", "8", 0x91, 0x27); +LPD8RK.hotcues["912e"][2] = new Array("[Channel2]", "9", 0x91, 0x2e); +LPD8RK.hotcues["912a"][2] = new Array("[Channel2]", "10", 0x91, 0x2a); +LPD8RK.hotcues["9126"][2] = new Array("[Channel2]", "11", 0x91, 0x26); +LPD8RK.hotcues["9124"][2] = new Array("[Channel2]", "12", 0x91, 0x24); +//bank 3 +LPD8RK.hotcues["912c"][3] = new Array("[Channel2]", "13", 0x91, 0x2c); +LPD8RK.hotcues["9127"][3] = new Array("[Channel2]", "14", 0x91, 0x27); +LPD8RK.hotcues["912e"][3] = new Array("[Channel2]", "15", 0x91, 0x2e); +LPD8RK.hotcues["912a"][3] = new Array("[Channel2]", "16", 0x91, 0x2a); +LPD8RK.hotcues["9126"][3] = new Array("[Channel2]", "17", 0x91, 0x26); +LPD8RK.hotcues["9124"][3] = new Array("[Channel2]", "18", 0x91, 0x24); +//bank 4 +LPD8RK.hotcues["912c"][4] = new Array("[Channel2]", "19", 0x91, 0x2c); +LPD8RK.hotcues["9127"][4] = new Array("[Channel2]", "20", 0x91, 0x27); +LPD8RK.hotcues["912e"][4] = new Array("[Channel2]", "21", 0x91, 0x2e); +LPD8RK.hotcues["912a"][4] = new Array("[Channel2]", "22", 0x91, 0x2a); +LPD8RK.hotcues["9126"][4] = new Array("[Channel2]", "23", 0x91, 0x26); +LPD8RK.hotcues["9124"][4] = new Array("[Channel2]", "24", 0x91, 0x24); +//bank 5 +LPD8RK.hotcues["912c"][5] = new Array("[Channel2]", "25", 0x91, 0x2c); +LPD8RK.hotcues["9127"][5] = new Array("[Channel2]", "26", 0x91, 0x27); +LPD8RK.hotcues["912e"][5] = new Array("[Channel2]", "27", 0x91, 0x2e); +LPD8RK.hotcues["912a"][5] = new Array("[Channel2]", "28", 0x91, 0x2a); +LPD8RK.hotcues["9126"][5] = new Array("[Channel2]", "29", 0x91, 0x26); +LPD8RK.hotcues["9124"][5] = new Array("[Channel2]", "30", 0x91, 0x24); + +//################## +//preset 3 (group, cuenum, status, ctrl) +//initialize +LPD8RK.hotcues["9248"] = new Array(); +LPD8RK.hotcues["9241"] = new Array(); +LPD8RK.hotcues["9247"] = new Array(); +LPD8RK.hotcues["9240"] = new Array(); +LPD8RK.hotcues["9245"] = new Array(); +LPD8RK.hotcues["923e"] = new Array(); +//bank 1 +LPD8RK.hotcues["9248"][1] = new Array("[Sampler1]", "1", 0x92, 0x48); +LPD8RK.hotcues["9241"][1] = new Array("[Sampler1]", "2", 0x92, 0x41); +LPD8RK.hotcues["9247"][1] = new Array("[Sampler1]", "3", 0x92, 0x47); +LPD8RK.hotcues["9240"][1] = new Array("[Sampler1]", "4", 0x92, 0x40); +LPD8RK.hotcues["9245"][1] = new Array("[Sampler1]", "5", 0x92, 0x45); +LPD8RK.hotcues["923e"][1] = new Array("[Sampler1]", "6", 0x92, 0x3e); +//bank 2 +LPD8RK.hotcues["9248"][2] = new Array("[Sampler1]", "7", 0x92, 0x48); +LPD8RK.hotcues["9241"][2] = new Array("[Sampler1]", "8", 0x92, 0x41); +LPD8RK.hotcues["9247"][2] = new Array("[Sampler1]", "9", 0x92, 0x47); +LPD8RK.hotcues["9240"][2] = new Array("[Sampler1]", "10", 0x92, 0x40); +LPD8RK.hotcues["9245"][2] = new Array("[Sampler1]", "11", 0x92, 0x45); +LPD8RK.hotcues["923e"][2] = new Array("[Sampler1]", "12", 0x92, 0x3e); +//bank 3 +LPD8RK.hotcues["9248"][3] = new Array("[Sampler1]", "13", 0x92, 0x48); +LPD8RK.hotcues["9241"][3] = new Array("[Sampler1]", "14", 0x92, 0x41); +LPD8RK.hotcues["9247"][3] = new Array("[Sampler1]", "15", 0x92, 0x47); +LPD8RK.hotcues["9240"][3] = new Array("[Sampler1]", "16", 0x92, 0x40); +LPD8RK.hotcues["9245"][3] = new Array("[Sampler1]", "17", 0x92, 0x45); +LPD8RK.hotcues["923e"][3] = new Array("[Sampler1]", "18", 0x92, 0x3e); +//bank 4 +LPD8RK.hotcues["9248"][4] = new Array("[Sampler1]", "19", 0x92, 0x48); +LPD8RK.hotcues["9241"][4] = new Array("[Sampler1]", "20", 0x92, 0x41); +LPD8RK.hotcues["9247"][4] = new Array("[Sampler1]", "21", 0x92, 0x47); +LPD8RK.hotcues["9240"][4] = new Array("[Sampler1]", "22", 0x92, 0x40); +LPD8RK.hotcues["9245"][4] = new Array("[Sampler1]", "23", 0x92, 0x45); +LPD8RK.hotcues["923e"][4] = new Array("[Sampler1]", "24", 0x92, 0x3e); +//bank 5 +LPD8RK.hotcues["9248"][5] = new Array("[Sampler1]", "25", 0x92, 0x48); +LPD8RK.hotcues["9241"][5] = new Array("[Sampler1]", "26", 0x92, 0x41); +LPD8RK.hotcues["9247"][5] = new Array("[Sampler1]", "27", 0x92, 0x47); +LPD8RK.hotcues["9240"][5] = new Array("[Sampler1]", "28", 0x92, 0x40); +LPD8RK.hotcues["9245"][5] = new Array("[Sampler1]", "29", 0x92, 0x45); +LPD8RK.hotcues["923e"][5] = new Array("[Sampler1]", "30", 0x92, 0x3e); + +//################## +//preset 4 (group, cuenum, status, ctrl) +//initialize +LPD8RK.hotcues["9330"] = new Array(); +LPD8RK.hotcues["9329"] = new Array(); +LPD8RK.hotcues["932f"] = new Array(); +LPD8RK.hotcues["9328"] = new Array(); +LPD8RK.hotcues["932d"] = new Array(); +LPD8RK.hotcues["9326"] = new Array(); +//bank 1 +LPD8RK.hotcues["9330"][1] = new Array("[Sampler2]", "1", 0x93, 0x30); +LPD8RK.hotcues["9329"][1] = new Array("[Sampler2]", "2", 0x93, 0x29); +LPD8RK.hotcues["932f"][1] = new Array("[Sampler2]", "3", 0x93, 0x2f); +LPD8RK.hotcues["9328"][1] = new Array("[Sampler2]", "4", 0x93, 0x28); +LPD8RK.hotcues["932d"][1] = new Array("[Sampler2]", "5", 0x93, 0x2d); +LPD8RK.hotcues["9326"][1] = new Array("[Sampler2]", "6", 0x93, 0x26); +//bank 2 +LPD8RK.hotcues["9330"][2] = new Array("[Sampler2]", "7", 0x93, 0x30); +LPD8RK.hotcues["9329"][2] = new Array("[Sampler2]", "8", 0x93, 0x29); +LPD8RK.hotcues["932f"][2] = new Array("[Sampler2]", "9", 0x93, 0x2f); +LPD8RK.hotcues["9328"][2] = new Array("[Sampler2]", "10", 0x93, 0x28); +LPD8RK.hotcues["932d"][2] = new Array("[Sampler2]", "11", 0x93, 0x2d); +LPD8RK.hotcues["9326"][2] = new Array("[Sampler2]", "12", 0x93, 0x26); +//bank 3 +LPD8RK.hotcues["9330"][3] = new Array("[Sampler2]", "13", 0x93, 0x30); +LPD8RK.hotcues["9329"][3] = new Array("[Sampler2]", "14", 0x93, 0x29); +LPD8RK.hotcues["932f"][3] = new Array("[Sampler2]", "15", 0x93, 0x2f); +LPD8RK.hotcues["9328"][3] = new Array("[Sampler2]", "16", 0x93, 0x28); +LPD8RK.hotcues["932d"][3] = new Array("[Sampler2]", "17", 0x93, 0x2d); +LPD8RK.hotcues["9326"][3] = new Array("[Sampler2]", "18", 0x93, 0x26); +//bank 4 +LPD8RK.hotcues["9330"][4] = new Array("[Sampler2]", "19", 0x93, 0x30); +LPD8RK.hotcues["9329"][4] = new Array("[Sampler2]", "20", 0x93, 0x29); +LPD8RK.hotcues["932f"][4] = new Array("[Sampler2]", "21", 0x93, 0x2f); +LPD8RK.hotcues["9328"][4] = new Array("[Sampler2]", "22", 0x93, 0x28); +LPD8RK.hotcues["932d"][4] = new Array("[Sampler2]", "23", 0x93, 0x2d); +LPD8RK.hotcues["9326"][4] = new Array("[Sampler2]", "24", 0x93, 0x26); +//bank 5 +LPD8RK.hotcues["9330"][5] = new Array("[Sampler2]", "25", 0x93, 0x30); +LPD8RK.hotcues["9329"][5] = new Array("[Sampler2]", "26", 0x93, 0x29); +LPD8RK.hotcues["932f"][5] = new Array("[Sampler2]", "27", 0x93, 0x2f); +LPD8RK.hotcues["9328"][5] = new Array("[Sampler2]", "28", 0x93, 0x28); +LPD8RK.hotcues["932d"][5] = new Array("[Sampler2]", "29", 0x93, 0x2d); +LPD8RK.hotcues["9326"][5] = new Array("[Sampler2]", "30", 0x93, 0x26); + + + + +//map hotcue loop and leds +LPD8RK.loops = new Array(); +//preset 1 (group, beatloop_len, status, ctrl) +LPD8RK.loops["b09"] = new Array("[Channel1]", "1", 0xB0, 0x09); +LPD8RK.loops["b04"] = new Array("[Channel1]", "2", 0xB0, 0x04); +LPD8RK.loops["b08"] = new Array("[Channel1]", "4", 0xB0, 0x08); +LPD8RK.loops["b03"] = new Array("[Channel1]", "8", 0xB0, 0x03); + +//preset 2 (group, beatloop_len, status, ctrl) +LPD8RK.loops["b19"] = new Array("[Channel2]", "1", 0xB1, 0x09); +LPD8RK.loops["b14"] = new Array("[Channel2]", "2", 0xB1, 0x04); +LPD8RK.loops["b18"] = new Array("[Channel2]", "4", 0xB1, 0x08); +LPD8RK.loops["b13"] = new Array("[Channel2]", "8", 0xB1, 0x03); + +//preset 3 (group, beatloop_len, status, ctrl) +LPD8RK.loops["b29"] = new Array("[Sampler1]", "1", 0xB2, 0x09); +LPD8RK.loops["b24"] = new Array("[Sampler1]", "2", 0xB2, 0x04); +LPD8RK.loops["b28"] = new Array("[Sampler1]", "4", 0xB2, 0x08); +LPD8RK.loops["b23"] = new Array("[Sampler1]", "8", 0xB2, 0x03); + +//preset 4 (group, beatloop_len, status, ctrl) +LPD8RK.loops["b39"] = new Array("[Sampler2]", "1", 0xB3, 0x09); +LPD8RK.loops["b34"] = new Array("[Sampler2]", "2", 0xB3, 0x04); +LPD8RK.loops["b38"] = new Array("[Sampler2]", "4", 0xB3, 0x08); +LPD8RK.loops["b33"] = new Array("[Sampler2]", "8", 0xB3, 0x03); + + + +LPD8RK.init = function (id, debug) { // called when the device is opened & set up + if (LPD8RK.debug){print("###init##############")}; + //soft takeovers + engine.softTakeover("[Master]","crossfader",true); + engine.softTakeover("[Channel1]","volume",true); + engine.softTakeover("[Channel1]","rate",true); + engine.softTakeover("[Channel2]","volume",true); + engine.softTakeover("[Channel2]","rate",true); + engine.softTakeover("[Sampler1]","volume",true); + engine.softTakeover("[Sampler1]","rate",true); + engine.softTakeover("[Sampler2]","volume",true); + engine.softTakeover("[Sampler2]","rate",true); + + //set LED timer + LPD8RK.ledTimer = engine.beginTimer(LPD8RK.LEDinterval, "LPD8RK.setLeds()"); +}; + +LPD8RK.shutdown = function () { + engine.stopTimer(LPD8RK.ledTimer); +}; + +LPD8RK.resetLEDTimer = function () { + engine.stopTimer(LPD8RK.ledTimer); + LPD8RK.setLeds() + LPD8RK.ledTimer = engine.beginTimer(LPD8RK.LEDinterval, "LPD8RK.setLeds()"); +}; + +LPD8RK.setLeds = function () { + //runs repeatedly on a timer set in init() + //has to run on a timer because you apparently can only set LEDs on the current prog selection on the LPD8 + //ie: leds on a PAD or CC other than the one you're currently using can't be set. + //and no midi messages are sent when you change a PROG or pad. No way of telling MIXXX which LEDs are currently active + //so, this runs 4x a second to make sure LEDs are updated. Kludge, but so it goes. + + //hotcues + for (var id in LPD8RK.hotcues){ + for (var bank in LPD8RK.hotcues[id]){ + //iterate through hotcues for current bank, set hotcue leds + var status = LPD8RK.hotcues[id][LPD8RK.hotcueBank][2]; + var ctrl = LPD8RK.hotcues[id][LPD8RK.hotcueBank][3]; + var state = engine.getValue(LPD8RK.hotcues[id][LPD8RK.hotcueBank][0], "hotcue_"+LPD8RK.hotcues[id][LPD8RK.hotcueBank][1]+"_enabled"); + + //if (LPD8RK.debug){print("midi.sendShortMsg("+status+", "+ctrl+", "+state+")")}; + + LPD8RK.lightLED(status, ctrl, state); + }; + }; + + //loops + for (var id in LPD8RK.loops){ + //iterate through hotcues, set hotcue leds + var status = LPD8RK.loops[id][2]; + var ctrl = LPD8RK.loops[id][3]; + var state = engine.getValue(LPD8RK.loops[id][0], "beatloop_"+LPD8RK.loops[id][1]+"_enabled"); + + //if (LPD8RK.debug){print("midi.sendShortMsg("+status+", "+ctrl+", "+state+")")}; + + LPD8RK.lightLED(status, ctrl, state); + }; + + //reloop buttons + LPD8RK.lightLED(0xb0, 0x01, engine.getValue("[Channel1]", "loop_enabled")); + LPD8RK.lightLED(0xb1, 0x01, engine.getValue("[Channel2]", "loop_enabled")); + LPD8RK.lightLED(0xb2, 0x01, engine.getValue("[Sampler1]", "loop_enabled")); + LPD8RK.lightLED(0xb3, 0x01, engine.getValue("[Sampler2]", "loop_enabled")); + }; + +LPD8RK.lightLED = function (status, ctrl, state){ + //function to check for valid LED lighting messages - LPD8 seems to go into a weird nonresponsive mode when some unknown code is sent to it + //don't know what the messed code is, but this function checks for valid LED addresses. Hopefully this will prevent problems. + if (LPD8RK.validLEDS[status][ctrl] !== true){ + print("######## INVALID STATUS ########"); + return false; + } else { + if (state > 0 || state === true){state=1;}//make sure state is valid + midi.sendShortMsg(status, ctrl, state); + } + }; + +LPD8RK.clear = function (){//enables hotcue clearing + if (LPD8RK.debug){print("###hotcueclear##############")}; + LPD8RK.hotcueClear=true; + }; + +LPD8RK.noclear = function (){//disables hotcue clearing + LPD8RK.hotcueClear=false; + }; + +LPD8RK.hotcueButton = function (channel, control, value, status, group) { + //weird status bug workaround + if (channel==0 && status != 0x90){status = 0x90}; + if (channel==1 && status != 0x91){status = 0x91}; + if (channel==2 && status != 0x92){status = 0x92}; + if (channel==3 && status != 0x93){status = 0x93}; + + if (LPD8RK.debug){print("###hotcueButton##############")}; + if (LPD8RK.debug){print("status:"+status)}; + if (LPD8RK.debug){print("channel:"+channel)}; + if (LPD8RK.debug){print("control:"+control)}; + if (LPD8RK.debug){print("hotcuebank:"+LPD8RK.hotcueBank)}; + if (LPD8RK.debug){print("phrase:#"+status.toString(16).toLowerCase()+control.toString(16).toLowerCase()+"#")}; + //activate or clear depending on whether clear button is pressed + var thecue = LPD8RK.hotcues[status.toString(16).toLowerCase()+control.toString(16).toLowerCase()][LPD8RK.hotcueBank]; + if (LPD8RK.hotcueClear){ + engine.setValue(thecue[0], "hotcue_"+thecue[1]+"_clear", 1); + engine.setValue(thecue[0], "hotcue_"+thecue[1]+"_clear", 0); + if (LPD8RK.debug){print("cleared")}; + } else { + engine.setValue(thecue[0], "hotcue_"+thecue[1]+"_activate", 1); + engine.setValue(thecue[0], "hotcue_"+thecue[1]+"_activate", 0); + if (LPD8RK.debug){print("###"+status.toString(16).toLowerCase()+control.toString(16).toLowerCase()+"--activated")}; + }; + + }; + +LPD8RK.loopButton = function (channel, control, value, status, group) { + if (LPD8RK.debug){print(LPD8RK.looplen+"len");} + if (LPD8RK.debug){print(LPD8RK.looptype+"type");} + //activate beatloop + var theloop = LPD8RK.loops[status.toString(16).toLowerCase()+control.toString(16).toLowerCase()]; + if (value>0){//button was pressed + LPD8RK.loopbuttonDown=true; + engine.setValue(group, LPD8RK.looptype+"_"+theloop[1]+"_activate", 1); + } else {//button was released + LPD8RK.loopbuttonDown=false; + }; + + }; + +LPD8RK.reloopButton = function (channel, control, value, status, group) { + if (LPD8RK.debug){print(LPD8RK.looplen+"len");} + if (LPD8RK.debug){print(LPD8RK.looptype+"type");} + + if (value>0){//button was pressed + engine.stopTimer(LPD8RK.reloopTimer); + LPD8RK.loopbuttonDown=true; + LPD8RK.doreloop=true; + LPD8RK.reloopTimer = engine.beginTimer(500, "LPD8RK.disablereloop()", true); + } else {//button was released + LPD8RK.loopbuttonDown=false; + if (LPD8RK.doreloop===true) {engine.setValue(group, "reloop_exit", 1);}; + LPD8RK.doreloop=true; + engine.stopTimer(LPD8RK.reloopTimer); + }; + + }; + +LPD8RK.disablereloop = function () { + //timed function - fires half a second after pressing reloop. Don't do the reloop if you hold down the button (so you can move the loop without exiting) + LPD8RK.doreloop=false; + }; + +LPD8RK.looptypeDial = function (channel, control, value, status, group) { + //activates variable length type depending on dial position + //beatlooproll only works in 1.11 or above - script is a placeholder, knob used to select hotcue bank for now + //if(value>63){LPD8RK.looptype="beatlooproll";}else{LPD8RK.looptype="beatloop";} + //if (LPD8RK.debug){print(LPD8RK.looptype);} + }; + +LPD8RK.resetOldBank = function () { + //clears stored old hotcue bank + LPD8RK.oldHotcueBank=0; + }; + +LPD8RK.hotcueBankDial = function (channel, control, value, status, group) { + //sets which hotcue bank to display (separate this out on dedicated controller) + + //pause LED resets, so bank indicator lights will be visible + engine.stopTimer(LPD8RK.ledTimer); + + //select hotcue bank + if (value>=0 && value <=12){LPD8RK.hotcueBank=1;}; + if (value>12 && value <=46){LPD8RK.hotcueBank=2;}; + if (value>46 && value <=80){LPD8RK.hotcueBank=3;}; + if (value>80 && value <=114){LPD8RK.hotcueBank=4;}; + if (value>114 && value <=128){LPD8RK.hotcueBank=5;}; + + //light up indicator light + if (LPD8RK.oldHotcueBank != LPD8RK.hotcueBank){//check if the bank's changed. If it has, change the LEDs - LPD8RK.oldHotcueBank != LPD8RK.hotcueBank + for (var id in LPD8RK.hotcues){ + for (var bank in LPD8RK.hotcues[id][1]){ + var status = LPD8RK.hotcues[id][1][2]; + var ctrl = LPD8RK.hotcues[id][1][3]; + //find bank number indicator light + if (LPD8RK.hotcues[id][1][1]==LPD8RK.hotcueBank){ + var state = 1; + }else{ + var state = 0; + }; + + LPD8RK.lightLED(status, ctrl, state); + }; + }; + }; + //record last hotcue bank + LPD8RK.oldHotcueBank=LPD8RK.hotcueBank; + //set timer to clear old bank number after 500 msec, so bank indicator light will light up + engine.stopTimer(LPD8RK.oldbanktimer); + LPD8RK.oldbanktimer = engine.beginTimer(500, "LPD8RK.resetOldBank()", true); + + //set timer to restart LED updates in 500 msec + engine.stopTimer(LPD8RK.LEDPauseTimer); + LPD8RK.LEDPauseTimer = engine.beginTimer(LPD8RK.LEDinterval, "LPD8RK.resetLEDTimer()", true); + }; + +LPD8RK.looplenDial = function (channel, control, value, status, group) { + //activates variable length loop depending on dial position + LPD8RK.looplen=value; + + if (LPD8RK.loopbuttonDown !== true){return false;}//exit if no loop button down + else if (LPD8RK.looplen<=0x12){engine.setValue(group, LPD8RK.looptype+"_0.0625_activate", .0625);return true;} else + if (LPD8RK.looplen<=0x25){engine.setValue(group, LPD8RK.looptype+"_0.125_activate", .125);return true;} else + if (LPD8RK.looplen<=0x37){engine.setValue(group, LPD8RK.looptype+"_0.25_activate", .25);return true;} else + if (LPD8RK.looplen<=0x49){engine.setValue(group, LPD8RK.looptype+"_0.5_activate", .5);return true;} else + if (LPD8RK.looplen<=0x5b){engine.setValue(group, LPD8RK.looptype+"_1_activate", 1);return true;} else + if (LPD8RK.looplen<=0x6d){engine.setValue(group, LPD8RK.looptype+"_2_activate", 2);return true;} else + if (LPD8RK.looplen<=0x70){engine.setValue(group, LPD8RK.looptype+"_4_activate", 4);return true;} else + if (LPD8RK.looplen<=0x7f){engine.setValue(group, LPD8RK.looptype+"_8_activate", 8);return true;}; + }; + +LPD8RK.loopminus = function (channel, control, value, status, group) { + //shrinks loop or moves loop back + if (LPD8RK.loopbuttonDown !== true){engine.setValue(group, "loop_halve", 1);engine.setValue(group, "loop_halve", 0); return false;}//shrink loop if no loop button down + else if (engine.getValue(group, "loop_start_position")>=0 && engine.getValue(group, "loop_end_position")>=0 ){ + //move loop + var interval = LPD8RK.loopmove*engine.getValue(group, "track_samples")/engine.getValue(group, "duration"); + var start = engine.getValue(group, "loop_start_position"); + var end = engine.getValue(group, "loop_end_position"); + engine.setValue(group, "loop_start_position", start-interval); + engine.setValue(group, "loop_end_position", end-interval); + return true; + }; + }; + +LPD8RK.loopplus = function (channel, control, value, status, group) { + //grows loop or moves loop forward + if (LPD8RK.loopbuttonDown !== true){engine.setValue(group, "loop_double", 1); engine.setValue(group, "loop_double", 0); return false;}//shrink loop if no loop button down + else if (engine.getValue(group, "loop_start_position")>=0 && engine.getValue(group, "loop_end_position")>=0 ){ + //move loop + var interval = LPD8RK.loopmove*engine.getValue(group, "track_samples")/engine.getValue(group, "duration"); + var start = engine.getValue(group, "loop_start_position"); + var end = engine.getValue(group, "loop_end_position"); + engine.setValue(group, "loop_start_position", start+interval); + engine.setValue(group, "loop_end_position", end+interval); + return true; + }; + }; + +LPD8RK.beatjump = function (channel, control, value, status, group) { + //jumps back certain number of beats depending on knob modifier + var curpos = engine.getValue(group, "playposition")*engine.getValue(group, "track_samples"); + var numbeats = LPD8RK.beatjumpstep; + var backseconds = numbeats*(1/(engine.getValue(group, "bpm")/60)); + var backsamples = backseconds*engine.getValue(group, "track_samples")/engine.getValue(group, "duration"); + var newpos = curpos-(backsamples+engine.getValue("Master", "latency")); + + if (LPD8RK.debug){print("backseconds: "+backseconds);} + if (LPD8RK.debug){print("backsamples: "+backsamples);} + if (LPD8RK.debug){print("curpos: "+curpos);} + if (LPD8RK.debug){print("newpos: "+newpos);} + if (LPD8RK.debug){print("numbeats: "+numbeats);} + + engine.setValue(group, "playposition", newpos/engine.getValue(group, "track_samples")); + }; + +LPD8RK.beatjumpDial = function (channel, control, value, status, group) { + //activates variable length loop depending on dial position + if(value>=0 && value <=127){ + if (value<=1){LPD8RK.beatjumpstep=.25; return true;} else + if (value<=31){LPD8RK.beatjumpstep=.5; return true;} else + if (value<=63){LPD8RK.beatjumpstep=1; return true;} else + if (value<=94){LPD8RK.beatjumpstep=2; return true;} else + if (value<=125){LPD8RK.beatjumpstep=4; return true;} else + if (value<=127){LPD8RK.beatjumpstep=8; return true;}; + }; + }; + +LPD8RK.mute = function (group) { + //toggles mute, then returns to previous volume + storedvol=LPD8RK.vol[group]; + curvol=engine.getValue(group, "volume"); + engine.softTakeover(group,"volume",false); + if (curvol==0){//is muted. unmute. + engine.setValue(group, "volume", storedvol); + }else{//is not muted. mute. + engine.setValue(group, "volume", 0); + LPD8RK.vol[group]=curvol; + }; + engine.softTakeover(group,"volume",true); + + if (LPD8RK.debug){print("MUTE");} + }; + +LPD8RK.progChng = function (channel, control, value, status, group) { + if (LPD8RK.debug){print("###PROG CHANGE###");} + //workaround because prog chng buttons don't seem to like to work unless they're linked to scripts + if (control==0x07){LPD8RK.toggleplay(group, engine.getValue(group, "play")); return true;} else + if (control==0x03){engine.setValue(group, "cue_default", true); engine.setValue(group, "cue_default", false); return true;} else + if (control==0x06){engine.setValue(group, "beatsync", true); engine.setValue(group, "beatsync", false); return true;} else + if (control==0x02){LPD8RK.togglepfl(group, engine.getValue(group, "pfl")); return true;} else + if (control==0x05){LPD8RK.togglereverse(group, engine.getValue(group, "reverse")); return true;} else + if (control==0x04){LPD8RK.toggleback(group, engine.getValue(group, "back")); return true;} else + if (control==0x00){LPD8RK.togglefwd(group, engine.getValue(group, "fwd")); return true;} + if (control==0x01){LPD8RK.mute(group); return true;} + }; + +LPD8RK.toggleplay = function (group, state) { + if (state==true){engine.setValue(group, "reverse",0);engine.setValue(group, "play", false);} else {engine.setValue(group, "reverse",0);engine.setValue(group, "play", true);}; + }; + +LPD8RK.togglepfl = function (group, state) { + if (state==true){engine.setValue(group, "pfl", false);} else {engine.setValue(group, "pfl", true);}; + }; + +LPD8RK.togglereverse = function (group, state) { + if (state==true){engine.setValue(group, "reverse", false);} else {engine.setValue(group, "reverse", true);}; + }; + +LPD8RK.toggleback = function (group, state) { + if (state==true){engine.setValue(group, "back", false);} else {engine.setValue(group, "back", true);}; + }; + +LPD8RK.togglefwd = function (group, state) { + if (state==true){engine.setValue(group, "fwd", false);} else {engine.setValue(group, "fwd", true);}; + }; + +LPD8RK.softXfade = function (channel, control, value, status, group) { + engine.setValue(group, "crossfader", (value/64)-1); + }; + +LPD8RK.softVolume = function (channel, control, value, status, group) { + engine.setValue(group, "volume", (value/127)); + }; + +LPD8RK.softRate = function (channel, control, value, status, group) { + engine.setValue(group, "rate", (value/64)-1); + }; + + +LPD8RK.test = function (channel, control, value, status, group) { + print("channel: "+channel); + print("control: "+control.toString(16)); + print("value: "+value); + print("status: "+status); + print("group: "+group); + print("test: ##"+status.toString(16)+control.toString(16)+"##"); + print("loopbuttondown: ##"+LPD8RK.loopbuttonDown+"##"); + print("LPD8RK.looplen: ##"+LPD8RK.looplen+"##"); + print("LPD8RK.looplen.tostring: ##"+LPD8RK.looplen.toString(16)+"##"); + print("LPD8RK.looptype: ##"+LPD8RK.looptype+"##"); + print("test: ##"+2+"##"); + }; + + diff -Nru mixxx-1.10.1-1/res/controllers/Akai-LPD8-RK.midi.xml mixxx-1.11.0-bzr3863/res/controllers/Akai-LPD8-RK.midi.xml --- mixxx-1.10.1-1/res/controllers/Akai-LPD8-RK.midi.xml 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/res/controllers/Akai-LPD8-RK.midi.xml 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,1298 @@ + + + + Akai LPD8 - RK + Rob K + This is a mapping for an Akai LPD8. Provides access to transport controls, 30 hotcues, loop controls, basic beat jumping, for two decks and two samplers. Prog 1 = Deck 1; Prog 2 = Deck 2; Prog 3 = Sampler 1; Prog 4 = Sampler 4. PAD controls hotcues, CC controls Loops, PROG CHNG provides transport controls. Intended for use as a supplementary controller on top of a standard DJ controller to give access to more hotcues, etc. but could be used as a standalone controller in a pinch. Created Jan 1, 2013 + http://mixxx.org/forums/viewtopic.php?f=7&t=4477 + + + + + + + + + + + [Channel1] + LPD8RK.softVolume + 0xB0 + 0x65 + + + + + + [Master] + LPD8RK.softXfade + 0xB0 + 0x66 + + + + + + [Master] + headVolume + 0xB0 + 0x67 + + + + + + [Master] + headMix + 0xB0 + 0x68 + + + + + + [Channel1] + LPD8RK.softRate + 0xB0 + 0x69 + + + + + + [Channel1] + LPD8RK.beatjumpDial + 0xB0 + 0x6A + + + + + + [Channel1] + LPD8RK.hotcueBankDial + 0xB0 + 0x6B + + + + + + [Channel1] + LPD8RK.looplenDial + 0xB0 + 0x6C + + + + + + + + + + + + [Channel1] + LPD8RK.hotcueButton + 0x90 + 0x2B + + + + + + [Channel1] + LPD8RK.hotcueButton + 0x90 + 0x2A + + + + + + [Channel1] + LPD8RK.hotcueButton + 0x90 + 0x29 + + + + + + [Channel1] + LPD8RK.hotcueButton + 0x90 + 0x27 + + + + + + [Channel1] + LPD8RK.hotcueButton + 0x90 + 0x26 + + + + + + [Channel1] + LPD8RK.hotcueButton + 0x90 + 0x25 + + + + + + [Channel1] + LPD8RK.beatjump + 0x90 + 0x28 + + + + + + [Channel1] + LPD8RK.clear + 0x90 + 0x24 + + + + + + [Channel1] + LPD8RK.noclear + 0x80 + 0x24 + + + + + + + + + + + + [Channel1] + LPD8RK.loopButton + 0xB0 + 0x09 + + + + + + [Channel1] + LPD8RK.loopButton + 0xB0 + 0x08 + + + + + + [Channel1] + LPD8RK.loopButton + 0xB0 + 0x04 + + + + + + [Channel1] + LPD8RK.loopButton + 0xB0 + 0x03 + + + + + + [Channel1] + LPD8RK.loopminus + 0xB0 + 0x06 + + + + + + [Channel1] + LPD8RK.loopplus + 0xB0 + 0x02 + + + + + + [Channel1] + LPD8RK.beatjump + 0xB0 + 0x05 + + + + + + [Channel1] + LPD8RK.reloopButton + 0xB0 + 0x01 + + + + + + + + + + + [Channel1] + LPD8RK.progChng + 0xC0 + 0x07 + + + + + + [Channel1] + LPD8RK.progChng + 0xC0 + 0x03 + + + + + + [Channel1] + LPD8RK.progChng + 0xC0 + 0x06 + + + + + + [Channel1] + LPD8RK.progChng + 0xC0 + 0x02 + + + + + + [Channel1] + LPD8RK.progChng + 0xC0 + 0x05 + + + + + + [Channel1] + LPD8RK.progChng + 0xC0 + 0x01 + + + + + + [Channel1] + LPD8RK.progChng + 0xC0 + 0x04 + + + + + + [Channel1] + LPD8RK.progChng + 0xC0 + 0x00 + + + + + + + + + + [Channel2] + LPD8RK.softVolume + 0xB1 + 0x65 + + + + + + [Master] + LPD8RK.softXfade + 0xB1 + 0x66 + + + + + + [Master] + headVolume + 0xB1 + 0x67 + + + + + + [Master] + headMix + 0xB1 + 0x68 + + + + + + [Channel2] + LPD8RK.softRate + 0xB1 + 0x69 + + + + + + [Channel2] + LPD8RK.beatjumpDial + 0xB1 + 0x6A + + + + + + [Channel2] + LPD8RK.hotcueBankDial + 0xB1 + 0x6B + + + + + + [Channel2] + LPD8RK.looplenDial + 0xB1 + 0x6C + + + + + + + + + + + + [Channel2] + LPD8RK.hotcueButton + 0x91 + 0x2C + + + + + + [Channel2] + LPD8RK.hotcueButton + 0x91 + 0x27 + + + + + + [Channel2] + LPD8RK.hotcueButton + 0x91 + 0x2e + + + + + + [Channel2] + LPD8RK.hotcueButton + 0x91 + 0x2a + + + + + + [Channel2] + LPD8RK.hotcueButton + 0x91 + 0x26 + + + + + + [Channel2] + LPD8RK.hotcueButton + 0x91 + 0x24 + + + + + + [Channel2] + LPD8RK.beatjump + 0x91 + 0x25 + + + + + + [Channel2] + LPD8RK.clear + 0x91 + 0x23 + + + + + + [Channel2] + LPD8RK.noclear + 0x81 + 0x23 + + + + + + + + + + + + [Channel2] + LPD8RK.loopButton + 0xB1 + 0x09 + + + + + + [Channel2] + LPD8RK.loopButton + 0xB1 + 0x08 + + + + + + [Channel2] + LPD8RK.loopButton + 0xB1 + 0x04 + + + + + + [Channel2] + LPD8RK.loopButton + 0xB1 + 0x03 + + + + + + [Channel2] + LPD8RK.loopminus + 0xB1 + 0x06 + + + + + + [Channel2] + LPD8RK.loopplus + 0xB1 + 0x02 + + + + + + [Channel2] + LPD8RK.beatjump + 0xB1 + 0x05 + + + + + + [Channel2] + LPD8RK.reloopButton + 0xB1 + 0x01 + + + + + + + + + + + [Channel2] + LPD8RK.progChng + 0xC1 + 0x07 + + + + + + [Channel2] + LPD8RK.progChng + 0xC1 + 0x03 + + + + + + [Channel2] + LPD8RK.progChng + 0xC1 + 0x06 + + + + + + [Channel2] + LPD8RK.progChng + 0xC1 + 0x02 + + + + + + [Channel2] + LPD8RK.progChng + 0xC1 + 0x05 + + + + + + [Channel2] + LPD8RK.progChng + 0xC1 + 0x01 + + + + + + [Channel2] + LPD8RK.progChng + 0xC1 + 0x04 + + + + + + [Channel2] + LPD8RK.progChng + 0xC1 + 0x00 + + + + + + + + + + + + [Sampler1] + LPD8RK.softVolume + 0xB2 + 0x65 + + + + + + [Master] + LPD8RK.softXfade + 0xB2 + 0x66 + + + + + + [Master] + headVolume + 0xB2 + 0x67 + + + + + + [Master] + headMix + 0xB2 + 0x68 + + + + + + [Sampler1] + LPD8RK.softRate + 0xB2 + 0x69 + + + + + + [Sampler1] + LPD8RK.beatjumpDial + 0xB2 + 0x6A + + + + + + [Sampler1] + LPD8RK.hotcueBankDial + 0xB2 + 0x6B + + + + + + [Sampler1] + LPD8RK.looplenDial + 0xB2 + 0x6C + + + + + + + + + + + + [Sampler1] + LPD8RK.hotcueButton + 0x92 + 0x48 + + + + + + [Sampler1] + LPD8RK.hotcueButton + 0x92 + 0x41 + + + + + + [Sampler1] + LPD8RK.hotcueButton + 0x92 + 0x47 + + + + + + [Sampler1] + LPD8RK.hotcueButton + 0x92 + 0x40 + + + + + + [Sampler1] + LPD8RK.hotcueButton + 0x92 + 0x45 + + + + + + [Sampler1] + LPD8RK.hotcueButton + 0x92 + 0x3e + + + + + + [Sampler1] + LPD8RK.beatjump + 0x92 + 0x43 + + + + + + [Sampler1] + LPD8RK.clear + 0x92 + 0x3c + + + + + + [Sampler1] + LPD8RK.noclear + 0x82 + 0x3c + + + + + + + + + + + + [Sampler1] + LPD8RK.loopButton + 0xB2 + 0x09 + + + + + + [Sampler1] + LPD8RK.loopButton + 0xB2 + 0x08 + + + + + + [Sampler1] + LPD8RK.loopButton + 0xB2 + 0x04 + + + + + + [Sampler1] + LPD8RK.loopButton + 0xB2 + 0x03 + + + + + + [Sampler1] + LPD8RK.loopminus + 0xB2 + 0x06 + + + + + + [Sampler1] + LPD8RK.loopplus + 0xB2 + 0x02 + + + + + + [Sampler1] + LPD8RK.beatjump + 0xB2 + 0x05 + + + + + + [Sampler1] + LPD8RK.reloopButton + 0xB2 + 0x01 + + + + + + + + + + + [Sampler1] + LPD8RK.progChng + 0xC2 + 0x07 + + + + + + [Sampler1] + LPD8RK.progChng + 0xC2 + 0x03 + + + + + + [Sampler1] + LPD8RK.progChng + 0xC2 + 0x06 + + + + + + [Sampler1] + LPD8RK.progChng + 0xC2 + 0x02 + + + + + + [Sampler1] + LPD8RK.progChng + 0xC2 + 0x05 + + + + + + [Sampler1] + LPD8RK.progChng + 0xC2 + 0x01 + + + + + + [Sampler1] + LPD8RK.progChng + 0xC2 + 0x04 + + + + + + [Sampler1] + LPD8RK.progChng + 0xC2 + 0x00 + + + + + + + + + + + + [Sampler2] + LPD8RK.softVolume + 0xb3 + 0x65 + + + + + + [Master] + LPD8RK.softXfade + 0xb3 + 0x66 + + + + + + [Master] + headVolume + 0xb3 + 0x67 + + + + + + [Master] + headMix + 0xb3 + 0x68 + + + + + + [Sampler2] + LPD8RK.softRate + 0xb3 + 0x69 + + + + + + [Sampler2] + LPD8RK.beatjumpDial + 0xb3 + 0x6A + + + + + + [Sampler2] + LPD8RK.hotcueBankDial + 0xb3 + 0x6B + + + + + + [Sampler2] + LPD8RK.looplenDial + 0xb3 + 0x6C + + + + + + + + + + + + [Sampler2] + LPD8RK.hotcueButton + 0x93 + 0x30 + + + + + + [Sampler2] + LPD8RK.hotcueButton + 0x93 + 0x29 + + + + + + [Sampler2] + LPD8RK.hotcueButton + 0x93 + 0x2f + + + + + + [Sampler2] + LPD8RK.hotcueButton + 0x93 + 0x28 + + + + + + [Sampler2] + LPD8RK.hotcueButton + 0x93 + 0x2d + + + + + + [Sampler2] + LPD8RK.hotcueButton + 0x93 + 0x26 + + + + + + [Sampler2] + LPD8RK.beatjump + 0x93 + 0x2b + + + + + + [Sampler2] + LPD8RK.clear + 0x93 + 0x24 + + + + + + [Sampler2] + LPD8RK.noclear + 0x83 + 0x24 + + + + + + + + + + + + [Sampler2] + LPD8RK.loopButton + 0xb3 + 0x09 + + + + + + [Sampler2] + LPD8RK.loopButton + 0xb3 + 0x08 + + + + + + [Sampler2] + LPD8RK.loopButton + 0xb3 + 0x04 + + + + + + [Sampler2] + LPD8RK.loopButton + 0xb3 + 0x03 + + + + + + [Sampler2] + LPD8RK.loopminus + 0xb3 + 0x06 + + + + + + [Sampler2] + LPD8RK.loopplus + 0xb3 + 0x02 + + + + + + [Sampler2] + LPD8RK.beatjump + 0xb3 + 0x05 + + + + + + [Sampler2] + LPD8RK.reloopButton + 0xb3 + 0x01 + + + + + + + + + + + [Sampler2] + LPD8RK.progChng + 0xC3 + 0x07 + + + + + + [Sampler2] + LPD8RK.progChng + 0xC3 + 0x03 + + + + + + [Sampler2] + LPD8RK.progChng + 0xC3 + 0x06 + + + + + + [Sampler2] + LPD8RK.progChng + 0xC3 + 0x02 + + + + + + [Sampler2] + LPD8RK.progChng + 0xC3 + 0x05 + + + + + + [Sampler2] + LPD8RK.progChng + 0xC3 + 0x01 + + + + + + [Sampler2] + LPD8RK.progChng + 0xC3 + 0x04 + + + + + + [Sampler2] + LPD8RK.progChng + 0xC3 + 0x00 + + + + + + + + + + + + + + diff -Nru mixxx-1.10.1-1/res/controllers/American Audio RADIUS 2000 CH1.midi.xml mixxx-1.11.0-bzr3863/res/controllers/American Audio RADIUS 2000 CH1.midi.xml --- mixxx-1.10.1-1/res/controllers/American Audio RADIUS 2000 CH1.midi.xml 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/res/controllers/American Audio RADIUS 2000 CH1.midi.xml 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,303 @@ + + + American Audio Radius 2000 CH1 + Markus Steinbauer + American Audio Radius 2000 mapping for Deck 1 + + + + + + + + 0xB0 + 0x38 + [Playlist] + RADIUS2000.trackSearch + + + + + + 0xB0 + 0x36 + [Playlist] + RADIUS2000.menuSearch + + + + + + 0x90 + 0x30 + [Channel1] + RADIUS2000.cue + + + + + + 0x90 + 0x26 + [Channel1] + RADIUS2000.wheelTouch + + + + + + 0xB0 + 0x35 + [Channel1] + RADIUS2000.wheelTurn + + + + + + 0x90 + 0x2a + [Channel1] + RADIUS2000.play + + + + + + 0x90 + 0x06 + [Channel1] + RADIUS2000.keylock + + + + + + 0x90 + 0x0C + [Channel1] + RADIUS2000.pitchRateRange + + + + + + 0x90 + 0x01 + [Channel1] + RADIUS2000.pitchRate + + + + + + 0x90 + 0x2D + [Channel1] + RADIUS2000.flanger + + + + + + 0xB0 + 0x18 + [Channel1] + RADIUS2000.flangerDelay + + + + + + 0x90 + 0x07 + [Channel1] + rate_temp_down + + + + + + 0x90 + 0x0D + [Channel1] + rate_temp_up + + + + + + 0x90 + 0x2 + [Channel1] + beatloop_4 + + + + + + 0x90 + 0x4 + [Channel1] + reverse + + + + + + 0x90 + 0x5 + [Channel1] + loop_out + + + + + + 0x90 + 0x8 + [Channel1] + loop_double + + + + + + 0x90 + 0x1F + [Channel1] + LoadSelectedTrack + + + + + + 0x90 + 0xa + [Channel1] + hotcue_3_activate + + + + + + 0x90 + 0xb + [Channel1] + loop_in + + + + + + 0xe0 + 0x46 + [Channel1] + rate + + + + + + 0x90 + 0xe + [Channel1] + loop_halve + + + + + + 0x90 + 0x10 + [Channel1] + hotcue_2_activate + + + + + + 0x90 + 0x11 + [Channel1] + back + + + + + + 0x90 + 0x12 + [Channel1] + beatsync + + + + + + 0x90 + 0x13 + [Channel1] + LoadSelectedTrack + + + + + + 0x90 + 0x16 + [Channel1] + hotcue_1_activate + + + + + + 0x90 + 0x17 + [Channel1] + reloop_exit + + + + + + 0x90 + 0x1d + [Playlist] + SelectNextTrack + + + + + + 0x90 + 0x22 + [Channel1] + hotcue_4_activate + + + + + + 0x90 + 0x23 + [Channel1] + fwd + + + + + + 0x90 + 0x29 + [Playlist] + SelectPrevTrack + + + + + + + + diff -Nru mixxx-1.10.1-1/res/controllers/American Audio RADIUS 2000 CH2.midi.xml mixxx-1.11.0-bzr3863/res/controllers/American Audio RADIUS 2000 CH2.midi.xml --- mixxx-1.10.1-1/res/controllers/American Audio RADIUS 2000 CH2.midi.xml 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/res/controllers/American Audio RADIUS 2000 CH2.midi.xml 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,303 @@ + + + American Audio Radius 2000 CH2 + Markus Steinbauer + American Audio Radius 2000 mapping for Deck 2 + + + + + + + + 0xB0 + 0x38 + [Playlist] + RADIUS2000.trackSearch + + + + + + 0xB0 + 0x36 + [Playlist] + RADIUS2000.menuSearch + + + + + + 0x90 + 0x30 + [Channel2] + RADIUS2000.cue + + + + + + 0x90 + 0x26 + [Channel2] + RADIUS2000.wheelTouch + + + + + + 0xB0 + 0x35 + [Channel2] + RADIUS2000.wheelTurn + + + + + + 0x90 + 0x2a + [Channel2] + RADIUS2000.play + + + + + + 0x90 + 0x06 + [Channel2] + RADIUS2000.keylock + + + + + + 0x90 + 0x0C + [Channel2] + RADIUS2000.pitchRateRange + + + + + + 0x90 + 0x01 + [Channel2] + RADIUS2000.pitchRate + + + + + + 0x90 + 0x2D + [Channel2] + RADIUS2000.flanger + + + + + + 0xB0 + 0x18 + [Channel2] + RADIUS2000.flangerDelay + + + + + + 0x90 + 0x07 + [Channel2] + rate_temp_down + + + + + + 0x90 + 0x0D + [Channel2] + rate_temp_up + + + + + + 0x90 + 0x2 + [Channel2] + beatloop_4 + + + + + + 0x90 + 0x4 + [Channel2] + reverse + + + + + + 0x90 + 0x5 + [Channel2] + loop_out + + + + + + 0x90 + 0x8 + [Channel2] + loop_double + + + + + + 0x90 + 0x1F + [Channel2] + LoadSelectedTrack + + + + + + 0x90 + 0xa + [Channel2] + hotcue_3_activate + + + + + + 0x90 + 0xb + [Channel2] + loop_in + + + + + + 0xe0 + 0x46 + [Channel2] + rate + + + + + + 0x90 + 0xe + [Channel2] + loop_halve + + + + + + 0x90 + 0x10 + [Channel2] + hotcue_2_activate + + + + + + 0x90 + 0x11 + [Channel2] + back + + + + + + 0x90 + 0x12 + [Channel2] + beatsync + + + + + + 0x90 + 0x13 + [Channel2] + LoadSelectedTrack + + + + + + 0x90 + 0x16 + [Channel2] + hotcue_1_activate + + + + + + 0x90 + 0x17 + [Channel2] + reloop_exit + + + + + + 0x90 + 0x1d + [Playlist] + SelectNextTrack + + + + + + 0x90 + 0x22 + [Channel2] + hotcue_4_activate + + + + + + 0x90 + 0x23 + [Channel2] + fwd + + + + + + 0x90 + 0x29 + [Playlist] + SelectPrevTrack + + + + + + + + diff -Nru mixxx-1.10.1-1/res/controllers/American Audio VMS2.midi.xml mixxx-1.11.0-bzr3863/res/controllers/American Audio VMS2.midi.xml --- mixxx-1.10.1-1/res/controllers/American Audio VMS2.midi.xml 1970-01-01 00:00:00.000000000 +0000 +++ mixxx-1.11.0-bzr3863/res/controllers/American Audio VMS2.midi.xml 2013-05-09 13:58:23.000000000 +0000 @@ -0,0 +1,2523 @@ + + + American Audio VMS2 + Groschi + American Audio VMS2 preset based on the American Audio VMS4 preset. + http://www.mixxx.org/forums/viewtopic.php?f=7&t=3202 + + + + + + + + 0xb0 + 0x31 + [Channel1] + VMS4.jog_move_msb + + + + + + + 0x90 + 0x11 + [Channel1] + beatsync + + +